The Story of Gravity Golf: Orbital slingshot physics inside Reddit

๐ŸŒŒ The Inspiration

The concept of Gravity Golf was born from a simple question: How can we turn Reddit's community-driven threads into interactive celestial playgrounds?

We wanted to capture the magic of retro gravitational slingshot games (like Kerbal Space Program trajectory planning and classic Gravitar) and merge it directly into the Reddit feed. The core vision was a premium, visually striking space console that felt like an operating cockpit terminal. It needed to be highly addictive, procedurally rich, and entirely type-safe on top of Redditโ€™s new Devvit Web environment.


๐Ÿ“ How We Built the Physics Engine & Mechanics

We bypassed high-overhead physics frameworks and built a custom Euler integration orbital solver inside Phaser 4 to achieve accurate Keplerian gravity dynamics.

1. Planetary Gravity Fields

The spacecraft's motion is governed by Newton's law of universal gravitation. In each frame step, the gravitational pull from all celestial bodies is accumulated:

$$\vec{F}g = \sum{i=1}^{N} -G \frac{m_{ship} m_i}{|\vec{r}_i|^3} \vec{r}_i$$

Where:

  • $G = 0.15$ is the scale-adjusted gravitational constant.
  • $m_i$ is the mass of the $i$-th planet.
  • $\vec{r}_i$ is the vector pointing from the ship to the center of the planet.

Applying the force accumulation, the acceleration and velocity of the spacecraft are computed iteratively:

$$\vec{v}{t+1} = \vec{v}_t + \frac{\vec{F}_g}{m{ship}} \Delta t$$ $$\vec{x}{t+1} = \vec{x}_t + \vec{v}{t+1} \Delta t$$

We implement this simulation forward in time up to 250 steps to draw the tactical trajectory prediction dots, letting users preview complex orbital paths and gravity-assists before launching.


๐ŸŽ™๏ธ Procedural Sound Synthesis (Web Audio API)

One of the largest architectural challenges was that Devvit packages static asset bundles within an isolated iframe, which regularly caused Phaser asset preloader network blocks or caching failures for .mp3/.wav audios.

To guarantee zero-crash, latency-free audio, we built a custom procedural synthesizer using the browser's native Web Audio API:

  • Engine Launch: An oscillator sweep starting at $150\text{ Hz}$ and linearly rising to $800\text{ Hz}$ over $0.25\text{ seconds}$ using an exponential gain envelope.
  • Explosions: A synthesized pink noise node passed through a low-pass filter with rapid sweep decay from $1000\text{ Hz}$ to $50\text{ Hz}$.
  • Star Collect: A high-frequency dual-oscillator chime ($880\text{ Hz} \rightarrow 1320\text{ Hz}$) forming a retro 8-bit major arpeggio.
  • Shield Deflection: A rapid frequency modulation pop using a triangle oscillator sweep.

๐Ÿš€ Challenges Faced & Solutions

1. Screen Scaling and Out-of-Bounds Glitch

  • The Problem: On mobile screens (where physical viewports shrink), the ball would immediately reset on launch. This was because the out-of-bounds boundary check evaluated against physical pixel dimensions, causing start positions on larger maps to be instantly flagged as "off-screen."
  • The Solution: We switched the Phaser scaling system from RESIZE to FIT and locked the camera logical resolution internally to $1024 \times 768$. Phaser automatically maps this logical matrix to any display device while preserving coordinate checks.

2. Vite & Phaser Bundling Isolation

  • The Problem: The console threw Uncaught ReferenceError: Phaser is not defined inside Game.ts during runtime physics loops. Vite's treeshaking separated Phaser modules, leaving the global namespace unpopulated.
  • The Solution: We eliminated all global runtime references to the Phaser package, replacing Phaser's native vector distance functions with an inline Euclidean distance helper: $$d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}$$ This resulted in a bundle that compiles in under $1\text{ second}$ with zero external dependencies.

๐Ÿ“š What We Learned

  1. Procedural Synthesis is King: Bypassing traditional media assets in serverless, iframe-framed environments like Devvit eliminates asset-loading lag and asset-blocking issues.
  2. Locked Logical Viewports: Designing layouts around a locked $4:3$ virtual aspect ratio scaled by the engine is significantly more robust than computing screen dimensions on the fly for physics slingshots.
  3. Community-Driven UGC is Powerful: Building the Level Blueprint Editor empowers players to create and share their own maps, changing the game from a single-player trial to a community universe.

Built With

Share this project:

Updates

Submission history