feat: polish nightdrive road sun and signage

This commit is contained in:
2026-09-03 00:29:26 +03:00
parent bc18bc2043
commit a03d4d8dba
44 changed files with 1208 additions and 202 deletions

View File

@@ -30,6 +30,7 @@ interface VisibleState {
targetId: SectionId;
latchedAt: number;
approachDuration: number;
departureRequested: boolean;
departStartedAt: number | null;
generation: number;
}
@@ -99,6 +100,7 @@ export function createSignController(): SignController {
targetId: input.candidateId,
latchedAt: input.now,
approachDuration: APPROACH_MS - APPROACH_REDUCTION_MS * clamp01(input.acceleration),
departureRequested: false,
departStartedAt: null,
generation,
};
@@ -111,6 +113,22 @@ export function createSignController(): SignController {
visible.departStartedAt = now;
};
const requestDeparture = (
visible: VisibleState,
current: SignSnapshot,
now: number,
): void => {
const dwellCompleteAt = visible.latchedAt
+ ANTICIPATE_MS
+ visible.approachDuration
+ DWELL_MS;
if (current.phase === 'dwell' && now < dwellCompleteAt) {
visible.departureRequested = true;
return;
}
beginDeparture(visible, now);
};
const snapshotVisible = (visible: VisibleState, now: number): SignSnapshot | null => {
if (visible.departStartedAt !== null) {
const progress = clamp01((now - visible.departStartedAt) / DEPART_MS);
@@ -180,7 +198,7 @@ export function createSignController(): SignController {
enterCooldown(input.now);
return null;
}
beginDeparture(state, input.now);
requestDeparture(state, current, input.now);
return snapshotVisible(state, input.now);
}
@@ -215,26 +233,25 @@ export function createSignController(): SignController {
enterCooldown(input.now);
return null;
}
beginDeparture(state, input.now);
requestDeparture(state, current, input.now);
return snapshotVisible(state, input.now);
}
if (input.direction < 0) {
const elapsed = input.now - state.latchedAt;
const dwellStartedAt = state.latchedAt + ANTICIPATE_MS + state.approachDuration;
if (elapsed < ANTICIPATE_MS + state.approachDuration) {
if (current.opacity <= CONCEALED_OPACITY) {
state = { kind: 'idle' };
return null;
}
if (state.departStartedAt === null && input.now >= dwellStartedAt) {
beginDeparture(state, input.now);
}
if (state.departStartedAt === null) requestDeparture(state, current, input.now);
}
if (state.departStartedAt === null) {
const dwellStartedAt = state.latchedAt + ANTICIPATE_MS + state.approachDuration;
const dwellComplete = input.now >= dwellStartedAt + DWELL_MS;
if (dwellComplete && input.activeSectionId === state.targetId) {
if (
dwellComplete
&& (state.departureRequested || input.activeSectionId === state.targetId)
) {
beginDeparture(state, input.now);
}
}