118 lines
1.8 KiB
Go
118 lines
1.8 KiB
Go
package hero
|
|
|
|
import (
|
|
"image/color"
|
|
"math"
|
|
|
|
"github.com/hajimehoshi/ebiten/v2"
|
|
"github.com/hajimehoshi/ebiten/v2/vector"
|
|
)
|
|
|
|
// Direction flags from the controls.
|
|
type Input struct {
|
|
Left bool
|
|
Right bool
|
|
Up bool
|
|
Down bool
|
|
}
|
|
|
|
// Playfield limits for movement.
|
|
type Bounds struct {
|
|
Width float64
|
|
Height float64
|
|
}
|
|
|
|
// Player avatar data.
|
|
type Hero struct {
|
|
X float64
|
|
Y float64
|
|
Radius float64
|
|
Speed float64
|
|
Color color.NRGBA
|
|
}
|
|
|
|
// Spawn settings for the avatar.
|
|
type Config struct {
|
|
StartX float64
|
|
StartY float64
|
|
Radius float64
|
|
Speed float64
|
|
Color color.NRGBA
|
|
}
|
|
|
|
// Builds an avatar from the config with fallbacks.
|
|
func New(cfg Config) *Hero {
|
|
if cfg.Radius <= 0 {
|
|
cfg.Radius = 24
|
|
}
|
|
if cfg.Speed <= 0 {
|
|
cfg.Speed = 180
|
|
}
|
|
if cfg.Color.A == 0 {
|
|
cfg.Color = color.NRGBA{R: 210, G: 220, B: 255, A: 255}
|
|
}
|
|
|
|
return &Hero{
|
|
X: cfg.StartX,
|
|
Y: cfg.StartY,
|
|
Radius: cfg.Radius,
|
|
Speed: cfg.Speed,
|
|
Color: cfg.Color,
|
|
}
|
|
}
|
|
|
|
// Applies movement input and clamps to the playfield.
|
|
func (h *Hero) Update(input Input, dt float64, bounds Bounds) {
|
|
dx, dy := 0.0, 0.0
|
|
|
|
if input.Left {
|
|
dx -= 1
|
|
}
|
|
if input.Right {
|
|
dx += 1
|
|
}
|
|
if input.Up {
|
|
dy -= 1
|
|
}
|
|
if input.Down {
|
|
dy += 1
|
|
}
|
|
|
|
if dx != 0 || dy != 0 {
|
|
length := math.Hypot(dx, dy)
|
|
dx /= length
|
|
dy /= length
|
|
}
|
|
|
|
h.X += dx * h.Speed * dt
|
|
h.Y += dy * h.Speed * dt
|
|
|
|
maxX := math.Max(h.Radius, bounds.Width-h.Radius)
|
|
maxY := math.Max(h.Radius, bounds.Height-h.Radius)
|
|
|
|
h.X = clamp(h.X, h.Radius, maxX)
|
|
h.Y = clamp(h.Y, h.Radius, maxY)
|
|
}
|
|
|
|
// Renders the avatar as a filled circle.
|
|
func (h *Hero) Draw(screen *ebiten.Image) {
|
|
vector.FillCircle(
|
|
screen,
|
|
float32(h.X),
|
|
float32(h.Y),
|
|
float32(h.Radius),
|
|
h.Color,
|
|
false,
|
|
)
|
|
}
|
|
|
|
func clamp(value, min, max float64) float64 {
|
|
if value < min {
|
|
return min
|
|
}
|
|
if value > max {
|
|
return max
|
|
}
|
|
return value
|
|
}
|