package main
import (
"github.com/dfirebaugh/tortuga"
"github.com/dfirebaugh/tortuga/pkg/component"
"github.com/dfirebaugh/tortuga/pkg/input"
"github.com/dfirebaugh/tortuga/pkg/math/geom"
)
type entity interface {
Update()
Render()
}
type cart struct {
entities []entity
Game tortuga.Console
}
func (c cart) Update() {
for _, e := range c.entities {
e.Update()
}
}
func (c cart) Render() {
c.Game.Clear()
for _, e := range c.entities {
e.Render()
}
}
const (
paddleSpeed = 3
ballSpeed = 1.1
)
var (
game = tortuga.New()
ball = Ball{
Coordinate: component.Coordinate{
X: float64(game.GetScreenWidth()) / 2,
Y: float64(game.GetScreenHeight()) / 2,
},
Velocity: component.Velocity{
VX: ballSpeed,
VY: ballSpeed,
},
Game: game,
}
player = paddle{
Game: game,
Coordinate: component.Coordinate{X: 10, Y: 10},
Height: 30,
Width: 5,
Mover: playerMover{
Game: game,
},
BallPosition: &ball.Coordinate,
Speed: paddleSpeed,
}
enemy = paddle{
Game: game,
Coordinate: component.Coordinate{X: float64(game.GetScreenWidth()) - 20, Y: 10},
Height: 30,
Width: 5,
Mover: enemyMover{
Game: game,
},
BallPosition: &ball.Coordinate,
Speed: paddleSpeed,
}
)
func main() {
game.Run(&cart{
Game: game,
entities: []entity{
&ball,
&player,
&enemy,
},
})
}
type Ball struct {
component.Coordinate
component.Velocity
Game tortuga.Console
}
func (b *Ball) Reset() {
b.Coordinate.X = float64(game.GetScreenWidth()) / 2
b.Coordinate.Y = float64(game.GetScreenHeight()) / 2
b.VX = ballSpeed
b.VY = ballSpeed
}
func (b *Ball) Update() {
if b.Coordinate.Y < 0 {
b.VY *= -ballSpeed
}
if b.Coordinate.Y > float64(b.Game.GetScreenHeight()) {
b.VY *= -ballSpeed
}
if b.Coordinate.X > float64(b.Game.GetScreenWidth()) || b.Coordinate.X < 0 {
b.Reset()
}
collisionBox := geom.MakeRect(b.X-4, b.Y-4, 4, 4)
if collisionBox.IsAxisAlignedCollision(geom.MakeRect(enemy.X, enemy.Y, enemy.Width, enemy.Height)) ||
collisionBox.IsAxisAlignedCollision(geom.MakeRect(player.X, player.Y, player.Width, player.Height)) {
b.VX *= -ballSpeed
}
b.Coordinate.Y += b.VY
b.Coordinate.X += b.VX
}
func (b Ball) Render() {
geom.MakeCircle(b.X, b.Y, 1).Filled(b.Game.GetDisplay(), b.Game.Color(4))
}
type mover interface {
Move(paddlePosition component.Coordinate, ballPosition component.Coordinate, speed float64) (x float64, y float64)
}
type playerMover struct {
input input.Keyboard
Game tortuga.Console
}
type enemyMover struct {
Game tortuga.Console
}
func (p playerMover) Move(paddlePosition component.Coordinate, ballPosition component.Coordinate, speed float64) (x float64, y float64) {
if p.input.IsDownPressed() {
return 0, speed
}
if p.input.IsUpPressed() {
return 0, -speed
}
if p.input.IsLeftPressed() {
return -speed, 0
}
if p.input.IsRightPressed() {
return speed, 0
}
return 0, 0
}
func (e enemyMover) Move(paddlePosition component.Coordinate, ballPosition component.Coordinate, speed float64) (x float64, y float64) {
if ballPosition.Y-10 > paddlePosition.Y {
return 0, speed
}
return 0, -speed
}
type paddle struct {
component.Coordinate
Mover mover
Game tortuga.Console
Speed float64
BallPosition *component.Coordinate
Height float64
Width float64
}
func (p *paddle) Update() {
x, y := p.Mover.Move(p.Coordinate, *p.BallPosition, p.Speed)
p.Coordinate.X += x
p.Coordinate.Y += y
}
func (p paddle) Render() {
geom.MakeRect(p.X, p.Y, p.Width, p.Height).Filled(p.Game.GetDisplay(), p.Game.Color(4))
}