VOOZH about

URL: https://dev.to/dev48v/i-built-space-invaders-in-120-lines-of-vanilla-javascript-5582

⇱ I Built Space Invaders in ~120 Lines of Vanilla JavaScript - DEV Community


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). 👾