feat(player): mort i respawn (DYING + death_spinning + lives counter)
This commit is contained in:
1 parent
6397f9d4eb
commit
9f0a566ffb
11 files changed
+377
-7
No files matched your search
@@ -68,6 +68,13 @@ class Player : public AnimatedSprite {
|
||||
// tots els slots durant les transicions de sala abans del spawn
|
||||
// aeri, i (c) en el futur, l'estat post-mort abans del respawn.
|
||||
DISABLED,
|
||||
// Mort en curs: animació `death_spinning` (3 voltes horàries) +
|
||||
// pausa `respawn_delay_ms` abans del respawn. Bloqueja input i
|
||||
// moviment; no rep contacte amb hazards (cf. `isDying`). Quan el
|
||||
// timer s'esgota, `respawn(spawn_x_, spawn_y_)` torna a GROUNDED
|
||||
// i decrementa el comptador de vides (pot anar a negatius — no
|
||||
// hi ha game over).
|
||||
DYING,
|
||||
};
|
||||
|
||||
// Geometria carregada des del YAML del player (p.ex. `data/player/sam.yaml`).
|
||||
@@ -203,6 +210,7 @@ class Player : public AnimatedSprite {
|
||||
[[nodiscard]] auto isHurt() const -> bool { return state_ == State::HURT; }
|
||||
[[nodiscard]] auto isExited() const -> bool { return state_ == State::EXITED; }
|
||||
[[nodiscard]] auto isDisabled() const -> bool { return state_ == State::DISABLED; }
|
||||
[[nodiscard]] auto isDying() const -> bool { return state_ == State::DYING; }
|
||||
// Resum dels estats "fora del món": EXITED i DISABLED comparteixen el
|
||||
// mateix perfil físic (no es pinten, no llegeixen input, no
|
||||
// col·lisionen, no participen al resolver PvP). Tots dos gates de
|
||||
@@ -240,6 +248,28 @@ class Player : public AnimatedSprite {
|
||||
being_pushed_ = false;
|
||||
}
|
||||
|
||||
// Mata el jugador d'un sol toc: transició a DYING, animació
|
||||
// `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).
|
||||
void enterDying();
|
||||
|
||||
// Coordenades del spawn de respawn (cantó superior-esquerra del
|
||||
// sprite, mateixa convenció que `respawn(x, y)`). El GameScene les
|
||||
// assigna després de `computeSpawn` al ctor i a cada `loadRoom`. Sense
|
||||
// això, el respawn enviaria el jugador a (0, 0).
|
||||
void setSpawnPoint(float x, float y) {
|
||||
spawn_x_ = x;
|
||||
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.
|
||||
[[nodiscard]] auto getLivesRemaining() const -> int { return lives_remaining_; }
|
||||
|
||||
// Reset complet a l'estat inicial: posició a (x, y), velocitats a 0,
|
||||
// estat GROUNDED, qualsevol flag de control reinicialitzat. Cridat
|
||||
// per GameScene a la transició ROOM_OUTRO → ROOM_INTRO. Idempotent
|
||||
@@ -554,6 +584,21 @@ class Player : public AnimatedSprite {
|
||||
// d'input es perd silenciosament).
|
||||
static void readWhipBlock(const fkyaml::node& yaml);
|
||||
|
||||
// Configuració de mort/respawn llegida del bloc `death:` del YAML.
|
||||
// `respawn_delay_ms` és la pausa entre la fi de `death_spinning` i la
|
||||
// reaparició al spawn; `initial_lives` és el comptador d'intents amb
|
||||
// què naix cada Player. Si el bloc manca, defaults segurs (0/3).
|
||||
struct DeathConfig {
|
||||
int respawn_delay_ms{0};
|
||||
int initial_lives{3};
|
||||
};
|
||||
static DeathConfig death_config;
|
||||
|
||||
// Llig el bloc `death:` del YAML i n'omple `death_config`. Si manca,
|
||||
// `respawn_delay_ms` queda a 0 (el respawn és immediat al final de
|
||||
// l'animació) i `initial_lives` es manté al default (3).
|
||||
static void readDeathBlock(const fkyaml::node& yaml);
|
||||
|
||||
// Activa l'estat ATTACKING en la direcció cardinal indicada (la
|
||||
// direcció cap on mira el jugador) i publica `whip_spawn` al bus
|
||||
// perquè el GameScene cree el `WhipAttack` corresponent. Posa el
|
||||
@@ -624,6 +669,35 @@ class Player : public AnimatedSprite {
|
||||
// bloquejat i no rep input direccional ni de salt ni d'atac.
|
||||
float attacking_remaining_ms_{0.0F};
|
||||
|
||||
// Estat de DYING. `death_animation_complete_` es marca quan
|
||||
// `animationIsCompleted()` retorna true per primera vegada al cicle
|
||||
// actual; només llavors comença a descomptar `respawn_remaining_ms_`.
|
||||
// Quan el delay arriba a 0, `respawnFromDying()` aplica `respawn(...)`
|
||||
// i decreix el comptador de vides.
|
||||
bool death_animation_complete_{false};
|
||||
float respawn_remaining_ms_{0.0F};
|
||||
|
||||
// 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.
|
||||
int lives_remaining_{0};
|
||||
|
||||
// Coordenades del spawn de respawn (cantó superior-esquerra del
|
||||
// sprite). Les assigna el GameScene via `setSpawnPoint`. 0/0 fins que
|
||||
// el GameScene n'invoque el setter al ctor / `loadRoom`.
|
||||
float spawn_x_{0.0F};
|
||||
float spawn_y_{0.0F};
|
||||
|
||||
// Aplica el respawn al final del cicle DYING: decreix vides (sense
|
||||
// clamp), neteja els flags interns del cicle i delega a `respawn`
|
||||
// amb les coordenades del spawn.
|
||||
void respawnFromDying();
|
||||
|
||||
// Branca de `applyMovement` per a DYING. Avança l'animació, detecta
|
||||
// la fi i descompta el delay; al final, dispara el respawn.
|
||||
void applyDyingMovement(float delta_time);
|
||||
|
||||
// Llig el botó de salt aquest frame (teclat + mando assignat) i,
|
||||
// amb edge-detection, retorna true si s'ha de despegar el salt.
|
||||
[[nodiscard]] auto consumeJumpEdge() -> bool;
|
||||
|
||||
Reference in new issue
Block a user