Void
Guide your ship through an asteroid field using only your mouse. You fire automatically — your only job is to stay alive. Waves escalate. The void doesn't forgive.
move mouse to aim · auto-fire · survive
How to play
Move your mouse over the canvas to pilot your ship. It follows your cursor smoothly. Bullets fire automatically every few frames. Destroy asteroids and enemy drones before they reach you. Each wave spawns more and faster enemies. You have three lives — collisions cost one. Reach zero and it's over.
Design notes
The aesthetic mirrors the rest of the site: Geist Mono, dark background, muted whites. Particles, asteroids, and explosions are rendered entirely on a single 2D canvas with no external libraries. The ship is a minimal triangle — one vertex always points toward the nearest threat.
Technical overview
| system | implementation |
|---|---|
| Rendering | HTML Canvas 2D, requestAnimationFrame loop |
| Ship control | mouse / touch position → lerp to target each frame |
| Shooting | auto-fire: bullet spawns at ship nose every N frames |
| Asteroids | polygon with random vertex jitter, slow rotation |
| Enemies | homing drones added from wave 3 onward |
| Collision | circle–circle distance check for all entities |
| Difficulty | wave number scales spawn count and speed multiplier |
| Particles | explosion sparks with velocity, gravity, fade-out |
Source highlights
// ship smoothly follows mouse via lerp
ship.x += (mouse.x - ship.x) * 0.12;
ship.y += (mouse.y - ship.y) * 0.12;
// auto-fire: every FIRE_INTERVAL frames
if (frameCount % fireInterval === 0) spawnBullet();
// asteroid polygon generation
for (let i = 0; i < sides; i++) {
const angle = (i / sides) * Math.PI * 2;
const r = radius * (0.75 + Math.random() * 0.5);
verts.push({ x: Math.cos(angle) * r, y: Math.sin(angle) * r });
}