added player loop detection, loose level if last player loops
This commit is contained in:
parent
5d2475d525
commit
707281212a
14
TODO.md
14
TODO.md
@ -2,9 +2,6 @@
|
||||
|
||||
- ignore comments in lvl files
|
||||
|
||||
- check when sphere bounces from one end to the other endlessly w/o
|
||||
any solids in between. this is a game lock and equals game over
|
||||
|
||||
- Start the game end timer and add a score FIXME: put the actual max
|
||||
reachable score into the level definition along with the minimum
|
||||
steps required to reach it, also add a step counter
|
||||
@ -15,19 +12,8 @@
|
||||
- Add some final message when the player reaches the last level, start
|
||||
from scratch or a message to buy me some beer, whatever
|
||||
|
||||
- Check player-player collisions!
|
||||
|
||||
- Add player mergers, possibly as an option, so maybe we could have
|
||||
different primary and secondary players: one pair can merge, the
|
||||
other not. Like S + s and M + m or something.
|
||||
|
||||
- Add shaders for animation (player destruction etc)
|
||||
|
||||
- Add player HUD + Stats (as hud_system!)
|
||||
|
||||
- Entity Observers don't work, removed entities remain there, errors
|
||||
about dead entities, had to add Alive checks, and in obstacle_system
|
||||
even remove the player manually from the world.
|
||||
|
||||
|
||||
## Collider Rework
|
||||
|
||||
@ -4,14 +4,14 @@ Background: background-lila
|
||||
|
||||
|
||||
|
||||
#
|
||||
W
|
||||
|
||||
|
||||
S
|
||||
S # o
|
||||
|
||||
|
||||
|
||||
#
|
||||
|
||||
|
||||
o
|
||||
#
|
||||
|
||||
|
||||
@ -5,6 +5,9 @@ import "github.com/hajimehoshi/ebiten/v2"
|
||||
type Player struct {
|
||||
IsPrimary bool
|
||||
Sprites []*ebiten.Image
|
||||
LoopPos *Position
|
||||
LoopStart bool
|
||||
LoopCount int
|
||||
}
|
||||
|
||||
func (player *Player) SwitchSprite() *ebiten.Image {
|
||||
|
||||
@ -44,7 +44,7 @@ func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
|
||||
systemlist = append(systemlist, systems.NewObstacleSystem(game.World, gridcontainer))
|
||||
|
||||
systemlist = append(systemlist,
|
||||
systems.NewPlayerSystem(game.World, gridcontainer))
|
||||
systems.NewPlayerSystem(game.World, gridcontainer, game.ScreenWidth, game.ScreenHeight))
|
||||
|
||||
systemlist = append(systemlist, systems.NewParticleSystem(game.World, game.Cellsize))
|
||||
|
||||
|
||||
@ -90,6 +90,7 @@ func NewGrid(world *ecs.World,
|
||||
vel.Speed = config.PLAYERSPEED
|
||||
player.IsPrimary = tile.IsPrimary
|
||||
player.Sprites = tile.Tiles
|
||||
player.LoopPos = &components.Position{Cellsize: tilesize}
|
||||
case tile.Collectible:
|
||||
entity := colmapper.New()
|
||||
pos, render, _ = colmapper.Get(entity)
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user