package main import ( "log" "time" "github.com/gdamore/tcell/v2" ) func initilize() (tcell.Screen, tcell.Style, error) { style := tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset) var err error screen, err := tcell.NewScreen() if err != nil { log.Println("Error creating screen: ", err) } err = screen.Init() if err != nil { log.Fatalln("Error initializing screen: ", err) } return screen, style, err } func quit(screen tcell.Screen) { maybePanic := recover() screen.Fini() if maybePanic != nil { panic(maybePanic) } } func gameDirector(screen tcell.Screen, style tcell.Style, keypresses chan int, gamestate chan int) { // Destined to die, even before I was born. defer quit(screen) var score int = 0 var scoreCounter int = 1 // Board size var screenx = 80 var screeny = 24 // Have snake start at the center of the board var snakex int = (screenx / 2) - 1 var snakey int = (screeny / 2) - 1 // Last direction we went in var lastpress int = 1 var snake Snake = initSnake(&snakex, &snakey) var apple Apple = placeApple(&snake) for { // Take input or sleep select { case press := <-keypresses: if validateDirection(&snake, press) { snakeDirection(press, &snake) lastpress = press } case <-time.After(500 * time.Millisecond): snakeDirection(lastpress, &snake) } if snake.head.x == apple.x && snake.head.y == apple.y { apple = placeApple(&snake) score += scoreCounter scoreCounter++ snake.length = 3 + score } // Call it quits once the snake hits the border. if snake.head.x == 0 || snake.head.x == screenx-1 { close(gamestate) return } else if snake.head.y == 0 || snake.head.y == screeny-1 { close(gamestate) return } // Check if head intersects with any parts of the body if hitsTail(&snake, snake.head.x, snake.head.y) { close(gamestate) return } // Clean the screen screen.Clear() // Draw the screen drawBox(screen, style, 0, 0, screenx-1, screeny-1) //drawCoords(screen, style, &snake) drawApple(screen, style, &apple) drawSnake(screen, style, &snake) drawScore(screen, style, score) // Draw the screen screen.Show() } } func keyboardProcessor(screen tcell.Screen, keypresses chan int, gamestate chan int) { defer close(keypresses) for { // Poll for an event ev := screen.PollEvent() // Fetch the type, and check if any other actions are required. switch ev := ev.(type) { case *tcell.EventKey: if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC { return } else if ev.Rune() == 'q' || ev.Rune() == 'Q' { return } else if ev.Key() == tcell.KeyCtrlL { screen.Sync() } else if ev.Rune() == 'C' || ev.Rune() == 'c' { screen.Clear() } else if ev.Key() == tcell.KeyLeft { keypresses <- Left } else if ev.Key() == tcell.KeyRight { keypresses <- Right } else if ev.Key() == tcell.KeyDown { keypresses <- Down } else if ev.Key() == tcell.KeyUp { keypresses <- Up } } // This function needs to know if the game is over. select { case <-time.After(10 * time.Millisecond): case _, ok := <-gamestate: if !ok { return } } } }