polish some things

This commit is contained in:
2026-09-07 14:49:25 +02:00
parent a106a26277
commit 96db9ec1f9
5 changed files with 110 additions and 62 deletions
+2
View File
@@ -5,6 +5,8 @@ import "image/color"
var ( var (
Black = color.RGBA{0, 0, 0, 1} Black = color.RGBA{0, 0, 0, 1}
LightGray = color.RGBA{24, 24, 24, 1} LightGray = color.RGBA{24, 24, 24, 1}
Gray = color.RGBA{80, 80, 80, 1}
Red = color.RGBA{186, 46, 46, 1} Red = color.RGBA{186, 46, 46, 1}
Green = color.RGBA{46, 186, 46, 1}
DarkYellow = color.RGBA{184, 178, 94, 1} DarkYellow = color.RGBA{184, 178, 94, 1}
) )
+2 -2
View File
@@ -34,9 +34,9 @@ func (b *MenuButton) GetMenuButtonImg(
fontOptions := &text.DrawOptions{} fontOptions := &text.DrawOptions{}
if isFocused { if isFocused {
fontOptions.ColorScale.ScaleWithColor(colors.Red)
} else {
fontOptions.ColorScale.ScaleWithColor(color.White) fontOptions.ColorScale.ScaleWithColor(color.White)
} else {
fontOptions.ColorScale.ScaleWithColor(colors.Gray)
} }
text.Draw( text.Draw(
+28 -12
View File
@@ -9,8 +9,8 @@ import (
) )
const ( const (
WINDOW_WIDTH int = 1200 WindowWidth int = 500
WINDOW_HEIGHT int = 800 WindowHeight int = 500
) )
type GameState int type GameState int
@@ -19,6 +19,7 @@ const (
MainMenu GameState = iota MainMenu GameState = iota
Playing Playing
Dead Dead
Won
) )
type Game struct { type Game struct {
@@ -32,7 +33,7 @@ type Game struct {
} }
func InitGame() *Game { func InitGame() *Game {
ebiten.SetWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT) ebiten.SetWindowSize(WindowWidth, WindowHeight)
ebiten.SetWindowTitle("Snake") ebiten.SetWindowTitle("Snake")
fontFile, err := os.Open("fonts/rockers_garage.ttf") fontFile, err := os.Open("fonts/rockers_garage.ttf")
@@ -49,7 +50,7 @@ func InitGame() *Game {
font: font, font: font,
titleImg: initTitle(font), titleImg: initTitle(font),
state: MainMenu, state: MainMenu,
snake: InitSnake(WINDOW_WIDTH, WINDOW_HEIGHT), snake: InitSnake(WindowWidth, WindowHeight),
menu: InitMenu(), menu: InitMenu(),
} }
} }
@@ -67,12 +68,21 @@ func (g *Game) Update() error {
g.snake.Move() g.snake.Move()
if g.snake.HasCollided() { if g.snake.HasCollided() {
g.snake.isDead = true g.state = Dead
// g.snake.isDead = true
} }
if g.snake.isDead { if g.snake.score == g.snake.total {
g.snake.Click(g) g.state = Won
// g.snake.hasWon = true
} }
// if g.snake.isDead || g.snake.hasWon {
// g.snake.Click(g)
// }
case Dead, Won:
g.snake.Click(g)
} }
return nil return nil
@@ -87,28 +97,34 @@ func (g *Game) Draw(screen *ebiten.Image) {
case Playing: case Playing:
g.snake.Render(screen, g.font) g.snake.Render(screen, g.font)
case Won:
g.snake.renderWinScreen(screen, g.font)
case Dead:
g.snake.renderDeadScreen(screen, g.font)
} }
} }
func (g *Game) Layout(outsideWith, outsideHeight int) (screenWidth, screenHeight int) { func (g *Game) Layout(outsideWith, outsideHeight int) (screenWidth, screenHeight int) {
return WINDOW_WIDTH, WINDOW_HEIGHT return WindowWidth, WindowHeight
} }
func initTitle(font *text.GoTextFaceSource) *ebiten.Image { func initTitle(font *text.GoTextFaceSource) *ebiten.Image {
face := &text.GoTextFace{ face := &text.GoTextFace{
Source: font, Source: font,
Size: 60, Size: 30,
} }
titleW, _ := text.Measure("snake", face, 0) titleW, _ := text.Measure("snake", face, 0)
fontOptions := &text.DrawOptions{} fontOptions := &text.DrawOptions{}
fontOptions.GeoM.Translate(float64(WINDOW_WIDTH)/2-titleW/2, 10) fontOptions.GeoM.Translate(float64(WindowWidth)/2-titleW/2, 10)
fontOptions.ColorScale.ScaleWithColor(color.RGBA{194, 169, 60, 1}) fontOptions.ColorScale.ScaleWithColor(color.RGBA{194, 169, 60, 1})
h := float64(WINDOW_HEIGHT) * 0.1 h := float64(WindowHeight) * 0.1
titleImg := ebiten.NewImage(WINDOW_WIDTH, int(h)) titleImg := ebiten.NewImage(WindowWidth, int(h))
text.Draw(titleImg, "snake", face, fontOptions) text.Draw(titleImg, "snake", face, fontOptions)
+2 -2
View File
@@ -43,7 +43,7 @@ func (m *Menu) Click(game *Game) {
func (m *Menu) executeAction(game *Game, action buttons.MenuAction) { func (m *Menu) executeAction(game *Game, action buttons.MenuAction) {
switch action { switch action {
case buttons.StartGame: case buttons.StartGame:
game.snake = InitSnake(WINDOW_WIDTH, WINDOW_HEIGHT) game.snake = InitSnake(WindowWidth, WindowHeight)
game.state = Playing game.state = Playing
case buttons.ExitGame: case buttons.ExitGame:
@@ -80,7 +80,7 @@ func (m *Menu) Render(screen *ebiten.Image, font *text.GoTextFaceSource) {
} }
imgOp := &ebiten.DrawImageOptions{} imgOp := &ebiten.DrawImageOptions{}
imgOp.GeoM.Translate(150, 200) imgOp.GeoM.Translate(50, 100)
screen.DrawImage(m.img, imgOp) screen.DrawImage(m.img, imgOp)
} }
+76 -46
View File
@@ -40,17 +40,19 @@ type Snake struct {
diff time.Duration diff time.Duration
isDead bool isDead bool
hasWon bool
total int total int
score int score int
} }
const ( const (
START_LENGTH = 20 StartLength = 20
THICKNESS = 8 Thickness = 10
MIN_SPEED int64 = 500 MinSpeed int64 = 400
MAX_SPEED int64 = 50 MaxSpeed int64 = 50
MAX_SPRINT int64 = 20 MaxSprint int64 = 20
EnnemiesCount = 1
) )
func InitSnake(width, height int) *Snake { func InitSnake(width, height int) *Snake {
@@ -60,11 +62,13 @@ func InitSnake(width, height int) *Snake {
return &Snake{ return &Snake{
img: img, img: img,
speed: MIN_SPEED, speed: MinSpeed,
direction: Right, direction: Right,
positions: getInitPositions(utils.GetCenter(width, height)), positions: getInitPositions(utils.GetCenter(width, height)),
ennemies: randomEnnemies(width, h, 10), ennemies: randomEnnemies(width, h, EnnemiesCount),
isDead: false, isDead: false,
total: EnnemiesCount,
score: 0,
} }
} }
@@ -77,11 +81,6 @@ func (snake *Snake) Render(screen *ebiten.Image, font *text.GoTextFaceSource) {
renderScoreScreen(screen, snake, font) renderScoreScreen(screen, snake, font)
if snake.isDead {
renderDeadScreen(screen, snake, font)
return
}
snake.img.Fill(colors.LightGray) snake.img.Fill(colors.LightGray)
for _, ennemy := range snake.ennemies { for _, ennemy := range snake.ennemies {
@@ -89,8 +88,8 @@ func (snake *Snake) Render(screen *ebiten.Image, font *text.GoTextFaceSource) {
snake.img, snake.img,
float32(ennemy.X), float32(ennemy.X),
float32(ennemy.Y), float32(ennemy.Y),
THICKNESS, Thickness,
THICKNESS, Thickness,
colors.DarkYellow, colors.DarkYellow,
true, true,
) )
@@ -101,8 +100,8 @@ func (snake *Snake) Render(screen *ebiten.Image, font *text.GoTextFaceSource) {
snake.img, snake.img,
float32(point.X), float32(point.X),
float32(point.Y), float32(point.Y),
THICKNESS, Thickness,
THICKNESS, Thickness,
color.White, color.White,
true, true,
) )
@@ -168,9 +167,11 @@ func (snake *Snake) Eat() {
snake.positions..., snake.positions...,
) )
if snake.speed > MAX_SPEED { if snake.speed > MaxSpeed {
snake.speed -= 50 snake.speed -= 50
} }
snake.score += 1
} }
func (snake *Snake) Move() { func (snake *Snake) Move() {
@@ -180,7 +181,7 @@ func (snake *Snake) Move() {
var speed int64 var speed int64
if snake.sprint { if snake.sprint {
speed = MAX_SPRINT speed = MaxSprint
} else { } else {
speed = snake.speed speed = snake.speed
} }
@@ -215,13 +216,13 @@ func (snake *Snake) getNextPosition() image.Point {
switch snake.direction { switch snake.direction {
case Up: case Up:
nextHead.Y = nextHead.Y - THICKNESS nextHead.Y = nextHead.Y - Thickness
case Right: case Right:
nextHead.X = nextHead.X + THICKNESS nextHead.X = nextHead.X + Thickness
case Down: case Down:
nextHead.Y = nextHead.Y + THICKNESS nextHead.Y = nextHead.Y + Thickness
case Left: case Left:
nextHead.X = nextHead.X - THICKNESS nextHead.X = nextHead.X - Thickness
} }
return nextHead return nextHead
@@ -237,8 +238,8 @@ func (snake *Snake) Click(game *Game) {
func getInitPositions(center image.Point) []image.Point { func getInitPositions(center image.Point) []image.Point {
points := []image.Point{} points := []image.Point{}
for i := range START_LENGTH { for i := range StartLength {
points = append(points, image.Point{X: center.X - i*THICKNESS, Y: center.Y}) points = append(points, image.Point{X: center.X - i*Thickness, Y: center.Y})
} }
return points return points
@@ -247,12 +248,12 @@ func getInitPositions(center image.Point) []image.Point {
func randomEnnemies(width int, height int, count int) []image.Point { func randomEnnemies(width int, height int, count int) []image.Point {
ennemies := []image.Point{} ennemies := []image.Point{}
w := width / THICKNESS w := width / Thickness
h := height / THICKNESS h := height / Thickness
for range count { for range count {
x := rand.Intn(w) * THICKNESS x := rand.Intn(w) * Thickness
y := rand.Intn(h) * THICKNESS y := rand.Intn(h) * Thickness
ennemies = append(ennemies, image.Point{X: x, Y: y}) ennemies = append(ennemies, image.Point{X: x, Y: y})
} }
@@ -261,31 +262,18 @@ func randomEnnemies(width int, height int, count int) []image.Point {
} }
func renderScoreScreen(screen *ebiten.Image, snake *Snake, font *text.GoTextFaceSource) { func renderScoreScreen(screen *ebiten.Image, snake *Snake, font *text.GoTextFaceSource) {
scoreImg := ebiten.NewImage(WINDOW_WIDTH, 100) scoreImg := ebiten.NewImage(WindowWidth, 50)
scoreImg.Fill(colors.Red) scoreImg.Fill(colors.Black)
levelOptions := &text.DrawOptions{}
levelOptions.ColorScale.ScaleWithColor(color.White)
levelOptions.GeoM.Translate(10, 10)
text.Draw(
scoreImg,
"Level 1",
&text.GoTextFace{
Source: font,
Size: 25,
},
levelOptions,
)
scoreOptions := &text.DrawOptions{} scoreOptions := &text.DrawOptions{}
scoreOptions.ColorScale.ScaleWithColor(color.White) scoreOptions.ColorScale.ScaleWithColor(color.White)
scoreOptions.GeoM.Translate(100, 10) scoreOptions.GeoM.Translate(float64(WindowWidth)-100, 15)
text.Draw( text.Draw(
scoreImg, scoreImg,
fmt.Sprintf("Score: %d/%d", snake.score, snake.total), fmt.Sprintf("Score: %d/%d", snake.score, snake.total),
&text.GoTextFace{ &text.GoTextFace{
Source: font, Source: font,
Size: 25, Size: 20,
}, },
scoreOptions, scoreOptions,
) )
@@ -295,7 +283,49 @@ func renderScoreScreen(screen *ebiten.Image, snake *Snake, font *text.GoTextFace
screen.DrawImage(snake.img, &ebiten.DrawImageOptions{}) screen.DrawImage(snake.img, &ebiten.DrawImageOptions{})
} }
func renderDeadScreen(screen *ebiten.Image, snake *Snake, font *text.GoTextFaceSource) { func (snake *Snake) renderWinScreen(screen *ebiten.Image, font *text.GoTextFaceSource) {
snake.img.Fill(colors.Black)
fontOptions := &text.DrawOptions{}
fontOptions.ColorScale.ScaleWithColor(colors.Green)
winImg := ebiten.NewImage(450, 90)
text.Draw(
winImg,
"You won !",
&text.GoTextFace{
Source: font,
Size: 80,
},
fontOptions,
)
deadImgW := winImg.Bounds().Dx()
deadImgH := winImg.Bounds().Dy()
x := float64(screen.Bounds().Dx()/2 - deadImgW/2)
y := float64(screen.Bounds().Dy()/2 - deadImgH/2)
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(x, y)
snake.img.DrawImage(winImg, op)
// ---- return to menu button
returnToMenuButton := buttons.MenuButton{
Value: "return to menu",
Action: buttons.ReturnToMenu,
}
rtmbImg := returnToMenuButton.GetMenuButtonImg(font, 24, true)
rtmOp := &ebiten.DrawImageOptions{}
rtmOp.GeoM.Translate(x, y+100)
snake.img.DrawImage(rtmbImg, rtmOp)
screen.DrawImage(snake.img, &ebiten.DrawImageOptions{})
}
func (snake *Snake) renderDeadScreen(screen *ebiten.Image, font *text.GoTextFaceSource) {
snake.img.Fill(colors.Black) snake.img.Fill(colors.Black)
fontOptions := &text.DrawOptions{} fontOptions := &text.DrawOptions{}