mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-02-02 14:04:28 +01:00
examples: Add a snake game (#1276)
This commit is contained in:
parent
88c103e1fd
commit
c352e69689
208
examples/snake/main.go
Normal file
208
examples/snake/main.go
Normal file
@ -0,0 +1,208 @@
|
||||
// Copyright 2020 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build example jsgo
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"log"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
"github.com/hajimehoshi/ebiten/inpututil"
|
||||
)
|
||||
|
||||
const (
|
||||
screenWidth = 640
|
||||
screenHeight = 480
|
||||
gridSize = 10
|
||||
xNumInScreen = screenWidth / gridSize
|
||||
yNumInScreen = screenHeight / gridSize
|
||||
)
|
||||
|
||||
const (
|
||||
dirNone = iota
|
||||
dirLeft
|
||||
dirRight
|
||||
dirDown
|
||||
dirUp
|
||||
)
|
||||
|
||||
type Position struct {
|
||||
X int
|
||||
Y int
|
||||
}
|
||||
|
||||
type Game struct {
|
||||
moveDirection int
|
||||
snakeBody []Position
|
||||
apple Position
|
||||
timer int
|
||||
moveTime int
|
||||
score int
|
||||
bestScore int
|
||||
level int
|
||||
}
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
func (g *Game) collidesWithApple() bool {
|
||||
return g.snakeBody[0].X == g.apple.X &&
|
||||
g.snakeBody[0].Y == g.apple.Y
|
||||
}
|
||||
|
||||
func (g *Game) collidesWithSelf() bool {
|
||||
for _, v := range g.snakeBody[1:] {
|
||||
if g.snakeBody[0].X == v.X &&
|
||||
g.snakeBody[0].Y == v.Y {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *Game) collidesWithWall() bool {
|
||||
return g.snakeBody[0].X < 0 ||
|
||||
g.snakeBody[0].Y < 0 ||
|
||||
g.snakeBody[0].X >= xNumInScreen ||
|
||||
g.snakeBody[0].Y >= yNumInScreen
|
||||
}
|
||||
|
||||
func (g *Game) needsToMoveSnake() bool {
|
||||
return g.timer%g.moveTime == 0
|
||||
}
|
||||
|
||||
func (g *Game) reset() {
|
||||
g.apple.X = 3 * gridSize
|
||||
g.apple.Y = 3 * gridSize
|
||||
g.moveTime = 4
|
||||
g.snakeBody = g.snakeBody[:1]
|
||||
g.snakeBody[0].X = xNumInScreen / 2
|
||||
g.snakeBody[0].Y = yNumInScreen / 2
|
||||
g.score = 0
|
||||
g.level = 1
|
||||
g.moveDirection = dirNone
|
||||
}
|
||||
|
||||
func (g *Game) Update(screen *ebiten.Image) error {
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyLeft) || inpututil.IsKeyJustPressed(ebiten.KeyA) {
|
||||
if g.moveDirection != dirRight {
|
||||
g.moveDirection = dirLeft
|
||||
}
|
||||
} else if inpututil.IsKeyJustPressed(ebiten.KeyRight) || inpututil.IsKeyJustPressed(ebiten.KeyD) {
|
||||
if g.moveDirection != dirLeft {
|
||||
g.moveDirection = dirRight
|
||||
}
|
||||
} else if inpututil.IsKeyJustPressed(ebiten.KeyDown) || inpututil.IsKeyJustPressed(ebiten.KeyS) {
|
||||
if g.moveDirection != dirUp {
|
||||
g.moveDirection = dirDown
|
||||
}
|
||||
} else if inpututil.IsKeyJustPressed(ebiten.KeyUp) || inpututil.IsKeyJustPressed(ebiten.KeyW) {
|
||||
if g.moveDirection != dirDown {
|
||||
g.moveDirection = dirUp
|
||||
}
|
||||
} else if inpututil.IsKeyJustPressed(ebiten.KeyEscape) {
|
||||
g.reset()
|
||||
}
|
||||
|
||||
if g.needsToMoveSnake() {
|
||||
if g.collidesWithWall() || g.collidesWithSelf() {
|
||||
g.reset()
|
||||
}
|
||||
|
||||
if g.collidesWithApple() {
|
||||
g.apple.X = rand.Intn(xNumInScreen - 1)
|
||||
g.apple.Y = rand.Intn(yNumInScreen - 1)
|
||||
g.snakeBody = append(g.snakeBody, Position{
|
||||
X: g.snakeBody[len(g.snakeBody)-1].X,
|
||||
Y: g.snakeBody[len(g.snakeBody)-1].Y,
|
||||
})
|
||||
if len(g.snakeBody) > 10 && len(g.snakeBody) < 20 {
|
||||
g.level = 2
|
||||
g.moveTime = 3
|
||||
} else if len(g.snakeBody) > 20 {
|
||||
g.level = 3
|
||||
g.moveTime = 2
|
||||
} else {
|
||||
g.level = 1
|
||||
}
|
||||
g.score++
|
||||
if g.bestScore < g.score {
|
||||
g.bestScore = g.score
|
||||
}
|
||||
}
|
||||
|
||||
for i := int64(len(g.snakeBody)) - 1; i > 0; i-- {
|
||||
g.snakeBody[i].X = g.snakeBody[i-1].X
|
||||
g.snakeBody[i].Y = g.snakeBody[i-1].Y
|
||||
}
|
||||
switch g.moveDirection {
|
||||
case dirLeft:
|
||||
g.snakeBody[0].X--
|
||||
case dirRight:
|
||||
g.snakeBody[0].X++
|
||||
case dirDown:
|
||||
g.snakeBody[0].Y++
|
||||
case dirUp:
|
||||
g.snakeBody[0].Y--
|
||||
}
|
||||
}
|
||||
|
||||
g.timer++
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Game) Draw(screen *ebiten.Image) {
|
||||
for _, v := range g.snakeBody {
|
||||
ebitenutil.DrawRect(screen, float64(v.X*gridSize), float64(v.Y*gridSize), gridSize, gridSize, color.RGBA{0x80, 0xa0, 0xc0, 0xff})
|
||||
}
|
||||
ebitenutil.DrawRect(screen, float64(g.apple.X*gridSize), float64(g.apple.Y*gridSize), gridSize, gridSize, color.RGBA{0xFF, 0x00, 0x00, 0xff})
|
||||
|
||||
if g.moveDirection == dirNone {
|
||||
ebitenutil.DebugPrint(screen, fmt.Sprintf("Press up/down/left/right to start"))
|
||||
} else {
|
||||
ebitenutil.DebugPrint(screen, fmt.Sprintf("FPS: %0.2f Level: %d Score: %d Best Score: %d", ebiten.CurrentFPS(), g.level, g.score, g.bestScore))
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
|
||||
return screenWidth, screenHeight
|
||||
}
|
||||
|
||||
func newGame() *Game {
|
||||
g := &Game{
|
||||
apple: Position{X: 3 * gridSize, Y: 3 * gridSize},
|
||||
moveTime: 4,
|
||||
snakeBody: make([]Position, 1),
|
||||
}
|
||||
g.snakeBody[0].X = xNumInScreen / 2
|
||||
g.snakeBody[0].Y = yNumInScreen / 2
|
||||
return g
|
||||
}
|
||||
|
||||
func main() {
|
||||
ebiten.SetWindowSize(screenWidth, screenHeight)
|
||||
ebiten.SetWindowTitle("Snake (Ebiten Demo)")
|
||||
if err := ebiten.RunGame(newGame()); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user