Flight (js/flight/): tube-mode controller in spline space (s,x,y) — flow-locked forward motion, throttle as a spring-back lean, boost + i-frames, banking chase cam on the parallel-transport frame, arcade wall response (shove + graze damage, never a hard stop). Twin-stick input: WASD/left-stick moves the ship in the disc, mouse/right-stick aims, Shift/Ctrl is throttle. Gamepad supported. Combat (js/combat/): lysozyme cannon (pooled, instanced, heat-limited with hysteresis lockout) + antacid torpedo emitting level:neutralize. Enemy framework with floater/seeker/turret and turn-rate-limited homing darts, spawned from C's level:event. Coat/hull model and the full bus surface E builds against. Measured (deterministic stepper): flow-lock exact (3s at flow 14 -> s=44.0); boost peak 30.8 u/s; heat 4s fire -> 2s lockout; wall slam 13.3 coat at 11.3 u/s with forward speed untouched; 10 combat draws at 55 live enemies (budget <=80); 0.10 ms/frame CPU; 0 leaks over 20 create/dispose cycles. fps NOT claimed — rAF does not run in the automated pane. Evidence: docs/shots/laneB/. Three findings escalated in LANE_B_NOTES: - qa.sh gate #1 is a no-op: node --check silently exits 0 on ESM, so the syntax gate has never checked anything. I shipped a real SyntaxError past a GREEN qa. Fix + verification handed to F. - Surf is structurally broken: the peristalsis wave (13.64 u/s) is slower than the player (19.6 u/s), so level 2's signature mechanic loses to mashing throttle. Not tunable from this lane; escalated to A/F with options. - Custom ShaderMaterials need #include <colorspace_fragment>, else ART_BIBLE's hostile amber reaches the display as rgb(255,26,6). Fixed here; stub/walls inherit it. js/flight/dev.html is a dev harness (boot.js has no player wiring yet); it retires once F pastes the snippet in LANE_B_NOTES. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
114 lines
6.2 KiB
JavaScript
114 lines
6.2 KiB
JavaScript
// flight/tuning.js (Lane B) — THE FEEL. Every number that decides how GUTS handles lives
|
||
// here and nowhere else. Tuned by hand on the stub esophagus; re-tune per biome later.
|
||
//
|
||
// Stub reference frame (js/stub/world_stub.js), which all of these are sized against:
|
||
// biome.flow = 14 u/s · radius 10 ±15% wobble => 8.5..11.5
|
||
// wallRho = radius − waveAmp(0.9) − skin(0.6) => a ~7.0..10.0 playable disc radius
|
||
// peristalsis crest travels at WAVE_W/WAVE_K = 3.0/0.22 = 13.64 u/s
|
||
//
|
||
// SURF IS A SHOVE, NOT YET A RIDE — and that is a world-side problem, not a tuning one.
|
||
// Measured in-engine this round (numbers in LANE_B_NOTES §surf):
|
||
// crest phase speed = WAVE_W/WAVE_K = 3.0/0.22 = 13.64 u/s
|
||
// player top speed = flow × throttleMax = 14 × 1.4 = 19.6 u/s
|
||
// A wave travelling 13.64 u/s cannot carry anything faster than 13.64 u/s, so "ride the
|
||
// crest" can never be the fast line while the wave is slower than the player. Worse, the
|
||
// bonus is self-cancelling: the crest window is fixed in SPACE, so a bigger surf.gain just
|
||
// ejects you out the front sooner. Measured distance gained per crest is ~3.0 units at
|
||
// gain 0.4, 0.75 AND 1.2 — identical. Tuning this number cannot fix it.
|
||
//
|
||
// So surf currently reads as what the wave physically is: a rhythmic peristaltic SHOVE as
|
||
// each crest sweeps over you (~0.3-0.6 s at 24.5 u/s), which is honest and feels good, but
|
||
// it is not the level-2 speed line the GDD asks for. The fix belongs to whoever owns the
|
||
// wave constants (stub = F, world = A): crest speed must exceed 19.6 u/s. Escalated in
|
||
// LANE_B_NOTES §"-> Lane A / F" with options. Do not paper over it here.
|
||
//
|
||
// gain below is therefore chosen for FEEL (punch of the shove), not for speed economy.
|
||
|
||
export const TUNING = {
|
||
ship: {
|
||
radius: 0.9, // collision sphere (hull reads ~1.9 long, 1.2 wide)
|
||
},
|
||
|
||
// --- forward motion along s -------------------------------------------------------
|
||
flow: {
|
||
throttleMin: 0.6, // GDD: throttle is ±40% of biome flow, never a full stop
|
||
throttleMax: 1.4,
|
||
throttleRate: 1.8, // throttle units/s while held (0.6 -> 1.4 in ~0.45 s)
|
||
throttleReturn: 0.9, // /s spring back to neutral 1.0 when hands off
|
||
},
|
||
boost: {
|
||
gain: 1.2, // +120% of biome flow (GDD)
|
||
duration: 0.55, // s of burst
|
||
cooldown: 2.4, // s from spend until available again
|
||
iframes: 0.35, // s invulnerable "at spend" (GDD) — shorter than the burst,
|
||
// so boosting *through* something is a read, not a get-out
|
||
fovKick: 13, // degrees of extra FOV at full burst (speed you feel)
|
||
},
|
||
surf: {
|
||
threshold: 0.45, // world.flowPulse(s,t) above this = on the crest.
|
||
// pulse=pow(sin,3) so 0.45 => sin>0.766 => the peak 22% of
|
||
// each wave: a ~6.3 u window in a 28.6 u wavelength.
|
||
gain: 0.75, // +75% flow while on a crest => a 24.5 u/s shove for ~0.3-0.6 s.
|
||
// Feel-tuned only; see the surf note in the header before
|
||
// touching it expecting a speed change.
|
||
ramp: 3.0, // /s blend in/out so cresting doesn't pop
|
||
},
|
||
|
||
// --- movement inside the cross-section disc ---------------------------------------
|
||
disc: {
|
||
accel: 78, // u/s²
|
||
maxSpeed: 13, // u/s — crosses the ~16 u tube in ~1.2 s: dodgeable, not twitchy
|
||
damping: 6.5, // /s exponential drag => coasts to rest in ~0.3 s
|
||
},
|
||
|
||
// --- aim: the reticle leads, the ship follows (Star Fox lag) -----------------------
|
||
aim: {
|
||
distance: 26, // u ahead (in s) that the reticle plane floats
|
||
sensitivity: 0.022, // disc units per pixel of mouse movement
|
||
padSpeed: 20, // u/s at full right-stick deflection
|
||
range: 9, // max |aim| from the centreline (≈ the widest wallRho)
|
||
recenter: 0.8, // /s drift back to centre when hands off
|
||
lag: 9, // /s spring — the ship's nose chases the reticle, never snaps
|
||
},
|
||
|
||
// --- attitude: bank into lateral motion -------------------------------------------
|
||
bank: {
|
||
gain: 0.055, // rad of roll per u/s of lateral disc velocity
|
||
max: 0.75, // rad (~43°)
|
||
rate: 7, // /s spring toward target roll
|
||
pitchGain: 0.03, // rad of pitch per u/s of vertical disc velocity
|
||
},
|
||
|
||
// --- chase camera ------------------------------------------------------------------
|
||
cam: {
|
||
back: 7.2, // u behind the ship (along −tan, measured in s)
|
||
up: 1.4, // u along the frame normal — ship sits low-centre
|
||
lookAhead: 16, // u ahead of the ship for the look target
|
||
discLag: 8.0, // /s spring on the camera's own disc offset
|
||
discFollow: 0.82, // camera tracks only 82% of the ship's offset, so hard dodges
|
||
// visibly move the ship within the frame instead of gluing it
|
||
aimInfluence: 0.35, // how much the look target drifts toward the reticle
|
||
fov: 75, // matches boot.js's camera so wiring in changes nothing
|
||
fovRate: 4.5, // /s toward target fov
|
||
},
|
||
|
||
// --- durability (GDD: regenerating mucus coat over a pickup-only hull) -------------
|
||
coat: {
|
||
max: 100,
|
||
regen: 8, // /s
|
||
regenDelay: 2.5, // s after the last damage before regen resumes
|
||
// ambient drain is the biome's: world.biomeAt(s).coatDrain (esophagus = 0.5/s)
|
||
},
|
||
hull: { max: 100 },
|
||
|
||
// --- wall contact: arcade. Shove + graze damage, NEVER a hard stop -----------------
|
||
wall: {
|
||
restitution: 0.35, // fraction of inward velocity returned on contact
|
||
grazeFloor: 3.0, // impact u/s below this is free — you can lean on the wall
|
||
damagePerSpeed: 1.6, // coat damage per u/s of impact above grazeFloor
|
||
maxHit: 28, // cap: a full-speed slam is a mistake, not a death
|
||
shoveOut: 1.0, // extra u/s pushed off the wall
|
||
cooldown: 0.25, // s between wall damage ticks (scraping ≠ machine-gun damage)
|
||
},
|
||
};
|