project-ely/internal/game/sprite/animation.go

99 lines
1.8 KiB
Go

package sprite
import (
"fmt"
"github.com/veandco/go-sdl2/sdl"
)
// animation defines a specific for an entity that references a sequence of sections of a sprite sheet.
// For example, walking to the left could be defined by 4 subsections of a sprite sheet.
type animation struct {
spritesheet *spritesheet
dimensions sdl.Point
offset sdl.Point
length int32
}
func NewAnimation(
filename string,
dimensions sdl.Point,
offset sdl.Point,
length int32,
) *animation {
spritesheet := GetSpritesheet(filename)
a := animation{
spritesheet: spritesheet,
dimensions: dimensions,
offset: offset,
length: length,
}
return &a
}
func (a *animation) Draw(frame int32, worldPosition *sdl.Point) error {
width := a.dimensions.X
height := a.dimensions.Y
base := sdl.Point{
X: width * a.offset.X,
Y: height * a.offset.Y,
}
// Assuming all frames are horizontal going left to right
f := frame % a.length
section := sdl.Rect{
X: base.X + f*width,
Y: base.Y,
W: width,
H: height,
}
err := a.checkBounds(&section)
if err != nil {
return err
}
// TODO convert to window position eventually
placement := sdl.Rect{
X: worldPosition.X,
Y: worldPosition.Y,
W: width,
H: height,
}
err = a.spritesheet.Draw(&section, &placement)
if err != nil {
return err
}
return nil
}
func (a *animation) checkBounds(section *sdl.Rect) error {
width := a.spritesheet.surface.W
height := a.spritesheet.surface.H
outOfBounds := false
if section.X < 0 {
outOfBounds = true
}
if section.Y < 0 {
outOfBounds = true
}
if section.X+section.W > width {
outOfBounds = true
}
if section.Y+section.H > height {
outOfBounds = true
}
if outOfBounds {
return fmt.Errorf("draw section was out of bounds - section: %v, image: %v", *section, a.spritesheet.surface.Bounds())
}
return nil
}