SOURCE / PINNED RELEASE
Made of little things.
Supersonic RC Revive
- Release
- 1ba42f1ca1d6…
- Author-recorded commit
- baecad10b1cd…
- License
- LICENSE
- Author’s source reference
- nostr://npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr/wss%3A%2F%2Fgit.napplet.soy%2F/n-143146b0d6f
Archive hash verified: 90d22b206672eba4…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
// Port of "ParentScript 22 - carsound" plus car.collision's crash sounds.
import type { Input } from '../input.js';
import type { SoundMixer } from '../audio.js';
import type { Car } from './car.js';
const random = (n: number) => 1 + Math.floor(Math.random() * n);
export class CarSound {
private readonly musicLoops = ['musicloop1', 'musicloop2', 'musicloop3', 'musicloop4', 'musicloop5'];
private pPlaying = 0;
private pShift = 1;
private pStopped = 0;
private pState: 'left' | 'right' | 'middle' = 'middle';
private readonly crashUp = ['crash1', 'Crash2', 'crash3', 'crash4', 'crash5', 'crash6', 'crash7', 'crash8'];
private readonly crashDown = ['Crash1_glass', 'Crash2_glass', 'Crash3_glass'];
constructor(
private readonly car: Car,
private readonly input: Input,
private readonly mixer: SoundMixer,
private readonly firstChannel = 1,
private readonly ownsMusic = true,
) {
mixer.sound(firstChannel).volume = 25;
mixer.sound(firstChannel + 1).volume = 20;
if (ownsMusic) {
const music = mixer.sound(8);
music.stop();
music.play({ member: this.musicLoops[random(5) - 1] });
music.fadeTo(75, 500);
}
car.events.crash = (upright) => this.crash(upright);
}
/** car.collision: one-shot on channel 3 unless one is still playing; lists rotate. */
private crash(upright: boolean): void {
const ch = this.mixer.sound(this.firstChannel + 2);
if (ch.current) return;
const list = upright ? this.crashUp : this.crashDown;
const member = list.shift()!;
list.push(member);
ch.play({ member });
ch.volume = 125;
}
/** Per chunk, from car.update. */
update(): void {
const s = (n: number) => this.mixer.sound(n === 8 ? 8 : this.firstChannel + n - 1);
if (this.ownsMusic && s(8).playlistCount() < 3 && !this.pStopped) s(8).queue({ member: this.musicLoops[random(5) - 1] });
let throttle = false;
let left = false;
let right = false;
if (!this.pStopped) {
throttle = this.input.keyPressed(126) || this.input.keyPressed(125);
// A controller stick leaning past halfway turns like an arrow key.
left = this.input.keyPressed(123) || this.input.steerAxis() <= -0.5;
right = this.input.keyPressed(124) || this.input.steerAxis() >= 0.5;
}
if (throttle && !this.pPlaying) {
const tStart = this.car.rb.linearVelocity.length() * 4 - 150;
s(1).play({ member: 'CarStart', rateShift: this.pShift, startTime: Math.max(0, tStart) });
s(1).queue({ member: 'CarLoop', loopCount: 0, rateShift: this.pShift });
this.pPlaying = 1;
} else if (this.pPlaying && !throttle) {
if (s(1).current === 'carstart') {
s(1).play({ member: 'carend', startTime: Math.max(0, this.mixer.duration('carend') - s(1).currentTime / 2 - 10) });
} else {
s(1).play({ member: 'CarEnd' });
}
this.pPlaying = 0;
}
if (left && this.pState !== 'left') {
s(2).play({ member: `carturnleft0${random(3)}` });
this.pState = 'left';
} else if (right && this.pState !== 'right') {
s(2).play({ member: `carturnright0${random(3)}` });
this.pState = 'right';
}
if (!right && !left && this.pState !== 'middle') {
s(2).play({ member: this.pState === 'left' ? `carturnright0${random(3)}` : `carturnleft0${random(3)}` });
this.pState = 'middle';
}
const w = this.car.wheels;
let tShift = 2 - (w[0].pOnGround + w[1].pOnGround) * 0.5 + 0.1;
if (this.car.pReversing) tShift = 0.2;
if (this.pShift !== tShift && this.pPlaying) s(1).play({ member: 'carloop', loopCount: 0, rateShift: tShift });
this.pShift = tShift;
}
stopDriving(): void {
this.pStopped = 1;
if (this.ownsMusic) this.mixer.sound(8).fadeOut(500);
}
destroy(): void {
this.mixer.sound(this.firstChannel).stop();
this.mixer.sound(this.firstChannel + 1).stop();
this.mixer.sound(this.firstChannel + 2).stop();
}
}
