/** * Centralised time manager. Game-logic should read deltas from here instead * of consuming raw `dt` from Cocos Creator components so that a single * `pause()` call freezes gameplay without freezing UI (menu / settlement). * * Used by: * - Pause menu, settings overlay, "公主被带走" cutscene (requirement 14.1). * - Story intro cutscene (requirement 19.x) — UI time keeps ticking while * gameplay time is held at zero. * * Two independent clocks are exposed: * - `gameTime` : respects pause / time-scale, used by AI, physics, weapons. * - `realTime` : ignores pause, used by UI animation, typewriter text, and * Logger timestamps. */ export class TimeMgr { private _gameTime = 0; private _realTime = 0; private _timeScale = 1; private _paused = false; /** Should be called once per frame (e.g. from a root node's `update`). */ public update(rawDt: number): void { this._realTime += rawDt; if (this._paused) { return; } this._gameTime += rawDt * this._timeScale; } public pause(): void { this._paused = true; } public resume(): void { this._paused = false; } public get paused(): boolean { return this._paused; } /** 1.0 = normal, 0.5 = slow-mo, 0 = hard freeze. Negative values clamped. */ public setTimeScale(scale: number): void { this._timeScale = Math.max(0, scale); } public get timeScale(): number { return this._timeScale; } public get gameTime(): number { return this._gameTime; } public get realTime(): number { return this._realTime; } /** Produce the scaled dt to pass into logic `update(dt)` calls. */ public scaledDelta(rawDt: number): number { return this._paused ? 0 : rawDt * this._timeScale; } /** Reset all clocks (used between scenes and in unit tests). */ public reset(): void { this._gameTime = 0; this._realTime = 0; this._timeScale = 1; this._paused = false; } } /** Shared project-wide time manager. */ export const globalTimeMgr = new TimeMgr();