An interactive Newtonian gravity simulator written in C++ with raylib.
▶ Play it in your browser — no install needed (built to WebAssembly on every push).
Place dots of any mass on an infinite canvas and watch them attract, orbit, slingshot, and merge. Spawn preset systems — solar systems, binary stars, colliding galaxies, a stable three-body figure-eight — with a live preview at your cursor, and fly around the space with pan and zoom.
- N-body physics — softened Newtonian gravity, semi-implicit Euler integration with substepping, three collision modes (pass-through, momentum-conserving merge, or merge with debris ejection), and toggleable tidal disruption that pulls small bodies apart on deep passes near heavy ones
- Placement — click to drop a dot at the current mass (log-scale slider, 1–20,000), or drag and release to flick-launch it with an aimed velocity; while aiming, a dotted preview shows the candidate's trajectory ~5 seconds ahead through the current field, stopping at the first impact; click an existing dot to drag it around
- Patterns — 11 presets placed with a mouse-follow ghost preview: Solar System, Binary Stars, Planet + Ring, Spiral Galaxy, Grid Collapse, Random Cloud, Figure-8, Moons, Collision, Comets, Black Hole
- Camera — infinite pan (right/middle drag), zoom to cursor (wheel), reset view, jump to the barycenter of all bodies or lock onto it with follow-center, or double-click a body to follow it
- Time — sim-speed slider (0.1x–10x) and single-frame stepping while paused
- Inspection — toggleable per-body velocity vectors and a live gravity vector-field overlay (Lagrange regions show up as gaps)
- Effects — additive glow halos on heavy stars, energy-scaled shockwave rings on impacts (black holes swallow without a ripple), and black holes with a photon ring and swirling accretion disk
- Space curvature — a GPU fragment shader warps the grid into gravity wells around the heaviest bodies, rubber-sheet style (works on desktop GL and WebGL)
- Rendering — motion trails with adjustable length, adaptive world grid, 4x MSAA, native-resolution (HiDPI) output, Inter font UI with hover tooltips on every control
| Input | Action |
|---|---|
| Left click | Place a dot at rest / drag an existing dot / stamp a pattern |
| Left drag on empty space | Flick-launch a dot: pull back like a slingshot, release to fire |
| Double-click a dot | Follow it with the camera (Esc, R, or panning stops following) |
| Right or middle drag | Pan the camera |
| Mouse wheel | Zoom (centered on cursor) |
Space |
Pause / resume |
Up / Down |
Adjust placement mass |
T |
Toggle trails |
G |
Toggle grid |
V |
Toggle velocity vectors |
B |
Toggle gravity field overlay |
W |
Toggle space-curvature grid (shader) |
. |
Advance one frame while paused |
M |
Cycle collision mode (none / merge / debris) |
D |
Toggle tidal destruction (heavy dots pull small ones apart) |
R |
Reset view |
H |
Center camera on all bodies |
J |
Toggle follow-center (camera tracks the barycenter) |
F |
Toggle fullscreen |
C |
Clear canvas |
Esc |
Cancel pattern placement |
Everything with a shortcut also has a button in the on-screen panel.
Prebuilt macOS / Linux / Windows binaries are attached as artifacts to every desktop build run.
- CMake 3.15+
- A C++17 compiler (Clang, GCC, or MSVC)
- Git
raylib is vendored as a git submodule and built from source — no system-wide install needed.
git clone https://github.com/siddharthroy12/gravitysandbox.git
cd gravitysandbox
./run.shrun.sh initializes the raylib submodule if needed, configures CMake, builds, and launches. Options:
./run.sh --build # compile only, don't launch
./run.sh --clean # wipe the build directory and rebuild from scratchWith Emscripten installed (brew install emscripten on macOS):
./build-web.sh # build only (./build-web.sh --clean rebuilds from scratch)
./run.sh --web # build and serve locallybuild-web.sh compiles to WebAssembly into build-web/; run.sh --web then
serves the result at http://localhost:8080/gravity_sandbox.html. The font is
bundled into the page's virtual filesystem automatically. To deploy, copy
gravity_sandbox.{html,js,wasm,data} and assets/icon.png from build-web/
to any static host.
git submodule update --init --depth 1 vendor/raylib
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
./build/gravity_sandboxOn Linux you'll need raylib's X11/Wayland dependencies first (Debian/Ubuntu):
sudo apt install libasound2-dev libx11-dev libxrandr-dev libxi-dev \
libgl1-mesa-dev libglu1-mesa-dev libxcursor-dev libxinerama-dev├── src/
│ ├── main.cpp # app loop, input, camera, world grid, HUD
│ ├── body.h # Body struct, shared constants, mass/radius/color helpers
│ ├── physics.* # N-body integration and collision resolution
│ ├── patterns.* # preset pattern generators
│ └── ui.* # theme, font loading, immediate-mode widgets
├── assets/ # Inter font (SIL OFL license) + app icon, copied next to the binary at build
├── vendor/raylib/ # raylib submodule, built statically via CMake
├── CMakeLists.txt
└── run.sh # build-and-run convenience script
- Forces use a Barnes-Hut quadtree (θ = 0.7, O(n log n)) above 200 bodies and brute-force pairwise summation below, both with a softening term (
SOFTENING2) that caps close-range forces and avoids singularities. Collision pairing likewise switches to a uniform spatial grid over each body's swept path when the scene is large. The gravity field overlay samples through the same quadtree (rebuilt once per frame), so it stays cheap at any body count. - Integration is semi-implicit (symplectic) Euler at 2 substeps per frame, which keeps orbits stable over long runs.
- When merging is enabled, bodies whose cores overlap combine into one, conserving mass and momentum; the merged color and radius follow the new mass.
- The Figure-8 pattern uses the Chenciner–Montgomery three-body choreography initial conditions, rescaled from normalized units to the simulation's G and pixel scale.
Code: no license specified yet. The bundled Inter font is licensed under the SIL Open Font License 1.1; raylib is zlib/libpng.
