gg/animation.go

99 lines
2 KiB
Go

package gg
import (
"github.com/hajimehoshi/ebiten/v2"
//"fmt"
)
type Animation []*Image
type AnimationDefine struct{
Id AnimationId
Indexes []ImageRectIndex
}
// Animation define
func AD(id AnimationId, indexes ...ImageRectIndex) AnimationDefine {
return AnimationDefine{
Id: id,
Indexes: indexes,
}
}
func (ad AnimationDefine) DefRow(y int, xs ...int) AnimationDefine {
for _, x := range xs {
ad.Indexes = append(ad.Indexes, ImageRectIndex{x, y})
}
return ad
}
func (ad AnimationDefine) DefCol(x int, ys ...int) AnimationDefine {
for _, y := range ys {
ad.Indexes = append(ad.Indexes, ImageRectIndex{x, y})
}
return ad
}
type AnimationId int
type AnimationSet map[AnimationId] Animation
func AnimationSetFromImage(
img *Image,
w, h int,
defines ...AnimationDefine,
) (AnimationSet, error) {
set := AnimationSet{}
r := img.Bounds()
fw, fh := r.Dx()/w, r.Dy()/h
for _, define := range defines {
animation := make(Animation, len(define.Indexes))
for i := range animation {
idx := define.Indexes[i]
animation[i] = ebiten.NewImageFromImage(img.SubImage(
ImageRect{
Min: ImagePoint{idx.X*fw, idx.Y*fh},
Max: ImagePoint{(idx.X+1)*fw, (idx.Y+1)*fh},
},
))
}
set[define.Id] = animation
}
return set, nil
}
// The type implements animated sprites.
type AnimatedSprite struct {
Sprite
Animations AnimationSet
AnimationId AnimationId
CurrentFrame int
// This is time between animation frames, not
// engine ones.
TimeBetweenFrames Duration
duration Duration
}
func (as *AnimatedSprite) Animate(id AnimationId) bool {
if as.AnimationId == id {
return true
}
_, ok := as.Animations[id]
if ok {
as.duration = 0
as.AnimationId = id
}
return ok
}
func (as *AnimatedSprite) Draw(c *Context) []EVertex {
as.duration += c.DrawDt()
frames := as.Animations[as.AnimationId]
fullTime := Duration(len(frames)) * as.TimeBetweenFrames
if as.duration > fullTime {
as.duration -= fullTime
}
as.Images[0] = frames[(as.duration/as.TimeBetweenFrames)%Duration(len(frames))]
return as.Sprite.Draw(c)
}