added player loop detection, loose level if last player loops

This commit is contained in:
2024-02-27 18:20:00 +01:00
parent 5d2475d525
commit 707281212a
6 changed files with 76 additions and 25 deletions

View File

@@ -18,13 +18,16 @@ type PlayerSystem struct {
World *ecs.World
Selector *generic.Filter4[Position, Velocity, Player, Renderable]
GridContainer *grid.GridContainer
Width, Height int
}
func NewPlayerSystem(world *ecs.World, gridcontainer *grid.GridContainer) System {
func NewPlayerSystem(world *ecs.World, gridcontainer *grid.GridContainer, width, height int) System {
system := &PlayerSystem{
Selector: generic.NewFilter4[Position, Velocity, Player, Renderable](),
GridContainer: gridcontainer,
World: world,
Width: width,
Height: height,
}
return system
@@ -48,7 +51,7 @@ func (system PlayerSystem) Update() error {
}
// check if the user alters or initiates movement
system.CheckMovement(velocity)
system.CheckMovement(playerposition, velocity, player)
// check if player collides with walls or edges
system.CheckGridCollision(playerposition, velocity)
@@ -56,6 +59,15 @@ func (system PlayerSystem) Update() error {
if count > 1 {
// check if player collides with another player, fuse them if any
EntitiesToRemove = system.CheckPlayerCollision(playerposition, velocity, query.Entity())
} else {
// only 1 player left or one is max
EntitiesToRemove = system.CheckPlayerLooping(
playerposition, velocity, player, query.Entity())
}
if !velocity.Moving() {
// disable loop detection
player.LoopCount = 0
}
}
@@ -130,17 +142,33 @@ func (system *PlayerSystem) SwitchPlayers() {
}
}
func (system *PlayerSystem) CheckMovement(velocity *components.Velocity) {
func (system *PlayerSystem) CheckMovement(
position *components.Position,
velocity *components.Velocity,
player *components.Player) {
moved := false
if !velocity.Moving() {
switch {
case ebiten.IsKeyPressed(ebiten.KeyRight):
velocity.Change(East)
moved = true
case ebiten.IsKeyPressed(ebiten.KeyLeft):
velocity.Change(West)
moved = true
case ebiten.IsKeyPressed(ebiten.KeyDown):
velocity.Change(South)
moved = true
case ebiten.IsKeyPressed(ebiten.KeyUp):
velocity.Change(North)
moved = true
}
if moved {
// will be reset every time the user initiates player movement
player.LoopPos.Set(position)
player.LoopCount = 0
}
}
}
@@ -161,9 +189,6 @@ func (system *PlayerSystem) CheckGridCollision(
tilepos.Point(), "playerpos", playerposition)
intersects, newpos := tilepos.Intersects(playerposition, velocity)
if intersects {
// slog.Debug("collision detected", "tile",
// tilepos, "player", playerposition, "new", newpos)
playerposition.Set(newpos)
velocity.Change(Stop)
}
@@ -202,3 +227,39 @@ func (system *PlayerSystem) CheckPlayerCollision(
// FIXME: add an animation highlighting the fusion
return EntitiesToRemove
}
func (system *PlayerSystem) CheckPlayerLooping(
position *components.Position,
velocity *components.Velocity,
player *components.Player,
entity ecs.Entity) []ecs.Entity {
if player.LoopPos.Rect == nil {
// hasn't moved
return nil
}
EntitiesToRemove := []ecs.Entity{}
ok, _ := player.LoopPos.Intersects(position, velocity)
if ok {
// Fatal: loop detected with last player
player.LoopStart = true
} else {
// no intersection with old pos anymore
if player.LoopStart {
// loop detection active
player.LoopCount++
max := system.Width
if velocity.Direction == North || velocity.Direction == South {
max = system.Height
}
// we haved moved one time around the whole screen, loose
if (player.LoopCount * velocity.Speed) > max {
EntitiesToRemove = append(EntitiesToRemove, entity)
}
}
}
return EntitiesToRemove
}