Phase 0: drivable car with persistent wear
Vite + TypeScript + three.js + Rapier raycast vehicle, fixed 60 Hz step. Flat plate, seeded obstacle scatter, chase camera, debug HUD. Car condition (engine/tires/chassis) degrades permanently and is derived into handling numbers, so decline is felt through the wheel rather than read off a meter. src/sim/ is kept free of three.js and Rapier imports — the later heat, region and front-line systems all live there, and staying engine-free is what makes them unit-testable without a browser. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import type { CarCondition } from '../sim/car';
|
||||
|
||||
const BAR_WIDTH = 12;
|
||||
|
||||
function bar(value: number): string {
|
||||
const filled = Math.round(value * BAR_WIDTH);
|
||||
return '█'.repeat(filled) + '·'.repeat(BAR_WIDTH - filled);
|
||||
}
|
||||
|
||||
export function createHud(seed: number) {
|
||||
const el = document.getElementById('hud')!;
|
||||
let last = 0;
|
||||
|
||||
return {
|
||||
update(speedMs: number, condition: CarCondition, now: number) {
|
||||
// The HUD is debug scaffolding, not the real interface — 10 Hz is plenty.
|
||||
if (now - last < 0.1) return;
|
||||
last = now;
|
||||
el.textContent = [
|
||||
`${Math.abs(speedMs * 3.6).toFixed(0).padStart(3)} km/h`,
|
||||
'',
|
||||
`engine ${bar(condition.engine)} ${(condition.engine * 100).toFixed(0)}%`,
|
||||
`tires ${bar(condition.tires)} ${(condition.tires * 100).toFixed(0)}%`,
|
||||
`chassis ${bar(condition.chassis)} ${(condition.chassis * 100).toFixed(0)}%`,
|
||||
'',
|
||||
`seed ${seed}`,
|
||||
'WASD drive · space handbrake · R respawn',
|
||||
].join('\n');
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user