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, gx, gy 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+gx, idx.Y*fh+gy}, Max: ImagePoint{(idx.X+1)*fw-gx, (idx.Y+1)*fh-gy}, }, )) } 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) }