| name | machin-game-demo-galaxy |
| description | Build, run, and modify machin-game-demo-galaxy — a procedural spiral galaxy with ~5000 star particles, OBAFGKM spectral colours, 4 logarithmic spiral arms, rlgl point-cloud rendering, and a WASD fly camera. Use when working on this repo or as the reference for rlgl point rendering and large-scale procedural placement in machin. |
machin-game-demo-galaxy
A procedural spiral galaxy — ~5000 stars placed along logarithmic spiral arms, coloured by spectral class, and rendered as a single rlgl point batch. Written in machin (MFL) via raylib's C FFI.
Shared game-dev setup, the FFI surface, and cross-cutting gotchas live in the canonical machin-gamedev skill. This file covers the specifics of this demo.
Build & run
./build.sh
./machin-game-demo-galaxy
Needs machin v0.48.0+, a C compiler, raylib, and a display.
Architecture
Star data (pure MFL)
type Star struct {
lx float ly float lz float // local position (pre-rotation)
mag float // magnitude / visual size
cr int cg int cb int // colour
}
All 5100 stars are stored in a []Star slice, built once in build_galaxy() before the main loop.
Spiral arm formula
Logarithmic spiral: θ = arm_offset + k · log(r / r0), with k = 2.8 controlling tightness. Per-star scatter along the arm (±0.25 rad) and perpendicular to it (±(0.08+0.035r) — widening at larger radii) creates natural-looking arms. The disk thickness is ±0.35 units.
Spectral colouring
star_spectral(t) maps a random threshold to OBAFGKM classes weighted toward dimmer red stars (matching the real stellar population). The core (r < 2.5) is biased toward yellow/orange (older population); outer arms (r > 18) bias toward blue (younger). Each class has a base magnitude that is scattered per-star by ±0.05–0.2.
Rendering
All stars are drawn in a single rlBegin(0) / rlEnd() batch (RL_POINTS). Each star emits 1–3 overlapping rlVertex3f calls depending on magnitude (brighter = more points = larger visual size). The colour is set per-point via rlColor4ub.
This is the first machin demo to use rlgl point rendering — the most efficient way to draw a large point cloud (~5000 stars = 1 draw call vs 5000 DrawSphere calls).
Rotation
v3_rot_y(v, angle) applies a 2D rotation around the Y axis. The galaxy turns at 0.012 rad/s (~1 revolution per 8 minutes). The rotation is applied per-frame during rendering (not pre-computed), so the star positions are always current.
Patterns worth copying
- rlgl point rendering.
rlBegin(0) / rlColor4ub / rlVertex3f / rlEnd() renders thousands of points in one GPU draw call. Use for stars, particles, dust, sparks, anything too numerous for individual DrawSphere calls.
- Pre-build, per-frame transform. Compute the galaxy once (5100 stars with positions, colours, sizes). Each frame, just rotate the positions around the Y axis — cheap and enables smooth rotation without rebuilding data.
- Multi-pass point size. Overlapping
rlVertex3f calls at the same position create effective multi-pixel points. 1 pass = tiny, 2 passes = medium, 3 passes = bright/large. No shader or texture needed.
- Weighted procedural distribution. Each star's spectral class is chosen from a weighted distribution (4% O, 8% B, 13% A, 15% F, 15% G, 20% K, 25% M) that mimics real stellar population statistics.
- Simple LCG for randomness. The physics demo's LCG is reused verbatim. For 5100 stars, each needing ~4 random values, the LCG produces deterministic output (same seed = same galaxy every time).
Modifying
- Star count: change 4800 to any value. The
build_galaxy loop scales linearly with star count.
- Arms: change
4 to any number. The arm_angle = arm * 2π/arms formula auto-distributes.
- Tightness: adjust
k = 2.8 — higher = more tightly wound, lower = looser.
- Disk thickness:
0.7 in build_galaxy — spread stars vertically.
- Rotation speed:
rot_speed = 0.012 — radians per second.
- Colours: edit the
star_spectral() temperature → RGB mappings.
Future directions
- Nebula dust clouds — a second particle layer using
rlBegin(RL_POINTS) with semi-transparent dark colours between the arms.
- Star names overlay — raylib
DrawText projected to 3D positions for a select few bright stars.
- Animated star formation — new stars fade in at arm tips as old stars fade at the core, driven by a slow tick.
- Billboard galaxy sprite — an alternative view from very far away showing the full disk as a textured sprite.