A polar-coordinate evolution of Boomer: a 1v1 real-time arena shooter (human vs AI) played on the inner surface of a circular world. You walk along the circumference, gravity pulls towards the core, and every projectile follows a curved trajectory under radial gravity.
Built with vanilla JS (ES6 modules), WebGL2, and Canvas 2D — no external dependencies, no build step.
ES6 modules need an HTTP server. From the repo root:
python3 -m http.server 8000
# then open http://localhost:8000Requires a browser with WebGL2 (any recent Chrome / Firefox / Safari).
- Ring terrain — a destructible polar grid (
theta × r) wrapped seamlessly around the full circle. Walk far enough in one direction and you're back where you started. - Radial gravity — "down" is always towards the core. Grenades arc dramatically; a fully charged shot can orbit the ring. By default gravity has constant strength at any altitude, so nothing can ever escape.
- Low-orbit gravity (menu toggle) — gravity instead fades with the inverse square of altitude. Feel at the surface is unchanged, but charged shots arc into towering Keplerian ellipses — and on a Small ring, a full charge exceeds escape velocity and is lost to space.
- Jetpack (low-orbit only) — E toggles slot 0 between Dig and Jetpack: the same key opens both a tunnelling strategy and a flying one. Hold fire to thrust towards the cursor on finite per-round fuel. Flying trades away terrain cover, the exhaust glow gives you away at night, and above the atmosphere ceiling you start to suffocate.
- Solar lighting — a fixed (or slowly orbiting) Sun lights one side of the ring. The lit side is warm-tinted, the dark side cool and starlit.
- Local light sources — muzzle flashes, explosions, rocket trails, lava pools, and lit windows illuminate the dark side. Firing in the dark gives your position away.
- Light-aware AI — the bot aims worse at targets in shadow, reacts slower, spots your muzzle flash, dodges laser sights, and (on Hard) deliberately fights from the dark.
- Clamber — jump onto a near-vertical face while pressing towards it and you grip it for a beat (a slow wall-slide); a fresh jump press launches you up and away. Chain taps to scale buildings: every tall obstacle now has two routes — through (dig) or over (clamber). The AI climbs too.
- Grapple hook — F throws a hook at the cursor; if it bites terrain the rope goes taut and you swing as a pendulum under radial gravity. Hold W to reel in, press F again to release with your momentum. The third route past any obstacle: through, over, or across. Blasts sever the line.
- Meteor storms (menu toggle) — every so often a warned bombardment craters the sector you're fighting in. Take cover, or dig.
- Med-kit crates — some parachute drops heal +35 HP instead of carrying ammo. Contested, and the chute can still be shot off.
- Headshots — direct hits to the head deal 1.4× damage. A carefully sighted sniper shot pays; blast splash never qualifies.
- What's New — the main menu carries an abbreviated changelog; the full
design log with playtest notes is
FEATURES.md. - The core — dig all the way through the crust and there's nothing to stand on. The glow at the centre is not friendly.
| Input | Action |
|---|---|
| A / D or ←/→ | Run around the ring |
| W / ↑ / Space | Jump (radially outward); tap while gripping a wall to clamber |
| Mouse | Aim |
| Click / hold | Fire / charge (grenade, cluster) / sight (sniper) |
| E | Dig (low-orbit mode: press again to toggle Jetpack) |
| F | Grapple hook: throw / release (hold W to reel in) |
| 1–5 | Weapons (Rocket, Shotgun, Grenade, Sniper, Cluster) |
| Q | Next weapon |
| R | Restart round |
| Esc | Menu |
Two stacked canvases:
terrain-canvas(WebGL2): a fragment shader maps every screen pixel through the camera transform into(theta, r), samples the polar material texture, and applies solar + point lighting, depth shading, sky, stars, and the core glow (js/renderer.js).overlay-canvas(2D): players, projectiles, particles, crates, and UI, positioned via the exact same camera transform (js/camera.js).
Physics runs in world Cartesian coordinates with gravity applied towards the
origin — equivalent to integrating in polar coordinates but simpler and free
of angular-velocity scaling artefacts. Terrain storage, destruction
(destroyDisc), and collision sampling are all polar.
Game logic (weapons, AI state machine, materials, crates, audio, rounds) is
ported from Boomer 2D — see that repo's BOOMER_WORLD.md for the original
design document.
- British spellings in comments and user-facing text
- Conventional commits (
feat:,fix:, …) - All tuning constants live in
js/constants.js - No build step — just serve the directory