---
title: "The Prompt I Used to Build a 3D Flappy Bird Plane Game in Three.js"
seoTitle: "The Prompt I Used to Build a 3D Flappy Bird Plane Game in Three.js | Avi\n      Vashishta"
description: "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."
date: "2026-07-15"
type: "build"
reel: "Da0dg1yyZ4V"
tags: []
legacy: true
---
<h2>Overview</h2>
      <p>
        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
        <a href="https://threejs.org" rel="nofollow">Three.js</a> and Vite. The
        whole point of the prompt is one detail: making the flight
        <em>feel</em> 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.
      </p>

      <div class="highlight">
        <p>
          <strong>What it produces:</strong> 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 <code>requestAnimationFrame</code> and delta time.
        </p>
      </div>

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

      <div class="prompt">
        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 &amp; 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
        &amp; 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.
      </div>

      <h2>Why the physics prompt is written this way</h2>
      <p>
        Most Flappy Bird clones rotate the sprite based on whether the button is
        <em>pressed</em>. That reads as rigid and mechanical. The trick here is
        decoupling rotation from input entirely:
      </p>
      <ol>
        <li>
          <strong>Velocity is the single source of truth.</strong> Gravity pulls
          velocity down every frame; a flap adds an upward impulse. Both height
          and pitch are derived from that one number.
        </li>
        <li>
          <strong>Pitch is a target, not a state.</strong> Map current vertical
          velocity to a target angle, then damp toward it (<code             >current += (target - current) * k</code>). The nose lifts and settles on its own — no snapping.
        </li>
        <li>
          <strong>Everything is delta-timed.</strong> Multiplying movement and
          damping by the frame delta keeps the feel identical at 60fps and
          144fps.
        </li>
      </ol>

      <h2>Notes on the glTF propeller</h2>
      <p>
        The propeller spin is deliberately independent of game state. It's a
        baked clip (<code>"Armature|prop spin"</code>) played on loop through an
        <code>AnimationMixer</code> 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.
      </p>
