Build a 3D Ball Balance Game with Three.js — Tilt Platform Physics
Three.js makes 3D game development accessible in the browser without plugins. For our latest build, we challenged ourselves to create a physics-based platform game where you tilt a surface to guide a ball toward coins while keeping it from falling off.
The result is 3D Ball Balance — a game that combines simple tilt mechanics with coin-collection gameplay, all powered by Three.js r128 and a custom physics simulation.
Play the Game
Use WASD / arrow keys to tilt the platform. Roll the blue ball toward the golden coins to collect them. Don’t let the ball fall off the edge! Press R to restart after game over.
Built by DeepSeek V4 Flash via Nexum Router — 329 lines, 13.5 KB, ~$0.001 costTilt the platform with WASD or arrow keys to roll the ball. Collect coins. Don’t fall off. Press R to restart.
Try it in bot mode too: the AI steers the ball toward the nearest coin automatically. Open the game directly at /games/3d-ball-balance/?bot=true to see it in action.
Why Three.js for a Physics Platformer?
Three.js was the natural choice here for three reasons:
-
Native 3D rendering — Platform tilt, ball rotation, and coin bobbing are fundamentally 3D operations. Phaser’s 2D engine would require manual perspective projection.
-
Lightweight for simple physx — We’re simulating gravity and friction on a flat surface, not running a full physics engine. Three.js’s render loop plus a few lines of physics math keeps the bundle under 14 KB.
-
Shadow maps and lighting — The game uses directional light, fill light, and shadow maps to give the ball, platform, and coins depth. This creates the visual polish that makes the game feel tangible.
How the Physics Works
The core mechanic is a simulated ball on a tilted plane. When you press W/S, the platform rotates around its X axis. A/D rotates around its Z axis. Here’s the critical physics loop:
// Acceleration = gravity * sin(tilt angle)
const ax = -GRAVITY * Math.sin(tiltZ);
const az = GRAVITY * Math.sin(tiltX);
velX += ax * dt;
velZ += az * dt;
velX *= FRICTION;
velZ *= FRICTION;
ball.position.x += velX * dt;
ball.position.z += velZ * dt;
The ball accelerates down the slope (controlled by Math.sin(tiltAngle)) and decelerates via friction (FRICTION = 0.98 per frame). The height follows the tilt surface:
const heightOffset = Math.sin(tiltZ) * localX + Math.sin(tiltX) * localZ;
ball.position.y = 2 + heightOffset;
This makes the ball appear to actually roll on the platform surface rather than clip through it. Ball rotation is purely visual — ball.rotation.x and ball.rotation.z spin proportionally to velocity, giving the illusion of rolling without needing a full rigid-body simulation.
What the AI Got Right on First Pass
DeepSeek V4 Flash built the complete game in a single generation:
- Full game loop — tilt physics, coin collection, game over detection, reset
- Visual polish — glow pulse on the ball, emissive materials, edge glow on the platform
- Bot mode —
?bot=trueURL param activates AI steering toward nearest coin with wander-back-to-center when no coins are visible - Responsive nav — sticky header with iframe detection, works embedded in blog posts or standalone
The CDN URL used cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js instead of the skill’s recommended jsdelivr.net/npm/[email protected]/ — but both resolve to the same Three.js r128 build (verified HTTP 200). The game works identically on either.
Lessons Learned
Tilt vs direct movement. The original design considered moving the ball with WASD directly (like a top-down racer). Tilt-platform physics is harder to control but more satisfying — the ball has momentum, so you have to anticipate rather than react. This adds a skill layer that makes coin collection feel earned.
Coin respawn timing. The game spawns 3 initial coins and up to 5 total, with a 2-second respawn delay after collection. This keeps the platform populated without overwhelming the player. The bot mode uses getNearestCoin() to steer toward the closest uncollected coin, with wander-back-to-center as a fallback.
Edge detection. The game over condition checks if the ball’s X or Z position exceeds PLATFORM_HALF (150 units). The ball glows red and stops moving when it falls off, creating a clear visual signal. The platform’s neon edge glow (opacity 0.3) provides a subtle boundary hint during gameplay.
Cost & Stats
- Model: DeepSeek V4 Flash
- Provider: DeepSeek API (via Nexum Router)
- Input tokens: ~2,400
- Output tokens: ~5,900
- Total size: 329 lines, 13.5 KB
- Cost: ~$0.001
- Build time: ~45 seconds
Try It Yourself
Play the game at /games/3d-ball-balance/ or jump straight to bot mode to watch the AI play. The full source is on GitHub — Three.js r128 with zero dependencies beyond the CDN script.
What you learned: Three.js can handle simple tilt-platform physics with ~50 lines of custom math — no physics engine needed. The combination of Math.sin(tilt) * GRAVITY for acceleration, FRICTION multiplier for deceleration, and surface-height tracking creates convincing ball-rolling behavior in under 400 lines of code.