Turn: ← → or A D — torque, not a fixed turn rate Thrust: ↑ or W Fire: SPACE Physics readout: P Restart: R
Vector-graphics Asteroids drawn entirely in pen, with rocks that are real rigid bodies — they have mass, a real moment of inertia, and splits that conserve both momentum and spin. THE INTERESTING BIT The rocks are rigid bodies, not sprites with a spin value. Each polygon's area and its exact polar moment of inertia about its own centroid are computed from the outline by tools/mkdata.py, using the standard signed-area polygon formulas — which also recentres every shape on its centroid, because a polygon rotating about anything other than its centre of mass visibly wobbles. A bullet strike is an impulse J applied at the contact point r, so it changes the velocity by J/m and the spin by (r × J)/I. Hitting a big rock near the edge sets it tumbling; hitting it dead centre does not. A split conserves both, and the spin factor is derived rather than chosen. Two children of half the parent's mass with equal and opposite separation velocities carry exactly the parent's momentum. For spin: halving the mass and dividing the radius by √2 gives each child I_c = I_p/4, so the pair has I_p/2, and setting ω_c = 2ω_p makes Σ I ω come out at exactly I_p ω_p. **The fragments really do spin twice as fast as their parent.** Press P and the game shows you Σp, Σ I ω and — the honest part — SPLIT ERR, the worst discrepancy in Σp it has ever seen across a split. That readout earned its place twice over during development: - It started at 0.35, which is enormous. Cause: fragments were being given a random polygon. The six shapes span area coefficients 1.60 to 2.16, so a child's mass was not half its parent's and the split was inventing momentum. Nothing on screen looked wrong. - After fixing that it read 3.7 × 10⁻⁴, because the medium radius was written as 21.213 rather than 30/√2. That is a mass ratio of 0.499989 instead of 0.5. Written out to full precision, a 330-frame run of the compiled .sb3 under the headless harness — firing continuously through a whole wave, 310 points of rocks split — ends with a worst-ever split error of 4.6 × 10⁻¹⁵ in Σp and 5.7 × 10⁻¹⁴ in Σ I ω. That is double-precision noise: the splits are exact. Screen wrap draws the mirror. A rock within its own radius of an edge is drawn again shifted 480 or 360, and one in a corner is drawn four times. Collision uses the matching minimum-image convention, so a bullet just off the right edge can hit a rock just off the left one. The wrap seam is exactly where naive versions give themselves away. Collision is per-polygon. A bounding circle over these rocks claims up to 55% more area than the rock actually has. The broad phase is a wrapped circle test; the narrow phase is exact — bullet travel is a segment tested against all ten edges, so a bullet moving 8.5px a frame cannot tunnel through a thin rock, and the ship is four edges against ten plus a containment test in both directions. HONEST LIMITATIONS - **Fragment separation adds orbital angular momentum that is not corrected for.** The two children are placed either side of the parent's centre, so while Σ I ω (spin) is conserved exactly, angular momentum about a fixed origin is not. Screen wrap makes the fixed-origin quantity meaningless anyway — a body teleporting 480px changes its moment arm — so the readout tracks spin, and says so. All original - code, art and sound. See Inside is open.