package systems import ( "openquell/assets" "openquell/components" . "openquell/components" "openquell/config" . "openquell/config" "openquell/observers" "github.com/hajimehoshi/ebiten/v2" "github.com/mlange-42/arche/ecs" "github.com/mlange-42/arche/generic" ) type CollectibleSystem struct { World *ecs.World Selector *generic.Filter3[Position, Collectible, Renderable] } func NewCollectibleSystem(world *ecs.World) System { system := &CollectibleSystem{ Selector: generic.NewFilter3[Position, Collectible, Renderable](), World: world, } return system } func (system *CollectibleSystem) Update() error { observer := observers.GetGameObserver(system.World) posID := ecs.ComponentID[components.Position](system.World) veloID := ecs.ComponentID[components.Velocity](system.World) particlepositions := []*components.Position{} EntitiesToRemove := []ecs.Entity{} query := system.Selector.Query(system.World) numcollectibles := query.Count() if numcollectibles == 0 || observer.Lost { query.Close() return nil } for query.Next() { colposition, _, _ := query.Get() for _, player := range observer.GetPlayers() { if !system.World.Alive(player) { continue } playerposition := (*Position)(system.World.Get(player, posID)) playervelocity := (*Velocity)(system.World.Get(player, veloID)) ok, _ := colposition.Intersects(playerposition, playervelocity) if ok { //slog.Debug("bumped into collectible", "collectible", collectible) particlepositions = append(particlepositions, colposition) EntitiesToRemove = append(EntitiesToRemove, query.Entity()) } } } for _, pos := range particlepositions { system.AddParticle(pos) } for _, entity := range EntitiesToRemove { system.World.RemoveEntity(entity) numcollectibles-- } if numcollectibles == 0 { // winner, winner, chicken dinner! timer := observers.GetGameObserver(system.World).StopTimer if !timer.Running { timer.Start(LEVEL_END_WAIT) } } return nil } func (system *CollectibleSystem) Draw(screen *ebiten.Image) { // write the movable tiles op := &ebiten.DrawImageOptions{} query := system.Selector.Query(system.World) for query.Next() { pos, _, sprite := query.Get() op.GeoM.Reset() op.GeoM.Translate(float64(pos.X), float64(pos.Y)) screen.DrawImage(sprite.Image, op) } } func (system *CollectibleSystem) AddParticle(position *components.Position) { observer := observers.GetGameObserver(system.World) ptmapper := generic.NewMap3[ components.Position, components.Particle, components.Timer, ](system.World) particleID := ecs.ComponentID[components.Particle](system.World) entity := ptmapper.New() pos, particle, timer := ptmapper.Get(entity) observer.AddEntity(entity, particleID) particle.Index = assets.Tiles["particle"].Particle particle.Tiles = assets.Tiles["particle"].Tiles pos.Update( position.X-(16), // FIXME: use global tilesize! position.Y-(16), 64, ) timer.Start(config.PARTICLE_LOOPWAIT) }