128 lines
2.7 KiB
Go
128 lines
2.7 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
|
|
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),
|
|
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)
|
|
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)
|
|
}
|