Space Invaders looks like it needs a game engine. It doesn't. The entire arcade classic is one array of objects, two bullet lists, and two collision checks — about 120 lines of plain JavaScript on a <canvas>. Here's how every piece works.
🎮 Play it in your browser: https://dev48v.infy.uk/game/day9-space-invaders.html
This is Day 9 of my GameFromZero series — a classic game rebuilt from scratch, no libraries.
1. The grid is one flat array
The trick that makes everything else easy: build the grid once into a single flat array. From then on the swarm is just a list you loop over.
for (let r = 0; r < ROWS; r++)
for (let col = 0; col < COLS; col++)
invaders.push({ x: col * GAP, y: r * GAP });
40 little objects. Marching, shooting, and counting survivors all become one-liners over this array.
2. The iconic march: move, drop, reverse
Every frame, shift the whole array in the current direction. Then check if any invader touched a wall — if so, flip direction for all of them and nudge the grid down a step:
for (const inv of invaders) inv.x += dir * speed;
if (edgeHit) {
dir *= -1;
invaders.forEach(i => i.y += DROP);
}
That single shared rule is the unmistakable Space Invaders motion. Bonus: as you destroy invaders the array shrinks, so dividing the count into the speed makes the swarm accelerate — for free.
3. Player shots delete invaders
Bullets are tiny objects moving up. Each frame, test bullets against invaders with a box overlap and filter out the ones that got hit:
const hit = invaders.find(inv => overlap(bullet, inv));
if (hit) {
invaders = invaders.filter(i => i !== hit);
score += 10;
}
4. Invaders shoot back — with a coin flip
There's no AI here, just probability. Each frame, with a small chance, pick a random surviving invader and drop a bullet from it:
if (Math.random() < 0.02) {
const shooter = invaders[Math.floor(Math.random() * invaders.length)];
enemyBullets.push({ x: shooter.x, y: shooter.y });
}
Tune that one number and you've set the entire difficulty. Emergent menace from a single Math.random().
5. Three ways the round ends
All at the bottom of the loop:
if (invaders.length === 0) win(); // cleared the swarm
if (enemyBulletHitsPlayer) lives--; // took a hit
if (lowestInvader.y >= player.y) gameOver(); // they landed
The lesson
Arcade games feel complex but are usually a handful of simple rules running 60 times a second. Model the world as plain data (an array), apply the rules each frame, and draw. That pattern — Frogger, Flappy, now Space Invaders — builds almost any 2D game.
Play it, then read the code (it has a step-by-step "Understand" tab). 👾
For further actions, you may consider blocking this person and/or reporting abuse
