From 96db9ec1f913978eadaeeb0a9824e0a5c7baa6f7 Mon Sep 17 00:00:00 2001 From: mimu Date: Mon, 7 Sep 2026 14:49:25 +0200 Subject: [PATCH] polish some things --- colors/colors.go | 2 + components/buttons/menu_button.go | 4 +- components/game.go | 40 +++++++--- components/menu.go | 4 +- components/snake.go | 122 +++++++++++++++++++----------- 5 files changed, 110 insertions(+), 62 deletions(-) diff --git a/colors/colors.go b/colors/colors.go index 6dc3516..a63957f 100644 --- a/colors/colors.go +++ b/colors/colors.go @@ -5,6 +5,8 @@ import "image/color" var ( Black = color.RGBA{0, 0, 0, 1} LightGray = color.RGBA{24, 24, 24, 1} + Gray = color.RGBA{80, 80, 80, 1} Red = color.RGBA{186, 46, 46, 1} + Green = color.RGBA{46, 186, 46, 1} DarkYellow = color.RGBA{184, 178, 94, 1} ) diff --git a/components/buttons/menu_button.go b/components/buttons/menu_button.go index 17a7f69..7761b8f 100644 --- a/components/buttons/menu_button.go +++ b/components/buttons/menu_button.go @@ -34,9 +34,9 @@ func (b *MenuButton) GetMenuButtonImg( fontOptions := &text.DrawOptions{} if isFocused { - fontOptions.ColorScale.ScaleWithColor(colors.Red) - } else { fontOptions.ColorScale.ScaleWithColor(color.White) + } else { + fontOptions.ColorScale.ScaleWithColor(colors.Gray) } text.Draw( diff --git a/components/game.go b/components/game.go index 4089ac3..984df23 100644 --- a/components/game.go +++ b/components/game.go @@ -9,8 +9,8 @@ import ( ) const ( - WINDOW_WIDTH int = 1200 - WINDOW_HEIGHT int = 800 + WindowWidth int = 500 + WindowHeight int = 500 ) type GameState int @@ -19,6 +19,7 @@ const ( MainMenu GameState = iota Playing Dead + Won ) type Game struct { @@ -32,7 +33,7 @@ type Game struct { } func InitGame() *Game { - ebiten.SetWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT) + ebiten.SetWindowSize(WindowWidth, WindowHeight) ebiten.SetWindowTitle("Snake") fontFile, err := os.Open("fonts/rockers_garage.ttf") @@ -49,7 +50,7 @@ func InitGame() *Game { font: font, titleImg: initTitle(font), state: MainMenu, - snake: InitSnake(WINDOW_WIDTH, WINDOW_HEIGHT), + snake: InitSnake(WindowWidth, WindowHeight), menu: InitMenu(), } } @@ -67,12 +68,21 @@ func (g *Game) Update() error { g.snake.Move() if g.snake.HasCollided() { - g.snake.isDead = true + g.state = Dead + // g.snake.isDead = true } - if g.snake.isDead { - g.snake.Click(g) + if g.snake.score == g.snake.total { + 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 @@ -87,28 +97,34 @@ func (g *Game) Draw(screen *ebiten.Image) { case Playing: 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) { - return WINDOW_WIDTH, WINDOW_HEIGHT + return WindowWidth, WindowHeight } func initTitle(font *text.GoTextFaceSource) *ebiten.Image { face := &text.GoTextFace{ Source: font, - Size: 60, + Size: 30, } titleW, _ := text.Measure("snake", face, 0) 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}) - 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) diff --git a/components/menu.go b/components/menu.go index ddad604..c94b975 100644 --- a/components/menu.go +++ b/components/menu.go @@ -43,7 +43,7 @@ func (m *Menu) Click(game *Game) { func (m *Menu) executeAction(game *Game, action buttons.MenuAction) { switch action { case buttons.StartGame: - game.snake = InitSnake(WINDOW_WIDTH, WINDOW_HEIGHT) + game.snake = InitSnake(WindowWidth, WindowHeight) game.state = Playing case buttons.ExitGame: @@ -80,7 +80,7 @@ func (m *Menu) Render(screen *ebiten.Image, font *text.GoTextFaceSource) { } imgOp := &ebiten.DrawImageOptions{} - imgOp.GeoM.Translate(150, 200) + imgOp.GeoM.Translate(50, 100) screen.DrawImage(m.img, imgOp) } diff --git a/components/snake.go b/components/snake.go index 1fb5112..0142e3a 100644 --- a/components/snake.go +++ b/components/snake.go @@ -40,17 +40,19 @@ type Snake struct { diff time.Duration isDead bool + hasWon bool total int score int } const ( - START_LENGTH = 20 - THICKNESS = 8 - MIN_SPEED int64 = 500 - MAX_SPEED int64 = 50 - MAX_SPRINT int64 = 20 + StartLength = 20 + Thickness = 10 + MinSpeed int64 = 400 + MaxSpeed int64 = 50 + MaxSprint int64 = 20 + EnnemiesCount = 1 ) func InitSnake(width, height int) *Snake { @@ -60,11 +62,13 @@ func InitSnake(width, height int) *Snake { return &Snake{ img: img, - speed: MIN_SPEED, + speed: MinSpeed, direction: Right, positions: getInitPositions(utils.GetCenter(width, height)), - ennemies: randomEnnemies(width, h, 10), + ennemies: randomEnnemies(width, h, EnnemiesCount), isDead: false, + total: EnnemiesCount, + score: 0, } } @@ -77,11 +81,6 @@ func (snake *Snake) Render(screen *ebiten.Image, font *text.GoTextFaceSource) { renderScoreScreen(screen, snake, font) - if snake.isDead { - renderDeadScreen(screen, snake, font) - return - } - snake.img.Fill(colors.LightGray) for _, ennemy := range snake.ennemies { @@ -89,8 +88,8 @@ func (snake *Snake) Render(screen *ebiten.Image, font *text.GoTextFaceSource) { snake.img, float32(ennemy.X), float32(ennemy.Y), - THICKNESS, - THICKNESS, + Thickness, + Thickness, colors.DarkYellow, true, ) @@ -101,8 +100,8 @@ func (snake *Snake) Render(screen *ebiten.Image, font *text.GoTextFaceSource) { snake.img, float32(point.X), float32(point.Y), - THICKNESS, - THICKNESS, + Thickness, + Thickness, color.White, true, ) @@ -168,9 +167,11 @@ func (snake *Snake) Eat() { snake.positions..., ) - if snake.speed > MAX_SPEED { + if snake.speed > MaxSpeed { snake.speed -= 50 } + + snake.score += 1 } func (snake *Snake) Move() { @@ -180,7 +181,7 @@ func (snake *Snake) Move() { var speed int64 if snake.sprint { - speed = MAX_SPRINT + speed = MaxSprint } else { speed = snake.speed } @@ -215,13 +216,13 @@ func (snake *Snake) getNextPosition() image.Point { switch snake.direction { case Up: - nextHead.Y = nextHead.Y - THICKNESS + nextHead.Y = nextHead.Y - Thickness case Right: - nextHead.X = nextHead.X + THICKNESS + nextHead.X = nextHead.X + Thickness case Down: - nextHead.Y = nextHead.Y + THICKNESS + nextHead.Y = nextHead.Y + Thickness case Left: - nextHead.X = nextHead.X - THICKNESS + nextHead.X = nextHead.X - Thickness } return nextHead @@ -237,8 +238,8 @@ func (snake *Snake) Click(game *Game) { func getInitPositions(center image.Point) []image.Point { points := []image.Point{} - for i := range START_LENGTH { - points = append(points, image.Point{X: center.X - i*THICKNESS, Y: center.Y}) + for i := range StartLength { + points = append(points, image.Point{X: center.X - i*Thickness, Y: center.Y}) } return points @@ -247,12 +248,12 @@ func getInitPositions(center image.Point) []image.Point { func randomEnnemies(width int, height int, count int) []image.Point { ennemies := []image.Point{} - w := width / THICKNESS - h := height / THICKNESS + w := width / Thickness + h := height / Thickness for range count { - x := rand.Intn(w) * THICKNESS - y := rand.Intn(h) * THICKNESS + x := rand.Intn(w) * Thickness + y := rand.Intn(h) * Thickness 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) { - scoreImg := ebiten.NewImage(WINDOW_WIDTH, 100) - scoreImg.Fill(colors.Red) - - 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, - ) + scoreImg := ebiten.NewImage(WindowWidth, 50) + scoreImg.Fill(colors.Black) scoreOptions := &text.DrawOptions{} scoreOptions.ColorScale.ScaleWithColor(color.White) - scoreOptions.GeoM.Translate(100, 10) + scoreOptions.GeoM.Translate(float64(WindowWidth)-100, 15) text.Draw( scoreImg, fmt.Sprintf("Score: %d/%d", snake.score, snake.total), &text.GoTextFace{ Source: font, - Size: 25, + Size: 20, }, scoreOptions, ) @@ -295,7 +283,49 @@ func renderScoreScreen(screen *ebiten.Image, snake *Snake, font *text.GoTextFace 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) fontOptions := &text.DrawOptions{}