Skip to content

Commit 248e072

Browse files
committed
Add games/snakegame
1 parent 71eac3f commit 248e072

3 files changed

Lines changed: 210 additions & 0 deletions

File tree

games/all/all/all.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/sago35/koebiten/games/blocks/blocks"
88
"github.com/sago35/koebiten/games/flappygopher/flappygopher"
99
"github.com/sago35/koebiten/games/jumpingopher/jumpingopher"
10+
"github.com/sago35/koebiten/games/snakegame/snakegame"
1011
)
1112

1213
type Game struct {
@@ -55,6 +56,16 @@ func NewGame() *Menu {
5556
}
5657
},
5758
},
59+
{
60+
Title: "Snake Game",
61+
Game: func() {
62+
koebiten.SetRotation(koebiten.Rotation0)
63+
game := snakegame.NewGame()
64+
if err := koebiten.RunGame(game); err != nil {
65+
log.Fatal(err)
66+
}
67+
},
68+
},
5869
})
5970

6071
return menu

games/snakegame/main.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package main
2+
3+
import (
4+
"math/rand"
5+
"time"
6+
7+
"github.com/sago35/koebiten"
8+
"github.com/sago35/koebiten/games/snakegame/snakegame"
9+
"github.com/sago35/koebiten/hardware"
10+
"tinygo.org/x/drivers/pixel"
11+
)
12+
13+
var (
14+
white = pixel.NewMonochrome(0xFF, 0xFF, 0xFF)
15+
black = pixel.NewMonochrome(0x00, 0x00, 0x00)
16+
17+
gridSize = 4
18+
width = 128 / gridSize
19+
height = 64 / gridSize
20+
initialSpeed = 100 * time.Millisecond
21+
)
22+
23+
func main() {
24+
rand.Seed(time.Now().UnixNano())
25+
koebiten.SetHardware(hardware.Device)
26+
koebiten.SetWindowSize(128, 64)
27+
koebiten.SetWindowTitle("Snake Gmae")
28+
29+
game := snakegame.NewGame()
30+
koebiten.RunGame(game)
31+
}
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
package snakegame
2+
3+
import (
4+
"math/rand"
5+
"time"
6+
7+
"github.com/sago35/koebiten"
8+
"tinygo.org/x/drivers/pixel"
9+
)
10+
11+
var (
12+
white = pixel.NewMonochrome(0xFF, 0xFF, 0xFF)
13+
black = pixel.NewMonochrome(0x00, 0x00, 0x00)
14+
15+
gridSize = 4
16+
width = 128 / gridSize
17+
height = 64 / gridSize
18+
initialSpeed = 100 * time.Millisecond
19+
)
20+
21+
type Point struct {
22+
x, y int
23+
}
24+
25+
type GameState int
26+
27+
const (
28+
StateOpening GameState = iota
29+
StatePlaying
30+
StateGameOver
31+
)
32+
33+
type Game struct {
34+
snake []Point
35+
dir Point
36+
food Point
37+
alive bool
38+
speed time.Duration
39+
lastMove time.Time
40+
pendingDir Point
41+
score int
42+
state GameState
43+
}
44+
45+
func NewGame() *Game {
46+
game := &Game{}
47+
game.Init()
48+
return game
49+
}
50+
51+
func (g *Game) Init() {
52+
g.snake = []Point{{width / 2, height / 2}}
53+
g.dir = Point{1, 0}
54+
g.pendingDir = g.dir
55+
g.spawnFood()
56+
g.alive = true
57+
g.speed = initialSpeed
58+
g.lastMove = time.Now()
59+
g.score = 0
60+
}
61+
62+
func (g *Game) spawnFood() {
63+
g.food = Point{rand.Intn(width), rand.Intn(height)}
64+
}
65+
66+
func (g *Game) Update() error {
67+
if g.state == StateOpening || g.state == StateGameOver {
68+
if isAnyKeyJustPressed() {
69+
g.state = StatePlaying
70+
g.Init()
71+
g.state = StatePlaying
72+
}
73+
return nil
74+
}
75+
76+
if !g.alive {
77+
g.state = StateGameOver
78+
return nil
79+
}
80+
81+
if koebiten.IsKeyPressed(koebiten.KeyArrowUp) && g.dir.y == 0 {
82+
g.pendingDir = Point{0, -1}
83+
}
84+
if koebiten.IsKeyPressed(koebiten.KeyArrowDown) && g.dir.y == 0 {
85+
g.pendingDir = Point{0, 1}
86+
}
87+
if koebiten.IsKeyPressed(koebiten.KeyArrowRight) && g.dir.x == 0 {
88+
g.pendingDir = Point{1, 0}
89+
}
90+
if koebiten.IsKeyPressed(koebiten.KeyArrowLeft) && g.dir.x == 0 {
91+
g.pendingDir = Point{-1, 0}
92+
}
93+
if koebiten.IsKeyPressed(koebiten.KeyRotaryRight) {
94+
if g.dir.x == 1 {
95+
g.pendingDir = Point{0, 1}
96+
} else if g.dir.y == 1 {
97+
g.pendingDir = Point{-1, 0}
98+
} else if g.dir.x == -1 {
99+
g.pendingDir = Point{0, -1}
100+
} else if g.dir.y == -1 {
101+
g.pendingDir = Point{1, 0}
102+
}
103+
}
104+
if koebiten.IsKeyPressed(koebiten.KeyRotaryLeft) {
105+
if g.dir.x == 1 {
106+
g.pendingDir = Point{0, -1}
107+
} else if g.dir.y == 1 {
108+
109+
} else if g.dir.x == -1 {
110+
g.pendingDir = Point{0, 1}
111+
} else if g.dir.y == -1 {
112+
g.pendingDir = Point{-1, 0}
113+
}
114+
}
115+
116+
if time.Since(g.lastMove) < g.speed {
117+
return nil
118+
}
119+
g.lastMove = time.Now()
120+
g.dir = g.pendingDir
121+
122+
next := Point{(g.snake[0].x + g.dir.x + width) % width, (g.snake[0].y + g.dir.y + height) % height}
123+
for _, s := range g.snake {
124+
if s == next {
125+
g.alive = false
126+
g.state = StateGameOver
127+
return nil
128+
}
129+
}
130+
131+
g.snake = append([]Point{next}, g.snake...)
132+
if next == g.food {
133+
g.spawnFood()
134+
g.score = len(g.snake) - 1
135+
g.speed = time.Duration(float64(g.speed) * 0.95)
136+
} else {
137+
g.snake = g.snake[:len(g.snake)-1]
138+
}
139+
140+
return nil
141+
}
142+
143+
func (g *Game) Draw(screen *koebiten.Image) {
144+
if g.state == StateOpening {
145+
koebiten.Println("Press Button to Start")
146+
return
147+
}
148+
if g.state == StateGameOver {
149+
koebiten.Println("Game Over")
150+
koebiten.Println("Score:", g.score)
151+
koebiten.Println("Press Button to Restart")
152+
return
153+
}
154+
155+
for _, s := range g.snake {
156+
koebiten.DrawFilledRect(screen, s.x*gridSize, s.y*gridSize, gridSize, gridSize, white)
157+
}
158+
koebiten.DrawFilledRect(screen, g.food.x*gridSize, g.food.y*gridSize, gridSize, gridSize, white)
159+
koebiten.Println("Score:", g.score)
160+
}
161+
162+
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
163+
return 128, 64
164+
}
165+
166+
func isAnyKeyJustPressed() bool {
167+
return len(koebiten.AppendJustPressedKeys(nil)) > 0
168+
}

0 commit comments

Comments
 (0)