What it does
A piece of cover is a mask: rows of characters, one per cell, each character standing for a material with hit points, an optional blast resistance, or no damage at all. You lay out as many pieces as you need, of any shape and size. When a shot moves, you trace its box or point from where it was to where it is, and get back the earliest contact with a cell that still stands. Holes are real: a shot passes straight through a gap an earlier shot opened.
Damage comes three ways. splat erodes by a stencil, a small mask of its own, so a shot blows a ragged hole out of a
shield rather than one cell or a perfect circle. damage hits the contacted cell and spreads to neighbours within a
radius, divided by each one's blast resistance. eraseRect damages everything under a rectangle, for an enemy marching
through a shield. Indestructible cells block traces and never take damage, so a frame can hold its shape while the brick
inside crumbles.
For drawing, runs() returns horizontal runs of cells with the same material and health, so a shield is a handful of
rectangles rather than hundreds of cells, and revision changes on every hit so you redraw only when something broke.
Snapshots save the state of every cell, and the whole thing runs without a renderer.
Features
- Masks and materials — cover authored as rows of characters, each character a material with hit points, blast
resistance or
indestructible. - Swept traces —
traceBoxandtracefind the earliest contact with a surviving cell along a shot's path, and only visit the cells under it, so small shots against large masks stay cheap. - Three kinds of damage — stencil splats, radius blasts scaled by resistance, and rectangle erasure.
- Arcade presets —
INVADERS_SHIELD_MASK, the classic 22 by 16 shield with its off-centre notch, andINVADERS_PLAYER_SPLATandINVADERS_ALIEN_SPLAT, the ragged shot explosions, taken from the original game's data. - Evenly spaced bunkers —
bunkerPresetplaces any number of bunkers of any mask across a screen. - Cheap drawing —
runs()merges cells into horizontal runs, andrevisiontells you when to redraw. - Snapshot and reset — save, restore and reset every cell's health.
Good for
- Fixed shooters with bunkers in the style of Space Invaders, with shields eroded by player and alien shots and by invaders marching through.
- Castle and fortress walls that crumble brick by brick behind an indestructible frame.
- Top-down shooters with cover that wears away as the fight goes on.
- Artillery and digging shots, where a projectile bites a shaped hole out of a wall.
- Armour plates of several materials, where heavy plating shrugs off splash that destroys brick.
Make it yours
Each definition has an id, a position, a cell size, a mask and the materials its characters stand for. There is no limit
on how many definitions, shapes, materials or stencils you use, and contact sizes and damage amounts are the caller's to
choose per shot. bunkerPreset takes the count, world width, height on screen, cell size, hit points, mask, left edge
and spacing.
Two materially different uses: the four classic shields, eroded by the original shot stencils and erased where the invaders march; and a fortress of steel that never breaks, armour with three hit points and a blast resistance of two, and one-hit brick, all worn down by radius blasts.
A quick look
Four bunkers, a shot traced upward, a splat where it hit, and the shields drawn as runs:
const dc = game.destructibleCover;
const cover = dc.createDestructibleCover(dc.bunkerPreset({ count: 4, worldWidth: 224, y: 192, left: 32, pitch: 45 }));
const hit = cover.traceBox({ x: 30.5, y: 210 }, { x: 30.5, y: 206 }, 0.5, 2); // a 1x4 shot moving up
if (hit) cover.splat({ x: hit.at.x, y: hit.at.y - 4 }, { mask: [...dc.INVADERS_PLAYER_SPLAT] });
for (const r of cover.runs()) drawRect(r.x, r.y, r.length * r.size, r.size, r.material, r.hp);
Works with
marching-fleet— uses this pack for the shields of its marching invader fleet.render-auto,world-screenandtypography— enough to draw cover, a screen and a score.
Good to know
- Cells are axis-aligned squares and do not collapse or fall: there is no physical crumbling.
- It is not for continuous deformable terrain meshes.
- Masks must be non-empty and rectangular, at most a million cells each.
- A snapshot only restores into definitions with the same mask shapes.






