I Prompted Ox Alpha to Build a 3D Marble Physics Maze — Custom Collision Math, No Physics Library, One Shot


The third genre in our Ox Alpha stress test moves away from open-world generation and endless-runner styling into something that lives or dies on physics correctness: a tilt-the-platform marble maze, where sloppy collision math is immediately, visibly obvious to anyone playing.
What I asked for
The prompt deliberately left the physics implementation open — either write custom collision math or load Cannon-es via CDN — to see which path Ox Alpha would take under time/complexity pressure.
You are a creative WebGL developer specializing in physics simulations and Three.js.
Build a complete, fully playable, single-file HTML/JS 3D Marble Physics Maze game.
Requirements:
- Single File: Self-contained index.html.
- CDN: Load Three.js (r128). Implement custom velocity/sphere-plane collision physics or load Cannon-es via CDN (https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.min.js).
- Mechanics & Controls:
- Tilt the maze platform using WASD / Arrow keys or drag controls to guide a metallic 3D sphere.
- Realistic gravity acceleration, friction, momentum, and bounce physics.
- Obstacles: Moving pushers, rotating hazard bars, holes/traps, speed booster pads, and bounce pads.
- Level Progression:
- At least 3 sequential maze stages with increasing complexity.
- Checkpoints and goal trigger zone that advances the stage upon marble entry.
- Procedural Audio (Web Audio API):
- Continuous rolling rumble modulated by marble velocity, surface click/bounce impacts, booster chime, trap fall noise, and victory fanfare.
- UI:
- Stage timer, Fall counter, Current Level display, and Level Complete modal.
Output only complete, production-ready code.
Interactive Demo
W A S D / Arrow Keys to drive
This is Ox Alpha's unedited one-shot output. Use WASD, arrow keys, or mouse drag to tilt the platform and guide the marble to the glowing goal ring.
Choosing to write physics from scratch
Given the option to load Cannon-es, Ox Alpha instead wrote its own fixed-timestep physics loop: a 120Hz substep (STEP = 1/120) accumulator pattern that decouples simulation rate from frame rate, capped at 12 substeps per frame to avoid a spiral-of-death if the tab stalls. Gravity is applied in the platform's local tilted space by transforming a world-down vector through the inverse of the board's rotation each step — a detail that matters because it means gravity genuinely follows the tilt rather than the platform visually rotating while the ball still falls straight down.
Collision math
Sphere-vs-box collision (collideBox) computes the closest point on the box surface to the ball center, derives a penetration normal and depth, and applies restitution only along the normal component of relative velocity — a proper reflected-bounce calculation rather than a simple "push it back and zero the velocity" shortcut. The same function is reused for the level border walls, interior walls, and the moving sine-driven pushers, with the pusher's own velocity fed in as svx/svz so the ball correctly inherits momentum from a pusher that's actively moving into it.
The rotating hazard bars go a step further: rather than colliding in world space, the ball's position is transformed into the bar's local rotated frame (lx/lz via a rotation matrix built from the bar's current spin angle), collision is resolved as an axis-aligned box in that local frame, and the result is rotated back to world space. This correctly handles a spinning obstacle without needing per-frame world-space box recomputation.
Holes, boosters, and bounce pads
Holes use a two-stage falloff: inside the hole radius the ball gets pulled toward the center with increasing force as it nears the middle (simulating losing its footing), and just outside the radius there's a smaller "lip" pull so the ball can still be tipped in from a near-miss rather than only from a dead-center overlap. Booster pads apply directional acceleration only while the ball is grounded and use a cooldown timer so the sound doesn't retrigger every physics substep. Bounce pads read incoming vertical velocity and only trigger above a minimum impact speed, with a visual squash-and-stretch animation on the pad mesh itself when triggered.
What impressed me
Choosing to hand-roll the physics instead of loading Cannon-es — when the prompt explicitly offered that as the easier path — produced a tighter, more purpose-built result. General physics engines solve the general case; here, every collision routine is shaped exactly around what this game needs (sphere vs. static box, sphere vs. moving box, sphere vs. rotating box, sphere vs. radial pull zone), which is arguably a more sophisticated choice than reaching for a dependency.
The local-rotated-frame trick for the spinning hazard bars stood out specifically — transforming into the rotating object's own coordinate frame to do axis-aligned collision, then transforming back, is the kind of solution that shows up in real physics engines but wasn't spelled out anywhere in the prompt.
Audio is also tightly coupled to physics state rather than bolted on afterward: the rolling rumble's filter frequency and gain both track marble speed and grounded state every frame (AU.setFrame), so it responds continuously rather than only firing on discrete events.
What needs work
- Camera can clip through walls at sharp angles — the follow camera doesn't do its own collision detection against maze walls, so it's possible to get a wall-obstructed view momentarily on tight corners.
- No difficulty-adjustable tilt sensitivity —
MAX_TILTis a fixed constant; there's no in-game way to adjust sensitivity for players who find the default too twitchy or too sluggish. - Only one effort tier tested — this run used Ox Alpha's High setting only, consistent with the rest of this genre-test round.
Honest assessment
Try it yourself
You are a creative WebGL developer specializing in physics simulations and Three.js.
Build a complete, fully playable, single-file HTML/JS 3D Marble Physics Maze game.
Requirements:
- Single File: Self-contained index.html.
- CDN: Load Three.js (r128). Implement custom velocity/sphere-plane collision physics, or load a physics library via CDN.
- Mechanics: Tilt the maze platform with WASD/arrows or mouse drag to guide a metallic 3D sphere. Realistic gravity, friction, momentum, and bounce.
- Obstacles: Moving pushers, rotating hazard bars, holes/traps, speed boosters, bounce pads.
- Level Progression: At least 3 sequential stages with increasing complexity, checkpoints, and a goal trigger zone.
- Procedural Audio: Velocity-modulated rolling rumble, impact clicks, booster chime, trap fall sound, victory fanfare.
- UI: Stage timer, fall counter, current level display, Level Complete modal.


