What it does
The march works the way the original did. A cursor visits the live invaders, bottom row first, left to right, moving a set number of them each frame. A full rack of 55 therefore shuffles once every 55 frames, and as invaders die it moves faster without any speed table at all, until the last one moves every frame. When an invader would cross the edge, the next sweep drops the rack and reverses it. A shot invader freezes the rack for a moment, invaders erase any cover they overlap, and an invader reaching the invasion line ends the game whatever the lives.
Alien fire is a set of shot types, each one shot in flight at a time, so the number of types caps the fire. Types take turns, and one fires only when every other shot in flight has travelled further than the reload rate for the current score allows, so the fire quickens as the score climbs. Each type picks its column its own way: the column above the player's cannon, a looping table, or at random. The mystery saucer launches on a timer while enough invaders remain and pays from a table indexed by how many shots you have fired.
Shields are cover masks from destructible-cover, eroded by explosion stencils rather than single cells. You tick the
game with a move and a fire button, read state for the invaders, shots, saucer, player, score and lives, and draw the
shields from merged runs of cover.
Features
- A self-pacing march — one invader a frame, bottom row first, so the rack speeds up as it thins, with edge drops, reversal and a freeze on each kill.
- Typed alien shots — each type with its own targeting policy, step and faster step near the end, taking turns on a cadence.
- Score-driven reload — a table that shortens the gap between shots as the score rises.
- A mystery saucer — launched on a timer, entering from a side set by your shot count, and paying from a wrapping score table.
- Eroding shields — cover masks worn away by explosion stencils, restored when a rack is cleared.
- Lives and rounds — extra-life thresholds, death and respawn freezes, and racks that start lower each round.
- The 1978 preset — values from the original program: start heights, column tables, reload table, saucer table and its timer, shield and explosion shapes.
- Deterministic and headless — fixed 60 Hz steps, a seed, and snapshots.
Good for
- Fixed-screen invasion shooters in the style of the 1978 arcade Space Invaders.
- Rack shooters with custom fleets, of other sizes, kinds and scores.
- Easier or harder variants with more player shots, more invaders moving per frame, or no saucer.
- Retro collections that need the march and shot rules to behave as players remember.
- Teaching and testing, since the rules run headless and replay exactly for a seed and inputs.
Make it yours
invadersPreset takes the columns, rows, lives, number of bunkers, the saucer, invaders moved per frame, player
shots, shot types, extra lives and a seed, and any field of the definition it returns can then be replaced: kinds and
scores, fleet layout and spacing, start heights per round, march steps and edges, the invasion line, the cannon's
speed, size and lives, every shot speed, count and table, the cadence, the reload table, the saucer's table and timer,
and the cover masks and stencils.
Two very different racks are tested. One is the classic eleven by five fleet with four shields, three shot types and the saucer. Another is a six by three rack with different scores, two shields, no saucer, three invaders moving every frame, two player shots at once and a bomb dropped in a random column, which still plays through a round.
A quick look
The classic game, ticked with a move and a fire button, with its events and shields presented:
const mf = game.marchingFleet;
const g = mf.createInvaders(mf.invadersPreset()); // the 1978 game
g.tick(dt, { move: -1 | 0 | 1, fire: keyDown('Space') }); // fixed 60 Hz frames inside
for (const e of g.drain()) { /* invader-killed, saucer-killed, player-hit, round-clear… */ }
const s = g.state; // invaders, shots, saucer, player, score, lives
for (const run of g.cover.runs()) drawRect(run); // shields, merged into runs
Works with
destructible-cover— required: the shields and their erosion.flight-formation— for enemies that fly in, dive, escort and capture.wave-arenaandscrolling-shooter— for free-roaming or scrolling shooters.
Good to know
- One player: two-player alternation, attract-mode play and sound are left to your game.
- Collisions are hit boxes rather than per-pixel sprite overlap, and the ground line does not erode.
- Racks are limited to 10,000 invaders, and the work each frame grows with them.
- A snapshot holds the state but not the configuration, so restore it into a game built from the same definition.






