Asteroids feels like it needs a physics engine — momentum, rotation, splitting rocks, screen wrap. It doesn't. The whole thing is velocity vectors, one angle, and a screen that wraps, in about 120 lines of vanilla JavaScript on a canvas.
🎮 Play it: https://dev48v.infy.uk/game/day10-asteroids.html
1. Rotation is just one number
The ship doesn't move left/right — it rotates. Arrow keys nudge a single angle:
if (left) ship.angle -= 0.07;
if (right) ship.angle += 0.07;
Everything else — which way you thrust, where bullets fly — is derived from that one angle with sin/cos.
2. Thrust adds momentum (you coast)
This is what makes it feel like space. Thrust adds to your velocity, not your position. Let go and you keep drifting:
if (up) {
ship.vx += Math.cos(ship.angle) * 0.13;
ship.vy += Math.sin(ship.angle) * 0.13;
}
ship.x += ship.vx; ship.y += ship.vy;
ship.vx *= 0.99; ship.vy *= 0.99; // gentle "space friction"
3. Trig converts an angle into movement
cos(angle) is the x-component of where you're pointing, sin(angle) is the y. The same pair aims your bullets. Two functions turn "which way am I facing" into "how do I move."
4. The screen wraps (toroidal space)
Fly off one edge, reappear on the other — four lines, applied to the ship, every bullet, and every rock:
const wrap = o => {
if (o.x < 0) o.x += W; if (o.x > W) o.x -= W;
if (o.y < 0) o.y += H; if (o.y > H) o.y -= H;
};
5. Splitting rocks = recursion in disguise
Shoot a big rock and it becomes two smaller, faster ones; shoot those and they split again until they're tiny enough to vanish:
if (dist(bullet, rock) < rock.r) {
if (rock.r > 14) for (let k = 0; k < 2; k++) spawnSmaller(rock);
rocks.splice(i, 1); score += 20;
}
That cascade is what turns 4 asteroids into a tense, screen-filling swarm.
The takeaway
Arcade games feel complex but are usually a handful of simple rules running 60 times a second. Model the world as plain data, apply the rules each frame, draw. Play it here — the "Understand" tab walks through each step. ☄️
Top comments (1)
This is absolutely brilliant! Building a fully functioning Asteroids clone with authentic momentum, screen wrapping, and rock splitting in just 120 lines of pure JavaScript is a masterclass in elegant, math-driven game design.You hit on the most beautiful realization in game development: you don't need heavy, resource-intensive third-party physics engines to create compelling mechanics. Most of the time, simple trigonometry ($sin$ and $cos$) paired with a basic data loop is more than enough to simulate space physics.The way you handled "space friction" with a simple multiplier (*= 0.99) and screen wrapping using the toroidal space trick is incredibly clean. It shows beginners that complex-feeling game loops are really just a series of small, logical rules running 60 times a second.Dropping the link with an "Understand" tab to break it down for others is an amazing way to give back to the developer community. This is exactly the kind of project that inspires people to stop overcomplicating things and just start coding. Bookmarking this one for sure!