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
@@ -95,17 +95,19 @@ class GameScene : public Scene {
|
||||
// Vector des del principi: AEE suportarà multijugador local; cada Player
|
||||
// té els seus propis Controls i entra al vector amb una crida extra.
|
||||
// Sempre conté **dos** entrades (P1 a [0], P2 a [1]) tant en mode BOTH
|
||||
// com en single-player: l'slot inactiu es queda en estat DISABLED de
|
||||
// manera permanent, deixant el camí preparat per al "join in progress"
|
||||
// futur (el segon jugador podrà entrar a meitat de partida sense
|
||||
// recrear estructures). Veure `players_starts_active_`.
|
||||
// com en single-player: l'slot inactiu es queda en estat DISABLED i
|
||||
// pot entrar mid-partida via "join in progress" (`handleJoinInput`).
|
||||
std::vector<std::unique_ptr<Player>> players_;
|
||||
|
||||
// Quins slots juguen aquesta partida segons `config_.starting_players`.
|
||||
// Index = id del jugador (0 = P1, 1 = P2). Determina a qui aplica el
|
||||
// spawn aeri al final de la fase 0 d'INTRO; un slot amb `false` es
|
||||
// queda DISABLED tot el cicle de sala.
|
||||
std::array<bool, 2> players_starts_active_{false, false};
|
||||
// Quins slots estan en partida ARA MATEIX (jugant o DYING). Mutable
|
||||
// durant la sala: el ctor el sembra des de `config_.starting_players`,
|
||||
// `joinPlayer` el posa a true quan un slot inactiu pulsa START, i la
|
||||
// subscripció a `player_disabled` el torna a false quan un slot
|
||||
// esgota vides. `loadRoom` recalcula `setExpectedPlayerCount` a
|
||||
// partir d'aquesta vista — un slot DISABLED al final d'una sala no
|
||||
// entra automàticament a la següent (el jugador ha de re-pulsar
|
||||
// START si vol re-entrar).
|
||||
std::array<bool, 2> players_active_{false, false};
|
||||
|
||||
// Cinemàtica de spawn d'un slot concret. Posa el slot indicat en
|
||||
// AIRBORNE des d'una altura fora de pantalla. Cridat per
|
||||
@@ -130,6 +132,13 @@ class GameScene : public Scene {
|
||||
// Extret a un mètode per acotar la complexitat cognitiva del ctor.
|
||||
void dispatchPlayerKilled(int player_id);
|
||||
|
||||
// Handler de l'event `player_disabled` (un slot acaba d'esgotar
|
||||
// vides). Apaga `players_active_[id]` perquè el `loadRoom` següent
|
||||
// no compti aquest slot i perquè el "join in progress" del frame
|
||||
// següent torni a oferir-li `setJoinPrompt(CAN_JOIN)`. Extret a
|
||||
// mètode per acotar la complexitat cognitiva del subscriber/ctor.
|
||||
void onPlayerDisabled(int player_id);
|
||||
|
||||
// Itera els slots actius i, si el delay configurat ha expirat des
|
||||
// del callback de fi de música d'INTRO, dispara `triggerPlayerSpawn`.
|
||||
// Cridada cada frame durant la fase d'spawn escalonat (entre el
|
||||
@@ -137,6 +146,33 @@ class GameScene : public Scene {
|
||||
// caigut tots o si encara no estem dins la finestra (intro_completed_).
|
||||
void spawnDuePlayers();
|
||||
|
||||
// Atén el "join in progress" (regla 1 de la FSM de joc): si un slot
|
||||
// està DISABLED i el jugador corresponent pulsa START dins de PLAYING,
|
||||
// dispara `joinPlayer`. La detecció de tecla/botó la fa
|
||||
// `Input::detect::pressedStart`. Ignorat fora de PLAYING (durant
|
||||
// INTRO/OUTRO el slot inactiu mostra "ESPERA / PARA JUGAR" al HUD).
|
||||
void handleJoinInput();
|
||||
|
||||
// Materialitza l'entrada d'un slot inactiu: spawn aeri al costat
|
||||
// corresponent de la porta (`computeSpawn().pX_x`), reset de vides
|
||||
// al valor inicial via `Player::resetForJoin`, marcatge de
|
||||
// `players_active_[i]=true` i activació del bloc del HUD. La
|
||||
// cinemàtica reaprofita `spawnFromAir` (mateixa caiguda visual que
|
||||
// l'INTRO de sala i el respawn post-mort).
|
||||
void joinPlayer(std::size_t slot_index);
|
||||
|
||||
// Recompte de jugadors "en partida" (no DISABLED ni EXITED, o bé
|
||||
// DYING — DYING encara compta com a jugant fins que es resol). Hook
|
||||
// exposat per a la futura sub-FSM CONTINUE? + GAME OVER, que vigila
|
||||
// la transició a 0 jugadors actius. No s'usa dins de la Fase 1.
|
||||
[[nodiscard]] auto activePlayerCount() const -> int;
|
||||
|
||||
// Refresca el prompt mostrat al bloc HUD de cada slot inactiu. Es
|
||||
// crida cada frame des d'`update()`. La decisió viu ací (que coneix
|
||||
// `state_` de la RoomFsm); el HUD només pinta. Per a slots actius,
|
||||
// posa el prompt a NONE per ser defensiu davant de canvis d'estat.
|
||||
void refreshJoinPrompt();
|
||||
|
||||
// Sentinel que marca el moment "música d'INTRO acabada" dins del
|
||||
// timeline. Ja no ve d'un callback d'àudio: el setja el GameScene
|
||||
// quan la FSM ha consumit l'última fase d'INTRO (la `music_tail`,
|
||||
|
||||
Reference in new issue
Block a user