Gravity Well Arena

A top-down shooter where the closer you fly to a black hole, the faster the rest of the arena runs

Screenshot of Gravity Well Arena
The callsign entry screen.

I wanted a game where the physics weren't decoration. Plenty of space games put a black hole in the background and give it a mild pull on your ship, and it changes nothing about how you play. Here the one number every other system depends on is how deep you are in a gravity well.

What the physics is

The motion is Newtonian, not relativistic. Ships and projectiles move under a softened inverse-square law,

\[\mathbf{a} = -\sum_j \frac{G M_j\,(\mathbf{x} - \mathbf{p}_j)}{\left(|\mathbf{x} - \mathbf{p}_j|^2 + \epsilon^2\right)^{3/2}}, \qquad \epsilon = 0.1,\]

integrated with velocity Verlet at a fixed step. The softening stops anything blowing up near the center. A circular orbit run for 10,000 steps stays on its circle.

The relativity is a single borrowed formula. At the player's position I compute

\[\tau = \sqrt{1 - \sum_j \frac{r_{s,j}}{d_j}},\]

clamped to \([0.01, 1]\), where \(r_{s,j}\) is each hole's Schwarzschild radius and \(d_j\) is the distance to it. With one hole that is the Schwarzschild time dilation factor. With two, the sum has no metric behind it and just plays well. Every bot and projectile then advances by \(\Delta t \cdot \tau_{\text{entity}} / \tau_{\text{player}}\), capped at 5, so when you're deep the rest of the arena runs up to five times faster than you do. Your own proper time runs at \(\tau_{\text{player}}\) times wall time, and so do your orbit-anchor and tidal-flare cooldowns, so diving speeds up everyone else and slows your own abilities down at the same time.

Two-hole levels are a restricted three-body problem: the holes follow fixed paths and the ship moves in their combined field. You can slingshot between them, but with the two clocks overlapping the trajectories get hard to predict.

Weapons

The railgun is a fast kinetic round that curves in the field like everything else. The mass driver is slower and heavier. The photon lance is a 40-step ray march that bends toward each mass by acceleration times step length over \(c^2\), with \(c^2\) set to 0.667 in game units because the physically honest value produced no visible bend. You can shoot it around a hole and hit something on the far side. The gravity bomb drops a temporary point mass into the field. The impulse rocket kicks whatever it hits deeper into the well. The tidal mine sits in orbit and detonates when something passes at a different altitude, with damage linear in the altitude gap up to a cap.

The clock mechanic ended up shaping the balance. Anything slow in flat space becomes threatening near a hole because the target's clock is running slow. So the "weak" weapons, the mines and the bombs, turned out to be the most dangerous ones in the deep zones.

Bots

Six archetypes, each trying to exploit depth from a different angle: Skirmisher, Diver, Vulture, Anchor, Swarm, and Commander, which climbs when you dive and dives when you climb. The Diver was the hardest to tune. Its whole strategy is going deep, which means everything outside is fast. Set its aggression too high and it suicides into the Abyss without reacting to incoming fire. Too low and it never commits and plays like a worse Skirmisher.

Audio

There are no audio files in the repository, only fonts. Every sound, engine hum, weapon discharge, explosion, ambient tone, is synthesized at runtime. I meant to add recorded samples later and used synthesis as a placeholder, but the synthesized sounds came out better than anything I found in free asset libraries. The engine hum pitch-shifts with \(\tau\).

Rendering and story

Rendering is wgpu with WGSL shaders for the accretion disk, a lensing pass that distorts the starfield near each hole, and bloom. Levels are generated from the level number and a seed. There's a four-act story delivered through mission briefings and radio chatter, which was an odd thing to write against procedural levels.