feat: engine off at the destination

On arrival the drive winds down to a stop, the tail and running lamps
drop to parking level, the sky darkens about 10% with more stars and
the grid fades. The engine and road noise take a 1.2 s low-pass sweep
to idle. The letterbox stays within 8vh and the closing credit types
into the lower bar; reduced motion keeps only the bars and dimming.
This commit is contained in:
2026-10-10 23:37:51 +03:00
parent 07e3ea014d
commit f08dfc3fba
7 changed files with 124 additions and 34 deletions

View File

@@ -307,9 +307,17 @@ export async function createProceduralSceneGeneration(
terrainSpectrumPhase =
(terrainSpectrumPhase + deltaSeconds * overdrive * 0.38) % 1;
writeChapterPalette(targetPalette, snapshot.chapter, snapshot.chapter, 0);
// Engine off: parked at the destination the sky drops about 10%, more
// stars come out, and the drive winds down to a stop.
const engineOff = THREE.MathUtils.smoothstep(outroProgress, 0.12, 0.7);
if (engineOff > 0) {
targetPalette.sky.lerp(ENGINE_OFF_NIGHT, 0.1 * engineOff);
targetPalette.fog.lerp(ENGINE_OFF_NIGHT, 0.1 * engineOff);
targetPalette.starVisibility *= 1 + 0.8 * engineOff;
}
dampPalette(currentPalette, targetPalette, deltaSeconds);
const driveDistance = travelDistance.advance(
deltaSeconds,
deltaSeconds * (1 - engineOff),
snapshot.driveSpeed,
response.roadEnergy,
);
@@ -317,7 +325,7 @@ export async function createProceduralSceneGeneration(
0.18 + response.roadEnergy * 0.82,
0.18,
1,
);
) * (1 - engineOff);
road.update(
driveDistance,
visualSpeed,
@@ -347,6 +355,7 @@ export async function createProceduralSceneGeneration(
overdrive,
terrainSurge,
terrainSpectrumPhase,
engineOff,
);
atmosphericTime += deltaSeconds;
const elapsedSeconds = atmosphericTime;
@@ -354,7 +363,7 @@ export async function createProceduralSceneGeneration(
skyline.update(currentPalette, elapsedSeconds);
traffic.update(
deltaSeconds,
18 + snapshot.driveSpeed * 54 + response.roadEnergy * 48,
(18 + snapshot.driveSpeed * 54 + response.roadEnergy * 48) * (1 - engineOff),
elapsedSeconds,
);
sun.update(
@@ -369,6 +378,7 @@ export async function createProceduralSceneGeneration(
response.suspensionEnergy,
elapsedSeconds,
driveDistance,
engineOff,
);
speedWake.update(
overdrive,
@@ -634,6 +644,7 @@ const INTRO_SECONDS = 4.2;
const OUTRO_SECONDS = 5.5;
const OUTRO_RETURN_SECONDS = 1.6;
const OUTRO_REACH = 0.62;
const ENGINE_OFF_NIGHT = new THREE.Color(0x000000);
/** Plates rise back over 720 ms with up to three 90 ms staggers. */
const INTERLUDE_RISE_MS = 1100;