Files
flight-sim/README.md
T
Quintine 8c19cdaae6 3D flight simulator: 6-DOF physics, three.js r160, browser HUD
- Detailed flight dynamics: aero lift/drag/side-force with smooth stall,
  control-surface moments, stability derivatives, engine spool with prop
  torque and gyro precession, inertial coupling, ISA atmosphere, ground
  effect, 3-point gear handling, landing vs crash classification.
- Pure ESM, zero build step; three.js vendored locally. Deterministic
  simulation; physics core is Node-testable (14 node:test cases).
- Procedural 8 km world with runway, water, sky dome, cloud wrap; DOM
  instrument panel (attitude indicator, tapes, VSI, lamps, stall warning).
- Controls: WASD/arrows, Q/E rudder, Shift/Ctrl throttle, F flaps, G gear,
  B brakes, C camera (chase/cockpit/orbit), R reset, P pause, D debug.
2026-08-24 17:58:58 +10:00

108 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Flight Sim
A browser 3D flight simulator: a detailed 6-DOF propeller aircraft flown over a
procedural 8 km world, with an instrument HUD, synthesized engine/wind audio and
three camera views (chase / cockpit / orbit). Pure ES modules, zero build step,
no assets, no runtime network — Three.js r160 is vendored locally.
Spawn: on the south end of the runway, engine idling, flaps 25 %, gear down,
brakes on. Throttle up with **Shift**, release brakes with **B**, roll forward
with the stick, and rotate at ~120–140 kts.
## Run it
ES modules must be served over HTTP (opening `index.html` directly on `file://`
is blocked by the browser). From the project root:
```bash
python3 -m http.server 8080
# or
npx serve .
```
Then open <http://localhost:8080>. Fullscreen canvas; **CLICK TO START**
enables audio (the browser requires a user gesture for WebAudio).
## Controls
> Table below mirrors `KEY_BINDINGS` from `src/controls.js` (single source).
| Key | Command |
|----------------|--------------------------------|
| `W` / `S` | Elevator — pitch up / down |
| `A` / `D` | Aileron — bank left / right |
| `↑` / `↓` | Elevator (arrow keys) |
| `←` / `→` | Aileron (arrow keys) |
| `Q` / `E` | Rudder — yaw left / right |
| `Shift`/`Ctrl` | Throttle up / down |
| `F` | Flaps 0 → 25 % → 50 % → 100 % |
| `G` | Gear up / down |
| `B` | Brakes on / off |
| `C` | Camera view (chase/cockpit/orbit) |
| `R` | Reset flight |
| `P` | Pause |
| `D` | Debug overlay |
| `S` / `Enter` | Sound on / off |
Sticks slew smoothly (~1.6 full-range/s), throttle slews slowly (~0.4/s) so
engine response feels realistic; toggle keys ignore auto-repeat.
## Architecture
```
index.html static shell: canvas, #hud, start overlay
css/style.css HUD/instrument glass styles + start overlay (integrator)
src/main.js game loop, fixed-timestep physics driver, cameras,
crash/reset/pause/debug, audio + HUD feed (integrator)
src/config.js SI constants — single source of truth (airframe, atmo)
src/world.js deterministic height field + runway (single ground source)
src/physics.js 6-DOF rigid-body dynamics, ground model, crash logic
src/controls.js keyboard → smoothed inputs + action events
src/aircraft-model.js Three.js visual model (surfaces/prop/gear animate)
src/terrain.js sky, sun, elevation-mapped ground, runway, water, clouds
src/instruments.js DOM instrument overlay (attitude, tapes, lamps, stall)
src/audio.js synthesized engine/wind/stall/touchdown (WebAudio)
vendor/three.module.min.js Three.js r160 (vendored)
```
### Loop
`main.js` runs a fixed-timestep sim: real frame dt is clamped to 0.05 s,
accumulated, and consumed in 1/120 s physics steps (max 8 per frame), so
simulation behaviour is frame-rate independent and deterministic. No
`Math.random()` anywhere in physics; cosmetic randomness is seeded.
### Physics summary
- Body frame **+X forward, +Y right, +Z down**; quaternions `[w,x,y,z]`;
heading 0° = north, +Y world up.
- Forces: stability-axis lift fitted with a smooth stall blend toward the
flat-plate regime, drag `CD0 + k·CL² + flaps/gear + flat-plate`, side force
from β and rudder; moments from static stability, control effectiveness and
rate damping (`Cmq`, `Clp`, `Cnr`).
- Engine: first-order spool to throttle, thrust scaled by `(ρ/ρ0)^0.7`,
prop torque and gyroscopic moment about the thrust axis.
- Inertial coupling with the full symmetric inertia tensor; semi-implicit
Euler integration at 1/240 s substeps, quaternion renormalised per substep.
- Ground: wheel-height contact, crash vs. landing classification by sink rate,
gear state and attitude; rolling friction, ×3 braking, ground steering,
taxi thrust. Fuel burn ∝ rpm·throttle.
- Atmosphere: ISA density lapse with altitude.
### Camera modes (`C`)
1. **Chase** — smooth follow 8 m aft / 2.2 m above the c.g., looking just
ahead of the nose.
2. **Cockpit** — pilot eye at `aircraft-model.cockpitOffset()`, hard-locked to
the aircraft attitude with a subtle g-load sway.
3. **Orbit** — slow auto-spin around the ship; drag with the mouse to steer
the view angle and height.
### Notes
- Shadows are disabled by default (cheap path; flip
`buildEnvironment(scene, { shadows: true })` and enable
`renderer.shadowMap` in `main.js` to test the 4096 px variant).
- Altimeter/airspeed/VS are pitot-static cosmetics: ft, kts, fpm.
- One CSS file owns all HUD look; `instruments.js` only sets per-frame
transforms and class toggles.