- 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.
108 lines
4.8 KiB
Markdown
108 lines
4.8 KiB
Markdown
# 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. |