package internal import ( "fmt" "image" "image/color" "github.com/hajimehoshi/ebiten/v2" ) type matchStatus uint8 const ( matchStatusNotStarted matchStatus = iota matchStatusInProgress matchStatusEnded ) // match represents the game match type match struct { status matchStatus ball *ball leftPaddle *paddle rightPaddle *paddle net *net score *score fonts *fonts } func newMatch(screenWidth, screenHeight int, f *fonts) *match { return &match{ ball: newBall(screenWidth, screenHeight), leftPaddle: newLeftPaddle(screenWidth, screenHeight, true), rightPaddle: newRightPaddle(screenWidth, screenHeight, false), net: &net{}, score: &score{ fonts: f, }, fonts: f, } } var backgroundColor = color.Black func (m *match) draw(img *ebiten.Image) { img.Fill(backgroundColor) switch m.status { case matchStatusNotStarted: bounds := img.Bounds() drawCenteredText( img, "Press space to start!", m.fonts.robotoRegularFont, bounds.Max.X/2, bounds.Max.Y/2, color.White, ) case matchStatusInProgress: m.ball.draw(img) m.leftPaddle.draw(img) m.rightPaddle.draw(img) m.score.draw(img) m.net.draw(img) case matchStatusEnded: bounds := img.Bounds() winLoseMessage := "You win!" if m.score.right >= requiredScoreToWin { winLoseMessage = "You lose :(." } drawCenteredText( img, winLoseMessage+" Press space to start!", m.fonts.robotoRegularFont, bounds.Max.X/2, bounds.Max.Y/2, color.White, ) } } const requiredScoreToWin = 1 //nolint:gocyclo func (m *match) update(bounds image.Rectangle) error { switch m.status { case matchStatusNotStarted: if ebiten.IsKeyPressed(ebiten.KeySpace) { m.status = matchStatusInProgress } case matchStatusInProgress: if err := m.ball.update(bounds, m.leftPaddle.bounds(), m.rightPaddle.bounds()); err != nil { return fmt.Errorf("couldn't update ball: %w", err) } if err := m.leftPaddle.update(bounds, m.ball); err != nil { return fmt.Errorf("couldn't update left paddle: %w", err) } if err := m.rightPaddle.update(bounds, m.ball); err != nil { return fmt.Errorf("couldn't update right paddle: %w", err) } if err := m.score.update(bounds, m.ball, m.leftPaddle, m.rightPaddle); err != nil { return fmt.Errorf("couldn't update score: %w", err) } if m.score.left >= requiredScoreToWin || m.score.right >= requiredScoreToWin { m.status = matchStatusEnded } case matchStatusEnded: if !ebiten.IsKeyPressed(ebiten.KeySpace) { return nil } m.ball.reset() m.leftPaddle.reset() m.rightPaddle.reset() m.score.reset() m.status = matchStatusInProgress } return nil } func (m *match) resize(x, y float32) { m.ball.resize(x, y) m.leftPaddle.resize(x, y) m.rightPaddle.resize(x, y) }