Compare commits

..

4 Commits

7 changed files with 118 additions and 23 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
builds

5
build.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
mkdir -p builds
go tool dist list | grep -v android | grep -v darwin | grep -v ios | grep -v wasip1 | awk -F '/' '{printf "echo Compiling %s/%s; env CGO_ENABLED=1 GOOS=%s GOARCH=%s go build -o builds/snake.%s-%s\n",$1,$2,$1,$2,$1,$2 }' | sh

26
game.go
View File

@ -31,26 +31,19 @@ func quit(screen tcell.Screen) {
} }
} }
func gameDirector(screen tcell.Screen, style tcell.Style, keypresses chan int, gamestate chan int) { func gameDirector(screen tcell.Screen, style tcell.Style, keypresses chan int, gamestate chan int, score *Score) {
// Destined to die, even before I was born. // Destined to die, even before I was born.
defer quit(screen) defer quit(screen)
var score int = 0
var scoreCounter int = 1
// Board size // Board size
var screenx = 80 var screenx = 80
var screeny = 24 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 // Last direction we went in
var lastpress int = 1 var lastpress int = 1
var snake Snake = initSnake(&snakex, &snakey) var snake Snake = initSnake((screenx/2)-1, (screeny/2)-1)
var apple Apple = placeApple(&snake) var apple Apple = placeApple(&snake)
for { for {
@ -68,22 +61,25 @@ func gameDirector(screen tcell.Screen, style tcell.Style, keypresses chan int, g
if snake.head.x == apple.x && snake.head.y == apple.y { if snake.head.x == apple.x && snake.head.y == apple.y {
apple = placeApple(&snake) apple = placeApple(&snake)
score += scoreCounter score.score += score.scoreCounter
scoreCounter++ score.scoreCounter++
snake.length = 3 + score snake.length = 3 + score.score
} }
// Call it quits once the snake hits the border. // Call it quits once the snake hits the border.
if snake.head.x == 0 || snake.head.x == screenx-1 { if snake.head.x == 0 || snake.head.x == screenx-1 {
score.reason = 2
close(gamestate) close(gamestate)
return return
} else if snake.head.y == 0 || snake.head.y == screeny-1 { } else if snake.head.y == 0 || snake.head.y == screeny-1 {
score.reason = 2
close(gamestate) close(gamestate)
return return
} }
// Check if head intersects with any parts of the body // Check if head intersects with any parts of the body
if hitsTail(&snake, snake.head.x, snake.head.y) { if hitsTail(&snake, snake.head.x, snake.head.y) {
score.reason = 3
close(gamestate) close(gamestate)
return return
} }
@ -93,7 +89,7 @@ func gameDirector(screen tcell.Screen, style tcell.Style, keypresses chan int, g
// Draw the screen // Draw the screen
drawBox(screen, style, 0, 0, screenx-1, screeny-1) drawBox(screen, style, 0, 0, screenx-1, screeny-1)
drawCoords(screen, style, &snake) //drawCoords(screen, style, &snake)
drawApple(screen, style, &apple) drawApple(screen, style, &apple)
drawSnake(screen, style, &snake) drawSnake(screen, style, &snake)
drawScore(screen, style, score) drawScore(screen, style, score)
@ -105,7 +101,7 @@ func gameDirector(screen tcell.Screen, style tcell.Style, keypresses chan int, g
} }
func keyboardProcessor(screen tcell.Screen, keypresses chan int, gamestate chan int) { func keyboardProcessor(screen tcell.Screen, keypresses chan int, gamestate chan int, score *Score) {
defer close(keypresses) defer close(keypresses)
for { for {
@ -117,8 +113,10 @@ func keyboardProcessor(screen tcell.Screen, keypresses chan int, gamestate chan
switch ev := ev.(type) { switch ev := ev.(type) {
case *tcell.EventKey: case *tcell.EventKey:
if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC { if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC {
score.reason = 1
return return
} else if ev.Rune() == 'q' || ev.Rune() == 'Q' { } else if ev.Rune() == 'q' || ev.Rune() == 'Q' {
score.reason = 1
return return
} else if ev.Key() == tcell.KeyCtrlL { } else if ev.Key() == tcell.KeyCtrlL {
screen.Sync() screen.Sync()

28
main.go
View File

@ -2,6 +2,7 @@
package main package main
import ( import (
"fmt"
"log" "log"
) )
@ -12,19 +13,40 @@ func main() {
keypresses := make(chan int) keypresses := make(chan int)
gamestate := make(chan int) gamestate := make(chan int)
// Score tracker
score := Score{
score: 0,
scoreCounter: 1,
reason: 0,
}
// Initialize tcell and clean up when needed. // Initialize tcell and clean up when needed.
screen, style, err := initilize() screen, style, err := initilize()
if err != nil { if err != nil {
log.Fatalln("Initlization error: ", err) log.Fatalln("Initlization error: ", err)
} }
defer quit(screen) //defer quit(screen)
// Spawn the Game Director in its own go routine // Spawn the Game Director in its own go routine
// We give it channels to control... // We give it channels to control...
go gameDirector(screen, style, keypresses, gamestate) go gameDirector(screen, style, keypresses, gamestate, &score)
// A simple function that captures keyboard presses... // A simple function that captures keyboard presses...
// ...and sends it to the GameDirector. // ...and sends it to the GameDirector.
keyboardProcessor(screen, keypresses, gamestate) keyboardProcessor(screen, keypresses, gamestate, &score)
// Quit the screen
quit(screen)
// Print the score
fmt.Println("Score: ", score.score)
switch score.reason {
case 1:
fmt.Println("Reason: You quit")
case 2:
fmt.Println("Reason: You hit a wall")
case 3:
fmt.Println("Reason: You ate your tail")
}
} }

View File

@ -7,9 +7,9 @@ import (
) )
// drawScore Print the score // drawScore Print the score
func drawScore(screen tcell.Screen, style tcell.Style, score int) { func drawScore(screen tcell.Screen, style tcell.Style, score *Score) {
var x, y int = 5, 24 var x, y int = 5, 24
for _, r := range []rune("[ Score: " + strconv.FormatInt(int64(score), 10) + " ]") { for _, r := range []rune("[ Score: " + strconv.FormatInt(int64(score.score), 10) + " ]") {
screen.SetContent(x, y-1, r, nil, style) screen.SetContent(x, y-1, r, nil, style)
x++ x++
} }

View File

@ -5,8 +5,8 @@ import (
) )
// initSnake Initialize the snake // initSnake Initialize the snake
func initSnake(snakex *int, snakey *int) Snake { func initSnake(snakex int, snakey int) Snake {
var x, y int = *snakex, *snakey var x, y int = snakex, snakey
snake := Snake{ snake := Snake{
head: Position{ head: Position{
x: x, x: x,
@ -35,6 +35,8 @@ func initSnake(snakex *int, snakey *int) Snake {
func drawSnake(screen tcell.Screen, style tcell.Style, snake *Snake) { func drawSnake(screen tcell.Screen, style tcell.Style, snake *Snake) {
var tail []rune
// Reverse tail, chop of the excesses, // Reverse tail, chop of the excesses,
snake.tail = ReverseSlice(snake.tail) snake.tail = ReverseSlice(snake.tail)
if len(snake.tail) > snake.length { if len(snake.tail) > snake.length {
@ -43,9 +45,32 @@ func drawSnake(screen tcell.Screen, style tcell.Style, snake *Snake) {
// reverse it back to the original order, replace the tail in `snake` // reverse it back to the original order, replace the tail in `snake`
snake.tail = ReverseSlice(snake.tail) snake.tail = ReverseSlice(snake.tail)
for i, j := range snake.tail {
// The Tail end
if i == 0 {
left := getDirection(j, snake.tail[i+1])
right := getDirection(j, snake.tail[i+1])
tail = append(tail, getLineType(left, right))
// The Bit behind the head
} else if i == len(snake.tail)-1 {
left := getDirection(j, snake.tail[i-1])
right := getDirection(j, snake.head)
tail = append(tail, getLineType(left, right))
// The body of the snake
} else {
left := getDirection(j, snake.tail[i-1])
right := getDirection(j, snake.tail[i+1])
tail = append(tail, getLineType(left, right))
}
}
// Draw the body // Draw the body
for _, segment := range snake.tail { for i, segment := range snake.tail {
screen.SetContent(segment.x, segment.y, '+', nil, style) screen.SetContent(segment.x, segment.y, tail[i], nil, style)
} }
// Draw the head, make sure it is on top of everything // Draw the head, make sure it is on top of everything
@ -109,3 +134,41 @@ func validateDirection(snake *Snake, direction int) bool {
return true return true
} }
} }
func getDirection(from Position, to Position) int {
var direction int
if from.x-to.x == 1 {
direction = Left
} else if from.x-to.x == -1 {
direction = Right
} else if from.y-to.y == 1 {
direction = Up
} else if from.y-to.y == -1 {
direction = Down
}
return direction
}
func getLineType(from int, to int) rune {
var lineType rune
if (from == Left && to == Down) || (from == Down && to == Left) {
lineType = '┐'
} else if (from == Up && to == Right) || (from == Right && to == Up) {
lineType = '└'
} else if (from == Left && to == Right) || (from == Right && to == Left) {
lineType = '─'
} else if (from == Left && to == Up) || (from == Up && to == Left) {
lineType = '┘'
} else if (from == Right && to == Down) || (from == Down && to == Right) {
lineType = '┌'
} else if (from == Up && to == Down) || (from == Down && to == Up) {
lineType = '│'
}
return lineType
}

View File

@ -20,3 +20,9 @@ type Snake struct {
length int length int
direction int direction int
} }
type Score struct {
score int
scoreCounter int
reason int
}