Compare commits
17 Commits
44724cbbb6
...
v20231124
Author | SHA1 | Date | |
---|---|---|---|
0732e7f809 | |||
763ed9b38a | |||
53e6bfdf4d | |||
44f2c5a41d | |||
c5827793ef | |||
1a9d75574b | |||
65ccadb6d8 | |||
47d5a6fb43 | |||
2009252bb8 | |||
b1cbe95485 | |||
aea82ab765 | |||
3902d2b0a9 | |||
c459247529 | |||
b17918f052 | |||
3fb13a165f | |||
e66f2a2672 | |||
c2134de4b7 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
builds
|
41
apple.go
41
apple.go
@ -2,13 +2,40 @@ package main
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
// getFoodItem returns an emoji from a string used to represent food
|
||||
// Takes no arguments, but returns an emoji/rune from a predefined string
|
||||
func getFoodItem() rune {
|
||||
var foods string = "🐵🐱🐷🐁🐇🐿🦇🐓🐣🐸🦎🍎🍏"
|
||||
foodsRune := []rune(foods)
|
||||
randomIndex := rand.Intn(len(foodsRune))
|
||||
return foodsRune[randomIndex]
|
||||
func placeApple(snake *Snake) Apple {
|
||||
var x, y int
|
||||
var found bool
|
||||
|
||||
for !found {
|
||||
|
||||
x = rand.Intn(80)
|
||||
y = rand.Intn(24)
|
||||
|
||||
if x != snake.head.x && y != snake.head.y {
|
||||
found = true
|
||||
}
|
||||
if x == 0 || x == 79 || y == 0 || y == 23 {
|
||||
found = false
|
||||
}
|
||||
if hitsTail(snake, x, y) {
|
||||
found = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
apple := Apple{
|
||||
x: x,
|
||||
y: y,
|
||||
}
|
||||
|
||||
return apple
|
||||
|
||||
}
|
||||
|
||||
func drawApple(screen tcell.Screen, style tcell.Style, apple *Apple) {
|
||||
screen.SetContent(apple.x, apple.y, 'o', nil, style)
|
||||
}
|
||||
|
5
build.sh
Executable file
5
build.sh
Executable 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
|
45
design.md
45
design.md
@ -1,45 +0,0 @@
|
||||
# Snake
|
||||
( Doing it my way. )
|
||||
|
||||
# The game
|
||||
This follows the usual setting:
|
||||
* Field
|
||||
* Snake that cannot hurt itself
|
||||
* Snake that gets wounded by the edges
|
||||
* Score
|
||||
|
||||
The game should look something like this:
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ ║
|
||||
║ ║
|
||||
║ ║
|
||||
║ ║
|
||||
║ │ ║
|
||||
║ │ ║
|
||||
║ └───────o ║
|
||||
║ ║
|
||||
║ ║
|
||||
║ ║
|
||||
║ ║
|
||||
║ ║
|
||||
║ ║
|
||||
║ ║
|
||||
║ ║
|
||||
║ 🍏 ║
|
||||
║ ║
|
||||
║ ║
|
||||
║ ║
|
||||
║ ║
|
||||
║ ║
|
||||
╚════[ Score: 12309 ]══════════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
The minimum and maximum resolution of this game is `80` columes and `24` rows, Anything console larger will have no issues with this setup, anything smaller should pause the game with a message to resize.
|
||||
|
||||
Scoring is done by having a counter _n_, every time an object is eaten, this counter is added to the score and raised by one. So after four apples the score would be (1+2+3+4) 10.
|
||||
|
||||
The objects to eat are a series of emojis Snakes would eat IRL in nature. This is anything from fruits, nuts, frogs, etc.
|
||||
|
||||
Snake cannot eat itself, nor eat the border.
|
73
game.go
73
game.go
@ -7,13 +7,6 @@ import (
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
Left = iota
|
||||
Right
|
||||
Up
|
||||
Down
|
||||
)
|
||||
|
||||
func initilize() (tcell.Screen, tcell.Style, error) {
|
||||
style := tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset)
|
||||
|
||||
@ -38,41 +31,55 @@ 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.
|
||||
defer quit(screen)
|
||||
|
||||
//var score int = 0
|
||||
//var scoreCounter int = 1
|
||||
//var field [80][24]int
|
||||
// fill up the field:
|
||||
// 0: empty
|
||||
// 1: snake
|
||||
// 2: apple
|
||||
// 3: border
|
||||
|
||||
// Board size
|
||||
var screenx = 80
|
||||
var screeny = 24
|
||||
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((screenx/2)-1, (screeny/2)-1)
|
||||
var apple Apple = placeApple(&snake)
|
||||
|
||||
for {
|
||||
|
||||
// Take input or sleep
|
||||
select {
|
||||
case press := <-keypresses:
|
||||
snakeDirection(press, &snakex, &snakey)
|
||||
lastpress = press
|
||||
if validateDirection(&snake, press) {
|
||||
snakeDirection(press, &snake)
|
||||
lastpress = press
|
||||
}
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
snakeDirection(lastpress, &snakex, &snakey)
|
||||
snakeDirection(lastpress, &snake)
|
||||
}
|
||||
|
||||
if snakex == 0 || snakex == screenx-1 {
|
||||
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 snakey == 0 || snakey == screeny-1 {
|
||||
} 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
|
||||
}
|
||||
@ -81,9 +88,11 @@ func gameDirector(screen tcell.Screen, style tcell.Style, keypresses chan int, g
|
||||
screen.Clear()
|
||||
|
||||
// Draw the screen
|
||||
drawBox(screen, 0, 0, screenx-1, screeny-1, style)
|
||||
drawCoords(screen, style, &snakex, &snakey)
|
||||
drawSnake(screen, style, snakex, snakey)
|
||||
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()
|
||||
@ -92,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)
|
||||
|
||||
for {
|
||||
@ -102,15 +111,12 @@ func keyboardProcessor(screen tcell.Screen, keypresses chan int, gamestate chan
|
||||
|
||||
// Fetch the type, and check if any other actions are required.
|
||||
switch ev := ev.(type) {
|
||||
//case *tcell.EventResize:
|
||||
// x, y := screen.Size()
|
||||
// drawBox(screen, 0, 0, x-1, y-1, style)
|
||||
// updateScore(screen, style, snakex)
|
||||
// screen.Sync()
|
||||
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()
|
||||
@ -130,7 +136,6 @@ func keyboardProcessor(screen tcell.Screen, keypresses chan int, gamestate chan
|
||||
// This function needs to know if the game is over.
|
||||
select {
|
||||
case <-time.After(10 * time.Millisecond):
|
||||
|
||||
case _, ok := <-gamestate:
|
||||
if !ok {
|
||||
return
|
||||
|
10
go.mod
10
go.mod
@ -7,9 +7,9 @@ require github.com/gdamore/tcell/v2 v2.6.0
|
||||
require (
|
||||
github.com/gdamore/encoding v1.0.0 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/rivo/uniseg v0.4.3 // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
golang.org/x/term v0.5.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
golang.org/x/sys v0.14.0 // indirect
|
||||
golang.org/x/term v0.14.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
)
|
||||
|
15
go.sum
15
go.sum
@ -4,11 +4,13 @@ github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCyS
|
||||
github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
|
||||
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
@ -23,17 +25,20 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
|
||||
golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
|
38
main.go
38
main.go
@ -1,22 +1,52 @@
|
||||
// An amateurs approach to the game of Snake
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
// main function
|
||||
func main() {
|
||||
|
||||
// Create a channel to push key-presses through
|
||||
// Create channles to manage keypresses and the gamestate
|
||||
keypresses := make(chan int)
|
||||
gamestate := make(chan int)
|
||||
|
||||
// Score tracker
|
||||
score := Score{
|
||||
score: 0,
|
||||
scoreCounter: 1,
|
||||
reason: 0,
|
||||
}
|
||||
|
||||
// Initialize tcell and clean up when needed.
|
||||
screen, style, err := initilize()
|
||||
if err != nil {
|
||||
log.Fatalln("Initlization error: ", err)
|
||||
}
|
||||
defer quit(screen)
|
||||
//defer quit(screen)
|
||||
|
||||
go gameDirector(screen, style, keypresses, gamestate)
|
||||
keyboardProcessor(screen, keypresses, gamestate)
|
||||
// Spawn the Game Director in its own go routine
|
||||
// We give it channels to control...
|
||||
go gameDirector(screen, style, keypresses, gamestate, &score)
|
||||
|
||||
// A simple function that captures keyboard presses...
|
||||
// ...and sends it to the GameDirector.
|
||||
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")
|
||||
}
|
||||
|
||||
}
|
||||
|
25
render.go
25
render.go
@ -6,35 +6,26 @@ import (
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
func checkSize(screen tcell.Screen) bool {
|
||||
var retval bool = true
|
||||
x, y := screen.Size()
|
||||
if x < 80 {
|
||||
retval = false
|
||||
}
|
||||
if y < 24 {
|
||||
retval = false
|
||||
}
|
||||
return retval
|
||||
}
|
||||
|
||||
func drawScore(screen tcell.Screen, style tcell.Style, score int) {
|
||||
// drawScore Print the score
|
||||
func drawScore(screen tcell.Screen, style tcell.Style, score *Score) {
|
||||
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)
|
||||
x++
|
||||
}
|
||||
}
|
||||
|
||||
func drawCoords(screen tcell.Screen, style tcell.Style, snakex *int, snakey *int) {
|
||||
// drawCoords Print the coordinates of the head of the snake
|
||||
func drawCoords(screen tcell.Screen, style tcell.Style, snake *Snake) {
|
||||
var x, y int = 25, 24
|
||||
for _, r := range []rune("[ x:" + strconv.FormatInt(int64(*snakex), 10) + " y: " + strconv.FormatInt(int64(*snakey), 10) + " ]") {
|
||||
for _, r := range []rune("[ x:" + strconv.FormatInt(int64(*&snake.head.x), 10) + " y: " + strconv.FormatInt(int64(*&snake.head.y), 10) + " ]") {
|
||||
screen.SetContent(x, y-1, r, nil, style)
|
||||
x++
|
||||
}
|
||||
}
|
||||
|
||||
func drawBox(s tcell.Screen, x1, y1, x2, y2 int, style tcell.Style) {
|
||||
// drawBox Draw the outline of the box the snake can move in
|
||||
func drawBox(s tcell.Screen, style tcell.Style, x1, y1, x2, y2 int) {
|
||||
if y2 < y1 {
|
||||
y1, y2 = y2, y1
|
||||
}
|
||||
|
167
snake.go
167
snake.go
@ -4,18 +4,171 @@ import (
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
func drawSnake(screen tcell.Screen, style tcell.Style, x int, y int) {
|
||||
screen.SetContent(x, y, '🐍', nil, style)
|
||||
// initSnake Initialize the snake
|
||||
func initSnake(snakex int, snakey int) Snake {
|
||||
var x, y int = snakex, snakey
|
||||
snake := Snake{
|
||||
head: Position{
|
||||
x: x,
|
||||
y: y,
|
||||
},
|
||||
tail: []Position{
|
||||
{
|
||||
x: x - 1,
|
||||
y: y,
|
||||
},
|
||||
{
|
||||
x: x - 2,
|
||||
y: y,
|
||||
},
|
||||
{
|
||||
x: x - 3,
|
||||
y: y,
|
||||
},
|
||||
},
|
||||
length: 3,
|
||||
direction: 1,
|
||||
}
|
||||
|
||||
return snake
|
||||
}
|
||||
|
||||
func snakeDirection(press int, snakex *int, snakey *int) {
|
||||
func drawSnake(screen tcell.Screen, style tcell.Style, snake *Snake) {
|
||||
|
||||
var tail []rune
|
||||
|
||||
// Reverse tail, chop of the excesses,
|
||||
snake.tail = ReverseSlice(snake.tail)
|
||||
if len(snake.tail) > snake.length {
|
||||
snake.tail = snake.tail[:snake.length]
|
||||
}
|
||||
// reverse it back to the original order, replace the tail in `snake`
|
||||
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
|
||||
for i, segment := range snake.tail {
|
||||
screen.SetContent(segment.x, segment.y, tail[i], nil, style)
|
||||
}
|
||||
|
||||
// Draw the head, make sure it is on top of everything
|
||||
screen.SetContent(snake.head.x, snake.head.y, '0', nil, style)
|
||||
|
||||
}
|
||||
|
||||
func snakeDirection(press int, snake *Snake) {
|
||||
if press == Left {
|
||||
*snakex--
|
||||
snake.head.x--
|
||||
snake.tail = append(snake.tail, Position{x: snake.head.x + 1, y: snake.head.y})
|
||||
snake.direction = press
|
||||
} else if press == Right {
|
||||
*snakex++
|
||||
snake.head.x++
|
||||
snake.tail = append(snake.tail, Position{x: snake.head.x - 1, y: snake.head.y})
|
||||
snake.direction = press
|
||||
} else if press == Up {
|
||||
*snakey--
|
||||
snake.head.y--
|
||||
snake.tail = append(snake.tail, Position{x: snake.head.x, y: snake.head.y + 1})
|
||||
snake.direction = press
|
||||
} else if press == Down {
|
||||
*snakey++
|
||||
snake.head.y++
|
||||
snake.tail = append(snake.tail, Position{x: snake.head.x, y: snake.head.y - 1})
|
||||
snake.direction = press
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a pos hits the tail
|
||||
func hitsTail(snake *Snake, x int, y int) bool {
|
||||
var hit bool = false
|
||||
|
||||
for _, segment := range snake.tail {
|
||||
if segment.x == x && segment.y == y {
|
||||
hit = true
|
||||
}
|
||||
}
|
||||
|
||||
return hit
|
||||
}
|
||||
|
||||
func ReverseSlice[T comparable](s []T) []T {
|
||||
var r []T
|
||||
for i := len(s) - 1; i >= 0; i-- {
|
||||
r = append(r, s[i])
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func validateDirection(snake *Snake, direction int) bool {
|
||||
if snake.direction == direction {
|
||||
return true
|
||||
} else if snake.direction == Left && direction == Right {
|
||||
return false
|
||||
} else if snake.direction == Right && direction == Left {
|
||||
return false
|
||||
} else if snake.direction == Up && direction == Down {
|
||||
return false
|
||||
} else if snake.direction == Down && direction == Up {
|
||||
return false
|
||||
} else {
|
||||
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
|
||||
}
|
||||
|
Reference in New Issue
Block a user