Death Debris Spawn

When an enemy dies, the engine spawns a short, punchy burst of tumbling shard fragments at the death location via spawnDeathDebris(wx, wy, radius, count, behavior?) in engine/bridge-death-debris.ts. The burst is the primary at-a-glance signal that a kill landed — shards carry the dying archetype’s color so the kill stream stays readable in chaos.

Not to be confused with the ambient DebrisField cluster system in engine/world/debris.ts, which spawns floating metal-shard hazard clusters in the world (player-damaging contact obstacles). That is a separate, biome-driven destructible system — death debris is a one-shot visual on enemy kill.

Spawn pipeline

spawnDeathDebris is called on enemy death with the enemy’s world position, collision radius, a base shard count, and the enemy’s archetype behavior string. It then:

  1. Looks up tint in ARCHETYPE_DEBRIS_TINT[behavior], falling back to a default red (_DEFAULT_DEBRIS_TINT: bright (1.00, 0.16, 0.16), dark (0.78, 0.10, 0.10)) when the archetype is unknown.
  2. Looks up count multiplier in ARCHETYPE_DEBRIS_COUNT_MULT[behavior], defaulting to 1.0 for unmapped archetypes. The scaled count is Math.max(1, Math.round(count * countMult)) — at least one shard always spawns so a kill never reads as silent.
  3. Spawns shards in a loop, gated by the global pool cap. Each shard gets a random ejection angle, a random speed in [220, 400] px/s (DEBRIS_MIN_SPEED + DEBRIS_SPEED_RANGE), a random lifetime in [0.18, 0.32] s, a random rotation + spin, a size of 4 + rand(0..4) + radius * 0.10, and a random sprite variant index in [0, 6).

Per-archetype tint map (16 archetypes)

Each entry is a 2-tone tint { rL, gL, bL, rD, gD, bD }. Per shard, bright vs dark is picked with 50/50 weight — matching the prior red-bright/red-dark jitter so kill bursts feel consistent across archetype. The map currently covers 16 archetypes:

ArchetypeBright (rL, gL, bL)Dark (rD, gD, bD)Read
orb1.00, 0.16, 0.160.78, 0.10, 0.10generic red (default)
charger1.00, 0.40, 0.100.78, 0.25, 0.06aggressive orange-red
racer1.00, 0.90, 0.200.78, 0.62, 0.10neon yellow-electric
shooter0.30, 1.00, 0.300.18, 0.78, 0.18toxic green
gunner0.60, 1.00, 0.200.40, 0.78, 0.10green-yellow
mortar1.00, 0.55, 0.100.78, 0.35, 0.06explosive orange
sniper0.75, 0.30, 1.000.50, 0.18, 0.78beam purple
field0.30, 0.90, 1.000.18, 0.62, 0.78field cyan
brute0.60, 0.45, 0.320.40, 0.28, 0.20dark grey-brown chunks
wisp1.00, 0.50, 1.000.78, 0.32, 0.78ethereal magenta
lurker0.55, 0.20, 0.800.35, 0.12, 0.55deep dark-purple
bombardier1.00, 0.75, 0.200.78, 0.50, 0.10bright explosive amber
sprinter0.78, 1.00, 1.000.50, 0.78, 0.78supersonic cyan-electric
spitter0.70, 1.00, 0.200.50, 0.78, 0.10acid yellow-green
burner1.00, 0.50, 0.150.78, 0.32, 0.08fire/lava red-orange
suppressor0.55, 0.70, 0.300.35, 0.50, 0.18industrial olive-drab

Per-archetype count multiplier (0.4x – 1.5x)

ARCHETYPE_DEBRIS_COUNT_MULT scales the caller-supplied base count so heavier archetypes throw more shards and lighter ones throw fewer — preserves the at-a-glance mass read that tint + audio already encode. Missing entries default to 1.0.

MultiplierArchetypes
0.4wisp (tiny ethereal — almost no shards)
0.5sprinter (fragile + supersonic)
0.8gunner (small turret)
1.0 (default)orb, charger, racer, shooter, sniper
1.1lurker
1.2spitter
1.3mortar, suppressor
1.4field, burner
1.5brute (heavy chassis), bombardier (big explosive payload)

Floor of 1 shard is enforced regardless of multiplier, so tiny enemies still produce visual feedback.

Sprite variants (6)

Each shard picks one of SHARD_VARIANT_COUNT = 6 pre-baked red shard sprites from the texture atlas (baked once at startup by atlas-builder.ts). The atlas index is stored on the shard as variant: 0..5. The runtime never re-bakes — it just samples a different region of the same atlas per shard for visual variety in a single burst. Tint multiplies the sprite pixels at draw time, so all 6 variant shapes work for every archetype color.

Pool cap (60)

The active shard pool is capped at _MAX_DEBRIS = 60. The spawn loop checks deathDebris.length < _MAX_DEBRIS per shard and stops adding once the pool is full — late shards in a big kill chain (e.g. a screen full of brutes dying simultaneously) are simply dropped. There is no priority eviction; oldest shards fall out via lifetime expiry (life: 0.18–0.32 s), which clears budget quickly enough that the cap rarely starves a normal burst.

Position jitter

Each shard’s spawn position is offset from the death point by (rand-0.5) * radius * 0.4 on each axis, so shards emerge from a small box scaled to the enemy’s collision radius rather than all from a single point. Larger enemies → wider initial spread.

See also

  • engine/bridge-death-debris.ts — source module
  • engine/world/debris.ts — separate ambient debris-cluster hazards
  • Sister T18/T19 dispatch-site override maps: tick-42 audio (per-archetype death SFX), tick-43 VFX burst, tick-56 count multiplier (this page)