SOURCE / PINNED RELEASE
Made of little things.
Pursuit PIT
- Release
- 565f4981bdc3…
- Author-recorded commit
- 197afdbed44b…
- License
- LICENSE
- Author’s source reference
- nostr://npub12lm3rxsva8kfempyjkxupt09e02n3fezurkyadyqfejdc5e0r2kscqty6r/wss%3A%2F%2Fgit.napplet.soy%2F/n-951414e7fd7
Archive hash verified: 3b0485589942fd5c…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
// A 6-speed automatic for the patrol car: turns road speed and throttle into engine rpm.
// The engine sound and the tachometer both read from it.
const RPM_PER_MPS = [300, 330, 205, 145, 112, 90, 75]; // index 0 is reverse; 6th tops out at 160 mph
const IDLE = 800;
const REDLINE = 6200;
export class Gearbox {
gear = 1;
rpm = IDLE;
/** 0..1 engine load after shift cuts, for the sound. */
load = 0;
private shiftCut = 0;
update(speed: number, throttle: number, dt: number): void {
const v = Math.abs(speed);
if (speed < -0.5) this.gear = 0;
else if (this.gear === 0) this.gear = 1;
if (this.gear > 0) {
const at = (g: number) => IDLE + v * RPM_PER_MPS[g];
if (this.gear < 6 && at(this.gear) > (throttle > 0.5 ? 5800 : 3200)) {
this.gear++;
this.shiftCut = 0.22;
} else if (this.gear > 1 && at(this.gear) < (throttle > 0.5 ? 2600 : 1500)) {
this.gear--;
this.shiftCut = 0.12;
}
}
// Below ~2 m/s the torque converter slips, so throttle revs the engine freely.
const slip = Math.max(0, 1 - v / 4) * Math.max(0, throttle) * 2600;
const target = Math.min(REDLINE, IDLE + v * RPM_PER_MPS[this.gear] + slip);
this.shiftCut = Math.max(0, this.shiftCut - dt);
const dip = this.shiftCut > 0 ? 0.9 : 1;
this.rpm += (target * dip - this.rpm) * Math.min(1, dt * (this.shiftCut > 0 ? 14 : 7));
const wantLoad = this.shiftCut > 0 ? 0.1 : Math.max(0, throttle);
this.load += (wantLoad - this.load) * Math.min(1, dt * 10);
}
}
