breakout/main.go
Ruidy 1c901e7e07
chore(deps): update Go and Ebiten dependencies
Upgrade Go version to 1.25.3 and bump Ebiten to v2.9.3. Update related
dependencies to their latest versions, including purego, xgb, image,
sync,
and sys. Add new indirect dependencies: gomobile and hideconsole.
2025-11-02 22:39:00 +01:00

129 lines
2.5 KiB
Go

package main
import (
"image/color"
"log"
"strconv"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/hajimehoshi/ebiten/v2/vector"
)
const (
screenWidth = 640
screenHeight = 480
)
type Game struct {
paddle paddle
ball ball
bricks []brick
score int
gameOver bool
initialized bool
victory bool
}
func (g *Game) init() {
g.paddle = newPaddle()
g.ball = newBall()
g.bricks = initBricks()
g.initialized = true
}
func (g *Game) Update() error {
if !g.initialized {
g.init()
}
if g.gameOver {
if ebiten.IsKeyPressed(ebiten.KeySpace) {
g.init()
g.gameOver = false
g.score = 0
}
return nil
}
// Update paddle position based on input
if ebiten.IsKeyPressed(ebiten.KeyLeft) {
g.paddle.moveLeft()
}
if ebiten.IsKeyPressed(ebiten.KeyRight) {
g.paddle.moveRight()
}
g.paddle.keepWithinBounds()
g.ball.updatePosition()
g.ball.checkWallCollision()
g.ball.checkPaddleCollision(g.paddle)
// Ball collision with bricks
for i := range g.bricks {
if !g.bricks[i].active {
continue
}
if g.ball.x+g.ball.size >= g.bricks[i].x &&
g.ball.x <= g.bricks[i].x+g.bricks[i].width &&
g.ball.y+g.ball.size >= g.bricks[i].y &&
g.ball.y <= g.bricks[i].y+g.bricks[i].height {
g.bricks[i].active = false
g.ball.dy = -g.ball.dy
g.score += g.bricks[i].score
}
}
if g.ball.y > screenHeight {
g.gameOver = true
}
// Check for victory condition
victory := true
for _, brick := range g.bricks {
if brick.active {
victory = false
break
}
}
g.victory = victory
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
vector.FillRect(screen, g.paddle.x, g.paddle.y, g.paddle.width, g.paddle.height, color.White, true)
vector.FillRect(screen, g.ball.x, g.ball.y, g.ball.size, g.ball.size, color.White, true)
for _, brick := range g.bricks {
if brick.active {
vector.FillRect(screen, brick.x, brick.y, brick.width, brick.height, brick.color, true)
}
}
// Draw score and game over text
if g.victory {
ebitenutil.DebugPrint(screen, "Victory! Press SPACE to restart")
} else if g.gameOver {
ebitenutil.DebugPrint(screen, "Game Over! Press SPACE to restart")
} else {
ebitenutil.DebugPrint(screen, "Score: "+strconv.Itoa(g.score))
}
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
}
func main() {
ebiten.SetWindowSize(screenWidth, screenHeight)
ebiten.SetWindowTitle("Breakout")
game := &Game{}
if err := ebiten.RunGame(game); err != nil {
log.Fatal(err)
}
}