Game Clock Singleton
Clock is the deterministic game clock used by all gameplay code in place of performance.now() / Date.now(). It lives at engine/core/clock.ts and exposes a tiny surface: now(), uniqueNow(), advanceSimStep(), reset().
Surface
Clock.now(): number— current sim time in milliseconds since the lastreset(). Deterministic: same inputs produce the same output. Used for cooldowns, weapon timers, spawner schedules, visual pulses, artifact timers, flame heat buildup, and telemetry timestamps that need to align with sim state.Clock.uniqueNow(): number— sim time plus a monotonically-incrementing sub-counter (_subCounter * 0.001). Used by call sites that need a unique timestamp within the same sim step (e.g. crate IDs).Clock.advanceSimStep(): void— advances_simTimeMsby1000 / 60(≈ 16.666 ms) and resets_subCounterto 0. Called only fromloop.ts::stepSimulation(). There is noadvance(dt)— the step size is fixed.Clock.reset(): void— sets sim time and sub-counter back to 0. Called fromloop.ts::startNewGame()and frombridge.ts::sandboxResetForTestso every test run begins with an identical clock.
Units
Milliseconds, matching performance.now()’s return type so call sites can be swapped 1:1 without math changes.
Determinism contract
Sim time advances only when the sim steps. Wall-clock time (performance.now(), Date.now()) is reserved for scheduler concerns: setTimeout delays, telemetry log timestamps for human reading, render-perf diagnostics. Game state — weapons, spawners, visual pulses, artifact timers, crate IDs — reads from Clock.now() so runs are byte-identical given the same input seed.
Distinct from game.time
Clock.now() is raw sim time. game.time (simulation time scaled by timeDilation) is the time-dilated view used by some gameplay systems that want to slow or speed up in-world time. The Clock is the substrate; time-dilated game time is derived from it.
Lifecycle
| Event | Action |
|---|---|
| New game starts | Clock.reset() (from loop.ts::startNewGame) |
| Sim tick | Clock.advanceSimStep() (from loop.ts::stepSimulation) |
| Sandbox test reset | Clock.reset() (from bridge.ts::sandboxResetForTest) |