feat(player): join in progress + DISABLED en agotar vidas (Fase 1)
Habilita la regla 1 de la nova FSM de joc: durant PLAYING, qualsevol
slot DISABLED pot pulsar START per entrar a partida amb spawn aeri al
seu costat de la porta i vides reseteades. Quan un jugador esgota les
vides, `respawnFromDying` el deixa a DISABLED i publica `player_disabled`
al bus; GameScene i HUD reaccionen, deixant el slot disponible per a un
nou join. Afegeix prompts al HUD ("PULSA START / PER JUGAR" o
"ESPERA / PER JUGAR") segons l'estat de la RoomFsm.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
8921b9fd0c
commit
c13b11c501
12 files changed
+325
-56
No files matched your search
@@ -1270,11 +1270,30 @@ void Player::applyDyingMovement(float delta_time) {
|
||||
}
|
||||
}
|
||||
|
||||
void Player::resetForJoin() {
|
||||
lives_remaining_ = death_config.initial_lives;
|
||||
}
|
||||
|
||||
void Player::respawnFromDying() {
|
||||
// Vides: decreix sempre. Pot anar a negatius — no hi ha game over.
|
||||
// Vides: decreix una unitat. Si el comptador arriba a 0 el jugador
|
||||
// surt de partida (DISABLED) i la GameScene/HUD reaccionen via bus
|
||||
// — això habilita el flux de "join in progress" (l'altre jugador
|
||||
// pot pulsar START per entrar) i obrirà el camí al CONTINUE? +
|
||||
// GAME OVER en una fase posterior.
|
||||
--lives_remaining_;
|
||||
death_animation_complete_ = false;
|
||||
respawn_remaining_ms_ = 0.0F;
|
||||
if (lives_remaining_ <= 0) {
|
||||
disable();
|
||||
if (bus_ != nullptr) {
|
||||
bus_->publish(Event{
|
||||
.name = "player_disabled",
|
||||
.payload = std::monostate{},
|
||||
.player_id = id_,
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Cinemàtica idèntica a la d'INTRO de sala: el jugador cau des de
|
||||
// dalt fins al passadís d'spawn (`spawnFromAir` reseteja primer i
|
||||
// després posa AIRBORNE amb l'altura derivada de la geometria).
|
||||
|
||||
@@ -296,8 +296,11 @@ class Player : public AnimatedSprite {
|
||||
// `death_spinning`, posició congelada, input ignorat. Idempotent —
|
||||
// si ja està DYING, EXITED o DISABLED, és no-op (un segon toc de
|
||||
// momia mentre la roda no la reinicia). Quan l'animació acaba i
|
||||
// `respawn_delay_ms` expira, `respawn(spawn_x_, spawn_y_)` torna a
|
||||
// GROUNDED i `lives_remaining_` decreix en 1 (pot anar a negatius).
|
||||
// `respawn_delay_ms` expira, `respawnFromDying()` decrementa
|
||||
// `lives_remaining_`: si encara queden vides, fa `spawnFromAir`
|
||||
// al spawn point; si arriba a 0, fa `disable()` i publica al bus
|
||||
// `player_disabled` perquè GameScene/HUD reaccionin (slot fora de
|
||||
// partida, esperant un nou START per re-entrar via "join in progress").
|
||||
void enterDying(DeathCause cause = DeathCause::GENERIC);
|
||||
|
||||
// Coordenades del spawn de respawn (cantó superior-esquerra del
|
||||
@@ -309,9 +312,11 @@ class Player : public AnimatedSprite {
|
||||
spawn_y_ = y;
|
||||
}
|
||||
|
||||
// Comptador d'intents (estil Mario, NO HP). Decreix a cada respawn;
|
||||
// no es clampa a 0 — permet anar a negatius perquè avui no hi ha
|
||||
// game over. Públic per a HUD i tests.
|
||||
// Comptador d'intents (estil Mario, NO HP). Decreix a cada respawn
|
||||
// post-mort. En arribar a 0 el jugador passa a DISABLED i publica
|
||||
// `player_disabled` al bus; pot tornar a partida via "join in
|
||||
// progress" (GameScene::joinPlayer crida `resetForJoin`). Públic
|
||||
// per a HUD i tests.
|
||||
[[nodiscard]] auto getLivesRemaining() const -> int { return lives_remaining_; }
|
||||
|
||||
// Activa la immunitat per `duration_ms` ms. Mentre `isImmune()` és
|
||||
@@ -342,6 +347,14 @@ class Player : public AnimatedSprite {
|
||||
// sala usa `disable()` + `spawnFromAir()`.
|
||||
void respawn(float x, float y);
|
||||
|
||||
// Restaura el comptador de vides al valor inicial configurat
|
||||
// (`death_config.initial_lives`). Cridat per la GameScene quan un
|
||||
// slot inactiu pulsa START per entrar mid-partida (regla 6 de la
|
||||
// FSM de joc): el jugador entra amb les vides plenes. La resta de
|
||||
// l'estat (posició, animació, flags) la reseteja `spawnFromAir`
|
||||
// que GameScene crida tot seguit.
|
||||
void resetForJoin();
|
||||
|
||||
// Posa el jugador en el slot inactiu (DISABLED). Idempotent: la
|
||||
// segona crida és no-op. Mateix patró que `exit()` per simetria.
|
||||
// No publica res al bus — el GameScene decideix quan disparar el
|
||||
@@ -829,8 +842,10 @@ class Player : public AnimatedSprite {
|
||||
|
||||
// Comptador d'intents (estil Mario). Inicialitzat a `death_config.
|
||||
// initial_lives` al ctor; decreix una vegada per cada respawn
|
||||
// post-mort (no per respawns de canvi de sala). Pot anar a negatius:
|
||||
// avui no hi ha game over.
|
||||
// post-mort (no per respawns de canvi de sala). En arribar a 0,
|
||||
// `respawnFromDying` posa el jugador a DISABLED i publica
|
||||
// `player_disabled` al bus. `resetForJoin()` el restaura al valor
|
||||
// inicial quan el jugador re-entra mid-partida.
|
||||
int lives_remaining_{0};
|
||||
|
||||
// Coordenades del spawn de respawn (cantó superior-esquerra del
|
||||
|
||||
Reference in new issue
Block a user