Animation Player
The AnimationPlayer drives sprite animations using a tick-based timing model.
You define animation clips (lists of frame indices with a playback speed), then
the player steps through them each time you call Advance.
Core Types
AnimationClip
An AnimationClip describes a single animation sequence:
type AnimationClip struct {
Name string
FPS uint16
Frames []uint16
}
| Field | Description |
|---|---|
Name | Human-readable label (e.g. "idle", "walk") |
FPS | Playback speed in frames per second |
Frames | Ordered list of sprite sheet frame indices |
Clips are typically loaded from a .anim file via an AnimationSet, but you
can also build them by hand:
walkClip := gosprite64.AnimationClip{
Name: "walk",
FPS: 10,
Frames: []uint16{0, 1, 2, 3},
}
AnimationSet
An AnimationSet groups related clips loaded from a compiled .anim file.
You get one from a bundle:
animSet, err := bundle.LoadAnimation("anims")
if err != nil {
panic(err)
}
idle, ok := animSet.Clip("idle")
walk, ok := animSet.Clip("walk")
Clips() returns all clips in the set. Clip(name) returns a single clip
by name along with a boolean indicating whether it was found.
Creating a Player
func NewAnimationPlayer() *AnimationPlayer
Creates a stopped player with no clip loaded.
player := gosprite64.NewAnimationPlayer()
Playback Controls
Play
func (p *AnimationPlayer) Play(clip AnimationClip)
Starts playing the given clip from frame 0. If the clip has no frames, the player stops.
player.Play(walkClip)
Pause / Resume
func (p *AnimationPlayer) Pause()
func (p *AnimationPlayer) Resume()
Pause freezes the animation at its current frame. Resume continues from
where it left off. Calling Pause when not playing (or Resume when not
paused) is a no-op.
Stop
func (p *AnimationPlayer) Stop()
Stops playback and resets to frame 0.
Restart
func (p *AnimationPlayer) Restart()
Jumps back to frame 0 and starts playing. Useful for retriggering an animation without constructing a new clip.
SetLoop
func (p *AnimationPlayer) SetLoop(loop bool)
When looping is enabled, the animation wraps around to frame 0 after the last frame. When disabled (the default), the player stops on the last frame.
player.SetLoop(true)
player.Play(idleClip) // will loop forever
Advancing Time
func (p *AnimationPlayer) Advance(ticks int)
Call Advance once per game tick (typically once per frame in your Update
function). The player uses an internal accumulator to convert ticks into
frame steps based on the clip's FPS.
The timing math assumes a 60-tick-per-second base rate. A clip with
FPS: 10 advances one animation frame every 6 ticks. A clip with FPS: 30
advances one frame every 2 ticks.
func (g *Game) Update() {
g.player.Advance(1) // one tick per game frame
}
Passing ticks <= 0 or calling Advance on a stopped/paused player is a
no-op.
Reading State
Frame
func (p *AnimationPlayer) Frame() int
Returns the current sprite sheet frame index. Use this with DrawSprite:
frame := player.Frame()
gosprite64.DrawSprite(sheet, frame, x, y)
Playing / Done
func (p *AnimationPlayer) Playing() bool
func (p *AnimationPlayer) Done() bool
| Method | Returns true when... |
|---|---|
Playing() | The player is actively advancing frames |
Done() | The player is stopped (finished or never started) |
These are useful for triggering events at the end of one-shot animations:
if player.Done() {
// switch to the next game state
}
Complete Example
type Game struct {
sheet *gosprite64.SpriteSheet
player *gosprite64.AnimationPlayer
idle gosprite64.AnimationClip
walk gosprite64.AnimationClip
flipH bool
moving bool
}
func (g *Game) Init() {
sheet, err := gosprite64.LoadSpriteSheet("assets/character.sheet")
if err != nil {
panic(err)
}
g.sheet = sheet
g.idle = gosprite64.AnimationClip{
Name: "idle", FPS: 6, Frames: []uint16{0, 1},
}
g.walk = gosprite64.AnimationClip{
Name: "walk", FPS: 10, Frames: []uint16{2, 3, 4, 5},
}
g.player = gosprite64.NewAnimationPlayer()
g.player.SetLoop(true)
g.player.Play(g.idle)
}
func (g *Game) Update() {
g.moving = false
if gosprite64.IsButtonDown(gosprite64.ButtonDPadRight) {
g.moving = true
g.flipH = false
}
if gosprite64.IsButtonDown(gosprite64.ButtonDPadLeft) {
g.moving = true
g.flipH = true
}
if g.moving {
g.player.Play(g.walk)
} else {
g.player.Play(g.idle)
}
g.player.Advance(1)
}
func (g *Game) Draw() {
gosprite64.ClearScreen()
frame := g.player.Frame()
gosprite64.DrawSpriteWithOptions(g.sheet, frame, 136, 100, gosprite64.DrawSpriteOptions{
FlipH: g.flipH,
})
}
Compiling Animation Data
Use mk2danim to compile a JSON animation definition into a binary .anim
file:
go run github.com/drpaneas/gosprite64/cmd/mk2danim \
-in anims.json \
-out anims.anim
The JSON format defines clips with frame lists and FPS:
{
"clips": [
{ "name": "idle", "fps": 6, "frames": [0, 1] },
{ "name": "walk", "fps": 10, "frames": [2, 3, 4, 5] }
]
}