tennis-game/internal/game.go

129 lines
2.7 KiB
Go

package internal
import (
"fmt"
"image"
"image/color"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
)
const (
BaseWidth = 640
BaseHeight = 360
)
type Game struct {
width int
height int
ball *ball
leftPaddle *paddle
rightPaddle *paddle
debug bool
img *ebiten.Image
}
var _ ebiten.Game = (*Game)(nil)
func NewGame(width, height int, debug bool) *Game {
return &Game{
width: width,
height: height,
ball: newBall(width, height),
leftPaddle: newLeftPaddle(width, height, true),
rightPaddle: newRightPaddle(width, height, false),
debug: debug,
}
}
func (g *Game) Update() error {
bounds := image.Rect(0, 0, g.width, g.height)
if err := g.ball.update(bounds); err != nil {
return fmt.Errorf("couldn't update ball: %w", err)
}
if err := g.leftPaddle.update(bounds, g.ball); err != nil {
return fmt.Errorf("couldn't update left paddle: %w", err)
}
if err := g.rightPaddle.update(bounds, g.ball); err != nil {
return fmt.Errorf("couldn't update right paddle: %w", err)
}
return nil
}
var backgroundColor = color.Black
func (g *Game) Draw(screen *ebiten.Image) {
if g.img == nil {
g.img = ebiten.NewImage(g.width, g.height)
}
g.img.Fill(backgroundColor)
g.ball.draw(g.img)
g.leftPaddle.draw(g.img)
g.rightPaddle.draw(g.img)
if g.debug {
g.drawDebug()
}
screen.DrawImage(g.img, nil)
}
func (g *Game) drawDebug() {
ebitenutil.DebugPrint(
g.img,
fmt.Sprintf(
"FPS: %0.2f"+
"\nBall: x=%v, y=%v, speedX=%v, speedY=%v, radius=%v"+
"\nLeft paddle: x=%v, y=%v, speed=%v, width=%v, height=%v, isControlledByPlayer=%v"+
"\nRight paddle: x=%v, y=%v, speed=%v, width=%v, height=%v, isControlledByPlayer=%v",
ebiten.ActualFPS(),
g.ball.x,
g.ball.y,
g.ball.speedX,
g.ball.speedY,
g.ball.r,
g.leftPaddle.x,
g.leftPaddle.y,
g.leftPaddle.speed,
g.leftPaddle.width,
g.leftPaddle.height,
g.leftPaddle.isControlledByPlayer,
g.rightPaddle.x,
g.rightPaddle.y,
g.rightPaddle.speed,
g.rightPaddle.width,
g.rightPaddle.height,
g.rightPaddle.isControlledByPlayer,
),
)
}
//nolint:nonamedreturns
func (g *Game) Layout(outsideWidth, outsideHeight int) (_screenWidth, _screenHeight int) {
if g.width != outsideWidth || g.height != outsideHeight {
ratioWidth := float32(outsideWidth) / float32(g.width)
ratioHeight := float32(outsideHeight) / float32(g.height)
g.ball.resize(ratioWidth, ratioHeight)
g.leftPaddle.resize(ratioWidth, ratioHeight)
g.rightPaddle.resize(ratioWidth, ratioHeight)
if g.img != nil {
g.img.Dispose()
g.img = nil
}
g.width = outsideWidth
g.height = outsideHeight
}
return outsideWidth, outsideHeight
}