tennis-game/internal/match.go

131 lines
2.8 KiB
Go

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)
}