Click a body: focus on it 1–9, 0: fly to Sun, Mercury … Neptune, Pluto — eased, and swinging round to the sunlit side Drag: rotate the view Z / X: zoom in / out Arrows: pan , / .: time slower / faster SPACE: pause time R: reverse time S: schematic (log-compressed) radii O / L: orbits / labels C: controls panel H: home The bottom strip always shows the date, the scale as 1 PX = n KM, the zoom in km/px and the time rate. The card top-left shows the focused body's radius and its distance from the Sun.
A navigable model of the solar system drawn entirely with the pen — real orbital elements, real axial tilts, Saturn's rings — that you can fly from Pluto's orbit down to forty-eight metres across a planet's surface without the picture ever shaking. THE SCALE PROBLEM IS THE PROJECT Pluto's orbit is 5.9 × 10⁹ km. A mountain is 1 km. Four decisions carry those ten orders of magnitude, and they are the whole design. Nothing is stored in screen coordinates. Positions are kilometres in the J2000 ecliptic frame and the camera owns exactly one number, kmpp — kilometres per pixel. Zooming changes that number and nothing else, so there is no accumulated scaling error to drift. Floating origin. World-to-screen subtracts the position of the focused body before scaling. Looking at Earth, the numbers entering that subtraction are Earth's own, bit for bit, so the result is exactly 0.0 — not nearly zero. The validator asserts that, because "nearly" is what jitters. Everything below the focus in the tree inherits the cancellation exactly, since the identical stored value is removed from both sides: that is why the Moon is steady when you are sitting on Earth. Hierarchical positions. Bodies are stored parent-relative and summed down the tree, so Io is Jupiter plus a 4.2 × 10⁵ km offset rather than a difference of two 7.8 × 10⁸ km numbers. The table is ordered parents-first, which makes that sum one forward pass. The trig is written out by hand — and this is the one that actually mattered. scratch-vm implements the sin and cos blocks as js parseFloat(Math.sin((Math.PI * n) / 180).toFixed(10)) rounded to ten decimal places. Every other maths block — sqrt, ln, atan, 10 ^ — is full double precision; only these two are quantised. At Pluto's semi-major axis that 5 × 10⁻¹¹ becomes 0.3 km of position error, and worse, it is a staircase: sweep the angle slowly and the value sits still for dozens of frames and then jumps. Measured, in tools/precision.py: with the per-sample change below the quantum, the built-in cos returns an unchanged value on 359 of 399 steps while the replacement changes on every one. That is the jitter everyone hits at deep zoom, and no choice of origin or units touches it, because it corrupts a body's own position before any subtraction happens. So sincos range-reduces in degrees — where the quadrant boundaries 0, 90, 180, 270 are exactly representable, so no rounded multiple of π/2 is ever subtracted — and then evaluates a Taylor series in radians, terms to r¹⁵ for sine and r¹⁶ for cosine. Worst error over [0°, 360°) falls from **5.0 × 10⁻¹¹ to 5.6 × 10⁻¹⁶**, a factor of 90,000. The fifteen coefficients are generated, not typed. The first hand-written attempt had the entire cosine series shifted by one term and a sine coefficient wrong by a factor of a thousand, and neither is visible by reading it — so tools/mktrig.py emits the goboscript block and then parses its own output back and checks it against math.sin/math.cos, failing the build rather than letting a subtly out-of-round solar system ship. It is spent only where it pays. All original - code, art and sound. See Inside is open.