snake/game.go

148 lines
3.1 KiB
Go
Raw Permalink Normal View History

2023-11-02 14:20:33 +01:00
package main
import (
"log"
"time"
2023-11-06 22:36:47 +01:00
"github.com/gdamore/tcell/v2"
)
2023-11-02 14:20:33 +01:00
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)
2023-11-12 16:57:52 +01:00
// Board size
var screenx = 80
var screeny = 24
2023-11-12 16:57:52 +01:00
// Last direction we went in
var lastpress int = 1
var snake Snake = initSnake((screenx/2)-1, (screeny/2)-1)
2023-11-23 22:36:44 +01:00
var apple Apple = placeApple(&snake)
2023-11-12 16:57:52 +01:00
for {
// Take input or sleep
select {
case press := <-keypresses:
if validateDirection(&snake, press) {
snakeDirection(press, &snake)
lastpress = press
}
case <-time.After(500 * time.Millisecond):
2023-11-23 22:36:44 +01:00
snakeDirection(lastpress, &snake)
}
2023-11-23 22:36:44 +01:00
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
2023-11-12 16:57:52 +01:00
}
2023-11-12 16:01:47 +01:00
// Call it quits once the snake hits the border.
2023-11-23 22:36:44 +01:00
if snake.head.x == 0 || snake.head.x == screenx-1 {
score.reason = 2
close(gamestate)
return
2023-11-23 22:36:44 +01:00
} else if snake.head.y == 0 || snake.head.y == screeny-1 {
score.reason = 2
2023-11-23 22:36:44 +01:00
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
2023-11-23 22:36:44 +01:00
drawBox(screen, style, 0, 0, screenx-1, screeny-1)
2023-11-24 00:08:13 +01:00
//drawCoords(screen, style, &snake)
2023-11-23 22:36:44 +01:00
drawApple(screen, style, &apple)
drawSnake(screen, style, &snake)
2023-11-12 16:57:52 +01:00
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
2023-11-06 23:43:45 +01:00
} 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
}
}
}
}