← Learn · Build · 15 July 2026 · 4 min

The Prompt I Used to Build a 3D Flappy Bird Plane Game in Three.js

The full, copy-pasteable prompt I used to build a 3D Flappy Bird-style plane game with Three.js and Vite — physics-driven pitch, glTF propeller animation, AABB collision, and clean game states.

Overview

This is a build prompt for a 3D Flappy Bird-style game — a low-poly voxel plane that flaps through pairs of obstacle walls — written as a single-page web app with Three.js and Vite. The whole point of the prompt is one detail: making the flight feel real. Instead of snapping the plane's rotation on keypress, the pitch is driven by vertical velocity and smoothly damped toward a target angle every frame, so the nose eases up after a flap and tips forward as it falls.

What it produces: a side-scrolling 3D scene, a glTF plane with a continuously spinning propeller (baked animation clip), gravity + flap-impulse physics, velocity-driven pitch with damping, recycled obstacle pipes with AABB collision, scoring with a best-score tracker, and start / playing / game-over states — all frame-rate independent via requestAnimationFrame and delta time.

The prompt

Copy this into any AI app-builder (Replit). It assumes you've uploaded a rigged glTF plane model with a baked "Armature|prop spin" animation clip.

Build a 3D Flappy Bird-style game as a single-page web app using Three.js (import via CDN or npm), running in a Node/static environment with Vite. ASSETS: I've uploaded a glTF model (scene.gltf + scene.bin + textures folder) of a low-poly voxel plane. It's rigged with a skeleton and already has a baked animation clip named "Armature|prop spin" that spins the propeller bone. Load the model with GLTFLoader, add it to the scene, get its AnimationMixer, find the clip by that name, play it in a loop (THREE.LoopRepeat), and update the mixer every frame with the clock delta — the propeller should be visibly spinning at all times, independent of game state. CAMERA & SCENE: Side-scrolling view (camera fixed, looking at the plane from the side, slightly above), like classic Flappy Bird but in 3D. Simple sky-colored background, maybe a subtle scrolling ground/horizon for depth cues. Plane stays at a fixed X position; the world scrolls toward the camera. PHYSICS (the part I care about most — make it feel real, not arcade-y): - Constant downward gravity acceleration on the plane's vertical velocity. - Pressing spacebar (or click/tap) applies an upward impulse to velocity (like a flap/thrust). - The plane's pitch should be driven by vertical velocity, NOT by whether the key is held: map velocity to a target pitch angle (falling fast = nose tilts down/forward, strong upward velocity right after a flap = nose tilts up/backward), then smoothly interpolate (lerp/damping, not snapping) the model's current rotation toward that target every frame so it eases in and out. Clamp the tilt to a reasonable max angle (±25-35°) so it doesn't flip. - Keep horizontal position fixed; only Y (height) and pitch rotation change. PIPES / OBSTACLES: Instead of pipe sprites, use pairs of rectangular meshes (THREE.BoxGeometry, solid material) — one from a gap going down, one from the same gap going up — spawned at fixed horizontal spacing off-screen right. Randomize gap position (optionally slightly randomize gap size within a min/max). Move all active pairs toward the plane at a constant speed each frame (same as the ground scroll), recycle/despawn pairs once they pass behind the camera, and spawn new ones to keep a steady stream. Use simple AABB (bounding box) collision between the plane's box and each wall box — on collision, trigger game over. SCORING & STATES: +1 score each time the plane passes a pair (compare plane X or scroll distance, not on collision). Track and display best score. Include start screen, playing state, and game-over screen with restart (space or click). Show current score during play. POLISH (nice to have): subtle camera shake or screen flash on collision, a particle or scale-pulse effect on the plane when scoring, controls limited to spacebar/click so it works on mobile via tap. Structure the code cleanly (separate modules for scene setup, physics, pipes, and game state), and make sure the render loop uses requestAnimationFrame with delta time so speed is frame-rate independent.

Why the physics prompt is written this way

Most Flappy Bird clones rotate the sprite based on whether the button is pressed. That reads as rigid and mechanical. The trick here is decoupling rotation from input entirely:

  1. Velocity is the single source of truth. Gravity pulls velocity down every frame; a flap adds an upward impulse. Both height and pitch are derived from that one number.
  2. Pitch is a target, not a state. Map current vertical velocity to a target angle, then damp toward it (current += (target - current) * k). The nose lifts and settles on its own — no snapping.
  3. Everything is delta-timed. Multiplying movement and damping by the frame delta keeps the feel identical at 60fps and 144fps.

Notes on the glTF propeller

The propeller spin is deliberately independent of game state. It's a baked clip ("Armature|prop spin") played on loop through an AnimationMixer that ticks every frame with the clock delta — so the prop keeps turning on the start screen, mid-flight, and on game over. If your model's forward axis differs, the pitch axis in the physics step (X vs. Z rotation) is the one line you'll adjust.