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

106 lines
1.9 KiB
Go

package sprite
import (
"fmt"
"github.com/veandco/go-sdl2/sdl"
)
// spriteAnimation specifies which subsections of a spritesheet define this animation.
// For example, walking to the right could be defined by 4 subsections of a sprite sheet.
type spriteAnimation struct {
spritesheet *spritesheet
dimensions sdl.Point
offset sdl.Point
length int32
}
func NewAnimation(
filename string,
dimensions sdl.Point,
offset sdl.Point,
length int32,
) *spriteAnimation {
spritesheet := GetSpritesheet(filename)
a := spriteAnimation{
spritesheet: spritesheet,
dimensions: dimensions,
offset: offset,
length: length,
}
return &a
}
func (a *spriteAnimation) Draw(
frame int32,
windowPosition *sdl.Point,
angle float64,
center *sdl.Point,
flip sdl.RendererFlip,
) 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
}
placement := sdl.Rect{
X: windowPosition.X,
Y: windowPosition.Y,
W: width,
H: height,
}
err = a.spritesheet.Draw(&section, &placement, angle, center, flip)
if err != nil {
return err
}
return nil
}
func (a *spriteAnimation) 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
}