snake/game.go

148 lines
3.1 KiB
Go

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, score *Score) {
// Destined to die, even before I was born.
defer quit(screen)
// Board size
var screenx = 80
var screeny = 24
// Last direction we went in
var lastpress int = 1
var snake Snake = initSnake((screenx/2)-1, (screeny/2)-1)
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.score += score.scoreCounter
score.scoreCounter++
snake.length = 3 + score.score
}
// Call it quits once the snake hits the border.
if snake.head.x == 0 || snake.head.x == screenx-1 {
score.reason = 2
close(gamestate)
return
} else if snake.head.y == 0 || snake.head.y == screeny-1 {
score.reason = 2
close(gamestate)
return
}
// Check if head intersects with any parts of the body
if hitsTail(&snake, snake.head.x, snake.head.y) {
score.reason = 3
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, score *Score) {
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 {
score.reason = 1
return
} else if ev.Rune() == 'q' || ev.Rune() == 'Q' {
score.reason = 1
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
}
}
}
}