Skip to main content

Health

The health module tracks hit points for every entity that can be damaged or destroyed. It is composed of HealthComponent, HealthSystem, and PlayerDeathEvent.

For how damage is applied to HealthComponent, see Damage Module.


HealthComponent

HealthComponent stores an entity's current, base, and maximum HP via StatValue. It conforms to StatProvidable.

public class HealthComponent: StatProvidable {
public var value: StatValue

// Starting HP equals max HP
public init(base: Float)

// Starting HP is different from max HP
public init(base: Float, max: Float)
}

Use the single-argument initialiser for most entities where the entity starts at full health. Use the two-argument form when an entity should spawn with reduced HP.

Example:

// Enemy that starts at full HP
world.addComponent(component: HealthComponent(base: 80), to: enemy)

// Player that starts at 50 of a 100 max (e.g. after a room transition penalty)
world.addComponent(component: HealthComponent(base: 50, max: 100), to: player)

Damage is applied by directly decrementing value.current and calling clampToMin().

HealthSystem

HealthSystem runs after EnemyAISystem and scans every entity with a HealthComponent each frame. Its only job is zero-HP detection — it does not apply damage itself.

For each entity with HealthComponent:

  1. Skip if value.current > 0.
  2. If the entity has PlayerTagComponent → call playerDeathEvent.record(). The player entity is not destroyed here, so other systems can finish processing the current frame safely.
  3. Otherwise → enqueue the entity for destruction via DestructionQueue.
public final class HealthSystem: System {
public var dependencies: [System.Type] { [EnemyAISystem.self] }
// ...
}

PlayerDeathEvent

PlayerDeathEvent is a simple flag object written by HealthSystem and read by GameScene after each frame's system update loop completes.

public final class PlayerDeathEvent {
public private(set) var playerDied: Bool = false

public func record() // called by HealthSystem
public func reset() // called by GameScene on restart
}

Lifecycle:

  1. HealthSystem calls record() when the player's HP hits zero.
  2. After the update loop, GameScene checks playerDied and triggers game over if true.
  3. On game restart, GameScene calls reset() to clear the flag.

GameScene is the sole consumer. Do not call reset() from within the ECS update loop.


Death Handling Summary

Entity typeAction when HP ≤ 0
Enemy / non-playerAdded to DestructionQueue, removed next frame
PlayerPlayerDeathEvent.record() called; entity persists until GameScene handles game over

Dependencies

DependencyRole
StatValueUnderlying value type for HealthComponent
DestructionQueueReceives non-player entities for removal
PlayerDeathEventSignals GameScene that the player has died
PlayerTagComponentDistinguishes player from non-player entities
EnemyAISystemHealthSystem declares it as a dependency to run after it