diff --git a/src/main.ts b/src/main.ts index 286a5c7..3da3d0b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -107,7 +107,7 @@ async function boot() { // is not until the player has actually touched something. const audio = createAudio(); input.onGesture(() => audio.resume()); - const hud = createHud(seed); + const hud = createHud(seed, DEBUG); const board = createBoard(); const driveState = createDriveState(); const areas = createAreas(model.roads, model.extent); diff --git a/src/ui/hud.ts b/src/ui/hud.ts index 1873ead..b61f846 100644 --- a/src/ui/hud.ts +++ b/src/ui/hud.ts @@ -112,13 +112,24 @@ function questLines(quest: NonNullable): string[] { ]; } -export function createHud(seed: number) { +/** + * @param debug Show the scaffolding: heat values, the district's standing, the + * road you are on, and the name of the band you are in. + * + * These exist to tune curves, and every one of them actively works against + * the thing it is measuring. Phase 3's gate is telling occupied ground from + * liberated *without being told*, and there was a line on screen naming it. + * Phase 1's gate is avoiding a road because of its history, with a numeric + * heat meter sitting underneath it. You cannot judge either while reading the + * answer, so they live behind `?debug` and the world has to speak for itself. + */ +export function createHud(seed: number, debug = false) { const el = document.getElementById('hud')!; let last = 0; return { update(speedMs: number, condition: CarCondition, now: number, model: HudModel) { - // The HUD is debug scaffolding, not the real interface — 10 Hz is plenty. + // Text at 10 Hz. Nothing here changes fast enough to want a frame each. if (now - last < 0.1) return; last = now; @@ -138,21 +149,27 @@ export function createHud(seed: number) { '', ...(model.quest ? questLines(model.quest) : ['no mission — find a base']), '', - CONTROL_WORDS[model.control], + // Which band you are in is meant to be read off the light, the fog and + // who is standing in the street. Naming it hands over the answer. + ...(debug ? [CONTROL_WORDS[model.control]] : []), ...pursuitLines(model.pursuit), ...(model.danger > 0 ? [`⚠ rounds in the air nearby (${model.danger})`] : []), '', - // Debug only. The real game signals heat through the road itself — - // see the design brief: no numeric meter ships. - `[debug] road ${ - model.heat.segmentId === null - ? 'off-route' - : `#${model.heat.segmentId} ${model.heat.onTarmac ? '(on road)' : '(alongside)'}` - }`, - `[debug] heat ${bar(model.heat.value)} ${model.heat.level ?? '—'}`, - `[debug] area ${bar(model.heat.area)}`, - '', - `seed ${seed}`, + // Heat is meant to be read off what is physically sitting in the road, + // so the meter that exists to tune it cannot also be on screen. + ...(debug + ? [ + `[debug] road ${ + model.heat.segmentId === null + ? 'off-route' + : `#${model.heat.segmentId} ${model.heat.onTarmac ? '(on road)' : '(alongside)'}` + }`, + `[debug] heat ${bar(model.heat.value)} ${model.heat.level ?? '—'}`, + `[debug] area ${bar(model.heat.area)}`, + '', + `[debug] seed ${seed}`, + ] + : []), `WASD drive · space handbrake · R respawn · X drop job at a base` + ` · M sound ${model.muted ? 'off' : 'on'}`, 'hold R to reset the campaign',