16 KiB
Death/Respawn Rules
Status: In Design Author: SepComet + Claude Last Updated: 2026-04-27 Implements Pillar: 操作优于数值 (Skill Over Stats), 切换即承诺 (Switch is Commitment)
Overview
Death/Respawn Rules 是夜裔的玩家死亡与重生管理系统——定义玩家如何承受伤害、何时死亡、在何处重生、以及死亡带来的代价。它与"切换即承诺"支柱直接对齐:死亡惩罚的设计目标是让玩家在切形态时感受到风险(切错了可能死),但不会让死亡变成挫折(快速重生,代价合理)。系统采用 checkpoint 重生模型:玩家死亡后在最近的检查点重生,失去所有当前血能,当前波次重置——但不会失去关卡进度或任何永久升级。
玩家直接感受死亡时刻的冲击和重生时刻的重新出发。死亡不是"你输了"——屏幕短暂变暗、血能归零、你在检查点重新站起、敌人重新列阵。这个循环参考 Celeste 的"失败是学习"哲学——死亡足够轻,让你敢于尝试高风险操作(弹反时机、形态切换窗口);但足够重,让你在意每一次切换的决策。没有这个系统,形态切换的风险维度崩塌——玩家可以无代价地随意切换,违背"切换即承诺"支柱。
Player Fantasy
Death/Respawn Rules 服务于一个动作游戏中最被低估的情感:"再来一次"的渴望。当你因切形态时机错误被 Brute 一拳砸死时,那一瞬间不是挫败——是"我知道了,下次弹反要早 0.1 秒按"。屏幕暗下、血能归零、你在检查点重新站起的 2 秒内,你已经在大脑里重放了刚才的失误并找到了修正方案。这就是好的死亡系统应该创造的感受:死亡不是终点,是信息。
参考 Celeste 的死亡哲学——"每次死亡都是学习,重生快到你不觉得被打断"——和 Hades 的死亡循环——"死亡是回家,不是失败"。夜裔的死亡走在两者之间:Celeste 的快速重生(检查点即重生,没有加载、没有菜单) + Hades 的资源重置(血能归零是实质性代价,迫使你重新赚取)。玩家敢于尝试高风险操作——极限弹反、狼形对撞、雾形深入包围——因为这些操作失败后的惩罚是有限的、可量化的、可恢复的。你不会因为一次失误而失去 30 分钟的进度,你只会失去当前的血能和当前波次——然后你立刻重新开始。
Detailed Design
Core Rules
1. Player Health
MaxHealth: 100 (baseline, before any upgrades)CurrentHealth: tracked by Death/Respawn Rules, range [0, MaxHealth]- Health displayed to player via HUD, driven by
OnPlayerHealthChanged(current, max)event
2. Player Damage Reception Pipeline
Enemy AI produces AttackData → CombatCoordinator.ResolveFrame() → OnPlayerHit → Death/Respawn subtracts health
- Combat Logic's
CombatCoordinator.ResolveFrame(deltaTime)handles all attack resolution (player + enemy) in a unified two-phase pipeline - Enemy attacks are resolved against
PlayerStateduring the damage phase (after parry nullification in the parry phase) - Death/Respawn Rules subscribes to
CombatLogic.OnPlayerHit(PlayerDamageResult)— subtracts FinalDamage from CurrentHealth - No player-side resistance or armor — damage is applied as-received (mirrors Enemy AI's pure-receiver model)
3. PlayerState Definition
PlayerState is defined in Combat Logic GDD (authoritative single source). Death/Respawn reads and writes these fields:
- Reads:
Position,HitShape(provided to CombatCoordinator for hit detection) - Writes:
CurrentHealth(updated on damage),MaxHealth(baseline 100, modified by upgrades),IsDead(set when CurrentHealth <= 0),IsInvincible(set during respawn i-frames) - Other PlayerState fields (
FacingAngle,IsParryActive,ParryShape) are managed by Form Switch SM and Combat Logic; Death/Respawn does not touch them.
4. Death Condition
CurrentHealth <= 0→ player dies- Death is immediate on the frame health reaches 0
- Player cannot act during death (all input ignored)
- Trigger sequence:
OnPlayerDied→ systems react → respawn timer starts
5. Checkpoint System
- Checkpoint = start of current wave
- Updated each time
OnWaveChangedfires (Wave Manager) - On death: player respawns at the checkpoint wave's start state
- No manual checkpoint activation needed — automatic, invisible
Death State
| Phase | Duration | What Happens |
|---|---|---|
| Death Freeze | 0.3s | Screen freeze-frame. Player input locked. OnPlayerDied emitted. |
| Death Fade | 1.0s | Screen fades to black. Audio ducks. Systems react (enemies stop, blood energy resets). |
| Respawn Fade | 0.5s | Player repositioned at checkpoint. HUD resets. OnPlayerRespawned emitted. |
| Invincibility | 2.0s | Player can move and act but takes no damage. Visual: player geometry pulses/flashes. |
| Active | — | i-frames expire. Full damage vulnerability restored. OnPlayerVulnerable emitted. |
Total death-to-active: ~3.8 seconds. Fast enough to feel like "instant retry."
Respawn Flow
- Player dies →
OnPlayerDiedemitted - Blood Energy Economy receives
OnPlayerDied→ resets blood energy to 0 - Wave Manager receives
OnPlayerDied→ freezes wave state - Death fade completes → player position reset to checkpoint spawn point
- Wave Manager receives
OnPlayerRespawned→ resets current wave (despawn all enemies, restart from InterWave) - Player enters Invincibility (2s)
OnPlayerVulnerable→ player fully active, wave restarts
Interactions with Other Systems
| System | Direction | Interface |
|---|---|---|
| Combat Logic | Upstream | Provides PlayerState to Combat Logic as hit target. Receives OnPlayerHit(PlayerDamageResult) for health subtraction. |
| Blood Energy Economy | Downstream | Emits OnPlayerDied → Blood Energy resets to 0. |
| Wave Manager | Downstream | Emits OnPlayerDied (wave freezes), OnPlayerRespawned (wave resets to current checkpoint wave). |
| Enemy AI Logic | Downstream | Emits OnPlayerDied → all enemies enter Cooldown/Idle. Emits OnPlayerVulnerable → enemies resume normal behavior. |
| Form Switch SM | Downstream | Emits OnPlayerDied → resets form to default (Human) on respawn. |
| UI/HUD (L2) | Downstream | Emits OnPlayerHealthChanged, OnPlayerDied, OnPlayerRespawned, OnPlayerVulnerable for HUD display. |
| VFX Spawner (L1) | Downstream | Emits OnPlayerDied (death VFX), OnPlayerRespawned (respawn VFX). |
| Audio Player (L1) | Downstream | Emits OnPlayerHit (pain SFX), OnPlayerDied (death sting), OnPlayerRespawned (respawn whoosh). |
Formulas
Player Damage Reception
The player damage formula is defined as:
newHealth = currentHealth - finalDamage
Variables:
| Variable | Symbol | Type | Range | Description |
|---|---|---|---|---|
| Current health | currentHealth |
float | 0–100 | Pre-hit health |
| Final damage | finalDamage |
float | 0–150 | From Combat Logic PlayerDamageResult |
Output Range: 0–100 | Clamped at 0. If newHealth <= 0 → IsDead = true, OnPlayerDied fires.
Design Intent: Player applies damage as-received — no armor, no resistance, no mitigation. Transparency: a Brute hit always does exactly 25 damage. The player always knows how many hits they can take. Skill expression is in avoiding/parrying hits, not in building damage resistance.
Death Threshold
The death formula is defined as:
isDead = currentHealth <= 0
Output: Boolean. Once true, triggers the full death→respawn sequence. OnPlayerDied fires exactly once per death.
Hit Survival Thresholds (Baseline 100 HP)
| Enemy Attack | Damage | Hits to Die |
|---|---|---|
| Swarm | 6 | 17 |
| Stalker | 18 | 6 |
| Brute | 25 | 4 |
Design Intent: Brute is always lethal in 4 hits — enough to create tension but enough time to learn the parry timing. Swarm chip damage adds up — ignoring them is viable short-term but fatal if sustained.
Edge Cases
- If player takes damage exceeding current health (overkill): Health clamps to 0. No negative health. Death triggers once. Overkill damage is not tracked — does not affect respawn.
- If player takes damage while IsInvincible=true (respawn i-frames): Damage ignored. OnPlayerHit does NOT fire. Health unchanged.
- If multiple hits kill the player in the same frame (simultaneous hits from multiple enemies): All hits resolve (batched frame). Health drops to 0 or below. OnPlayerDied fires exactly once. Hit events for the same frame after death are still emitted but health stays at 0.
- If deltaTime = 0 (game paused): Death/respawn timers (Death Freeze, Death Fade, Respawn Fade, Invincibility) all pause. No phase transitions during pause.
- If player dies on Wave 1 (first wave, checkpoint = Wave 1 start): Normal respawn flow applies. Blood energy already 0 or low. Wave 1 restarts. No special case needed.
- If player dies during Invincibility (2s i-frames): Cannot happen — player is invincible. No damage received.
- If OnPlayerDied fires but OnPlayerRespawned never fires (e.g., game quit during death): State is discarded. Next session starts fresh. No partial death state persists.
- If MaxHealth is modified (future Skill Tree upgrade) while player is dead: Applied on respawn. CurrentHealth = new MaxHealth on respawn.
- If checkpoint advances (OnWaveChanged) during death animation: Ignored. Checkpoint only updates while player is in Active state. Death-locks checkpoint at the wave where death occurred.
Dependencies
| System | Layer | Type | Hard/Soft | Interface |
|---|---|---|---|---|
| Combat Logic | L0 | Upstream | Hard | Provides PlayerState for hit detection. Receives OnPlayerHit for health subtraction. Cannot function without damage pipeline. |
| Blood Energy Economy | L0 | Downstream | Hard | Emits OnPlayerDied → resets blood energy to 0. Core death penalty mechanic. |
| Wave Manager | L0 | Downstream | Hard | Emits OnPlayerDied (freeze), OnPlayerRespawned (reset wave). Wave reset is the other core death penalty. |
| Enemy AI Logic | L0 | Downstream | Soft | Emits OnPlayerDied → enemies stop attacking. Works without but enemies attacking a corpse looks broken. |
| Form Switch SM | L0 | Downstream | Soft | Emits OnPlayerDied → form resets to Human on respawn. |
| UI/HUD (L2) | L2 | Downstream | Soft | Emits OnPlayerHealthChanged, OnPlayerDied, OnPlayerRespawned for display. |
| VFX Spawner (L1) | L1 | Downstream | Soft | Emits death/respawn events for visual feedback. |
| Audio Player (L1) | L1 | Downstream | Soft | Emits hit/death/respawn events for audio feedback. |
| Level Loader (L1) | L1 | Upstream | Soft | Receives checkpoint spawn positions from LevelData. |
Hard dependencies: Combat Logic, Blood Energy Economy, Wave Manager.
Tuning Knobs
| Parameter | Default | Safe Range | Too Low | Too High |
|---|---|---|---|---|
MaxHealth |
100 | 60–150 | Every hit feels lethal — no learning window | Player immortal — no tension |
DeathFreezeDuration |
0.3s | 0.1–0.5s | No impact feel — death feels glitchy | Too long — feels unresponsive |
DeathFadeDuration |
1.0s | 0.5–1.5s | Not enough time for audio cue | Player waiting — frustration builds |
RespawnFadeDuration |
0.5s | 0.3–1.0s | Disorienting — player doesn't register new position | Dead air before action resumes |
InvincibilityDuration |
2.0s | 1.0–3.0s | Spawn-camped by enemies at perimeter | Too safe — player can clear enemies during i-frames |
PlayerHitShapeRadius |
0.5 | 0.3–0.7 | Too hard to hit — attacks whiff unfairly | Too easy to hit — player feels bloated |
Key tuning pair: MaxHealth + enemy AttackBaseDamage values (in Enemy AI GDD). Changing MaxHealth changes every hits-to-die threshold. Baseline (non-crit worst case): Swarm=100/6≈17 hits, Stalker=100/18≈6 hits, Brute=100/25=4 hits. Actual hits-to-die varies with player crits, positional guarantees, and form-specific damage.
Visual/Audio Requirements
Combat is a visual system — Visual/Audio is REQUIRED.
| Event | VFX | Audio |
|---|---|---|
OnPlayerHit |
Red flash at screen edge from hit direction. Player geometry briefly flashes red. | Pain SFX — varies by damage amount (light grunt <15, heavy grunt ≥15) |
OnPlayerDied |
Screen freeze-frame (0.3s) → player geometry shatters outward in white/silver fragments | Bass drop + silence — distinct from enemy death sounds |
OnPlayerRespawned |
Player geometry reforms from fragments at checkpoint position. White flash → form color transition. | Rising whoosh + heartbeat start |
OnPlayerVulnerable |
Player geometry stops pulsing/flashing. Brief shimmer. | Subtle "ready" chime |
OnPlayerHealthChanged |
Health bar VFX (flash on damage, gentle pulse on low health <25%) | None (too frequent for SFX) |
Invincibility visual: Player geometry pulses white at 4Hz during i-frames. Intensity decreases over the 2s duration — last 0.5s is barely visible.
UI Requirements
| Element | Content | Trigger |
|---|---|---|
| Health Bar | CurrentHealth / MaxHealth as horizontal bar. Color: green (>50%), yellow (25-50%), red (<25%). | OnPlayerHealthChanged |
| Death Overlay | Full-screen dark vignette + "You Died" text (1s) | OnPlayerDied |
| Respawn Text | "Again" — centered, fades after 1s | OnPlayerRespawned |
| i-Frame Indicator | Health bar border pulses white during invincibility | OnPlayerRespawned → OnPlayerVulnerable |
Acceptance Criteria
| # | GIVEN | WHEN | THEN |
|---|---|---|---|
| 1 | Player CurrentHealth=100. PlayerDamageResult { FinalDamage=25 }. |
OnPlayerHit received | CurrentHealth=75. OnPlayerHealthChanged(75, 100) fires. IsDead=false. |
| 2 | Player CurrentHealth=20. PlayerDamageResult { FinalDamage=25 }. |
OnPlayerHit received | CurrentHealth=0 (clamped). IsDead=true. OnPlayerDied fires. Death sequence begins. |
| 3 | Player CurrentHealth=10. Two simultaneous hits: FinalDamage=8 and FinalDamage=6. | Both hits in same frame | CurrentHealth=0. OnPlayerDied fires exactly once. Both OnPlayerHit events fire. |
| 4 | Player IsInvincible=true (during respawn i-frames). PlayerDamageResult { FinalDamage=25 }. |
OnPlayerHit received | Damage ignored. CurrentHealth unchanged. OnPlayerHealthChanged does NOT fire. |
| 5 | Player dies. Death Freeze(0.3s) → Death Fade(1.0s) → Respawn Fade(0.5s) → Invincibility(2.0s). | Death sequence completes | Total elapsed ~3.8s. Player is at checkpoint position, full health, form=Human. |
| 6 | Player dies on Wave 3. Checkpoint = Wave 3. | Respawn completes | Wave Manager.OnPlayerRespawned fires → Wave 3 resets from InterWave. Blood energy = 0. |
| 7 | Player in Active state. Wave 4 starts (OnWaveChanged fires). | Checkpoint update | CurrentCheckpointWave = 4. Future death respawns at Wave 4. |
| 8 | deltaTime=0.0 during Death Fade (0.5s elapsed, 0.5s remaining). | Update called | Timer does not advance. Death Fade stays at 0.5s remaining. |
| 9 | Player CurrentHealth=100. MaxHealth increased to 120 (future upgrade). | Upgrade applied | MaxHealth=120. CurrentHealth stays 100. (Does not auto-heal on upgrade.) |
| 10 | Player dies at MaxHealth=120. | Respawn completes | CurrentHealth = MaxHealth = 120 (full heal on respawn). |
Open Questions
- Respawn position within arena: Should the player respawn at arena center, or at a designer-specified spawn point per wave? MVP defaults to arena center. Defer spawn point customization to Level Loader GDD.
- Should there be a "death streak" mechanic (e.g., slight health buff after 3 consecutive deaths on same wave)? Aligns with Celeste philosophy of helping struggling players, but may conflict with "Skill Over Stats" pillar.
- Player HitShape (Circle r=0.5): Is this the same regardless of current form? Or should HitShape change with form (Human smaller, Wolf larger, Mist diffuse)? MVP uses uniform HitShape for simplicity.
- Should the death counter be tracked for scoring/statistics? Score Calculator GDD may want this data.
- Game Over condition: Is there one? Infinite retries is the MVP plan, but should a level have a max-death count for challenge mode? Defer to Score Calculator / Menu System.