127 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package systems
 | |
| 
 | |
| import (
 | |
| 	"log/slog"
 | |
| 	"openquell/components"
 | |
| 	. "openquell/components"
 | |
| 	. "openquell/config"
 | |
| 
 | |
| 	"openquell/grid"
 | |
| 	"openquell/observers"
 | |
| 
 | |
| 	"github.com/hajimehoshi/ebiten/v2"
 | |
| 	"github.com/mlange-42/arche/ecs"
 | |
| 	"github.com/mlange-42/arche/generic"
 | |
| )
 | |
| 
 | |
| type DestroyableSystem struct {
 | |
| 	World         *ecs.World
 | |
| 	Selector      *generic.Filter3[Position, Renderable, Destroyable]
 | |
| 	GridContainer *grid.GridContainer
 | |
| 	SolidMapper   generic.Map4[ // needed for replacement
 | |
| 		components.Position,
 | |
| 		components.Renderable,
 | |
| 		components.Tilish,
 | |
| 		components.Solid]
 | |
| 	Cellsize int
 | |
| }
 | |
| 
 | |
| type DoorToRemove struct {
 | |
| 	Entity   ecs.Entity
 | |
| 	Position *components.Position
 | |
| }
 | |
| 
 | |
| func NewDestroyableSystem(world *ecs.World, gridcontainer *grid.GridContainer,
 | |
| 	cellsize int) System {
 | |
| 
 | |
| 	solidmapper := generic.NewMap4[
 | |
| 		components.Position,
 | |
| 		components.Renderable,
 | |
| 		components.Tilish,
 | |
| 		components.Solid](world)
 | |
| 
 | |
| 	system := &DestroyableSystem{
 | |
| 		Selector:      generic.NewFilter3[Position, Renderable, Destroyable](),
 | |
| 		World:         world,
 | |
| 		GridContainer: gridcontainer,
 | |
| 		SolidMapper:   solidmapper,
 | |
| 		Cellsize:      cellsize,
 | |
| 	}
 | |
| 
 | |
| 	return system
 | |
| }
 | |
| 
 | |
| func (system *DestroyableSystem) Update() error {
 | |
| 	observer := observers.GetGameObserver(system.World)
 | |
| 	posID := ecs.ComponentID[components.Position](system.World)
 | |
| 	veloID := ecs.ComponentID[components.Velocity](system.World)
 | |
| 
 | |
| 	query := system.Selector.Query(system.World)
 | |
| 
 | |
| 	EntitiestoRemove := []*DoorToRemove{}
 | |
| 
 | |
| 	for query.Next() {
 | |
| 		doorposition, renderable, door := 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, newpos := doorposition.Intersects(playerposition, playervelocity)
 | |
| 			if ok {
 | |
| 				// player bumped into hidden wall, activate it, snap in player
 | |
| 				slog.Debug("bump not die", "originalpos", playerposition)
 | |
| 				playervelocity.Change(Stop)
 | |
| 				playerposition.Set(newpos)
 | |
| 
 | |
| 				if door.Activated {
 | |
| 					// player bumps into the door a second time, now hide it
 | |
| 					EntitiestoRemove = append(EntitiestoRemove,
 | |
| 						&DoorToRemove{Entity: query.Entity(), Position: doorposition})
 | |
| 				} else {
 | |
| 					slog.Debug("activating destroyable", "doorpos", doorposition)
 | |
| 					door.Activated = true
 | |
| 					renderable.Damaged = 1
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	for _, door := range EntitiestoRemove {
 | |
| 		slog.Debug("hiding destroyable", "doorpos", door.Position.Point())
 | |
| 
 | |
| 		// remove door entity
 | |
| 		system.World.RemoveEntity(door.Entity)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (system *DestroyableSystem) Draw(screen *ebiten.Image) {
 | |
| 	// write transients (these are no tiles!)
 | |
| 	op := &ebiten.DrawRectShaderOptions{}
 | |
| 
 | |
| 	query := system.Selector.Query(system.World)
 | |
| 
 | |
| 	for query.Next() {
 | |
| 		pos, render, _ := query.Get()
 | |
| 
 | |
| 		op.GeoM.Reset()
 | |
| 
 | |
| 		op.Uniforms = map[string]any{
 | |
| 			"Damaged": render.Damaged,
 | |
| 		}
 | |
| 
 | |
| 		op.Images[0] = render.Image
 | |
| 		op.Images[1] = render.DamageImage
 | |
| 
 | |
| 		op.GeoM.Translate(float64(pos.X), float64(pos.Y))
 | |
| 
 | |
| 		screen.DrawRectShader(system.Cellsize, system.Cellsize, render.Shader, op)
 | |
| 	}
 | |
| }
 |