package systems import ( "log/slog" "openquell/components" . "openquell/components" "github.com/hajimehoshi/ebiten/v2" "github.com/mlange-42/arche/ecs" "github.com/mlange-42/arche/generic" ) type AnimationSystem struct { World *ecs.World Selector *generic.Filter2[Position, Renderable] Cellsize int } func NewAnimationSystem(world *ecs.World, cellsize int) System { system := &AnimationSystem{ Selector: generic.NewFilter2[Position, Renderable](), World: world, Cellsize: cellsize, } return system } func (system *AnimationSystem) Update() error { EntitiesToRemove := []ecs.Entity{} query := system.Selector.Query(system.World) for query.Next() { _, render := query.Get() for animationtype, animate := range render.Animations() { if animate.Active { if animate.Timer.IsReady() { switch { // animation shows from earlier tick, animate case animate.Index > -1 && animate.Index < len(animate.Sprites)-1: animate.Index += 1 animate.Timer.Start(animate.GetDuration()) default: // last sprite reached if animate.Loop { animate.Index = 0 animate.Timer.Start(animate.GetDuration()) } if animationtype == components.Destruction { EntitiesToRemove = append(EntitiesToRemove, query.Entity()) } } } else { animate.Timer.Update() } } } } for _, entity := range EntitiesToRemove { slog.Debug("remove collectible") system.World.RemoveEntity(entity) } return nil } func (system *AnimationSystem) Draw(screen *ebiten.Image) { // write animations (these are no tiles!) op := &ebiten.DrawImageOptions{} query := system.Selector.Query(system.World) for query.Next() { pos, render := query.Get() for _, animate := range render.Animations() { if animate.Active { op.GeoM.Reset() op.GeoM.Translate(float64(pos.X), float64(pos.Y)) sprite := animate.GetSprite() screen.DrawImage(sprite, op) } } } }