Echo / src /scene /GameClock.js
mlmihjaz's picture
Initial commit: ECHO 3D vocab game with Node+SQLite backend, admin dashboard, Docker deploy
173e683
Raw
History Blame Contribute Delete
2.24 kB
/**
* GameClock β€” continuous game-time cycle (GTA-style).
*
* gameTime: 0..1 represents the full 24-hour cycle.
* 0.00 / 1.00 β†’ midnight
* 0.22 β†’ sunrise
* 0.50 β†’ noon
* 0.78 β†’ sunset
*
* dayDurationSeconds controls how fast time passes (default 120s = 2 minutes per game day,
* a bit faster than GTA so kids see day β†’ night within one play session).
*
* Optional jumpToLevel(t01) snaps the clock to a sensible time-of-day for the current grade:
* level low β†’ bright morning
* level mid β†’ noon β†’ afternoon
* level high β†’ sunset β†’ night
* After a snap, time keeps progressing forward β€” so the BG never goes static.
*/
export class GameClock {
constructor({ dayDurationSeconds = 120, startTime = 0.30 } = {}) {
this.dayDurationSeconds = dayDurationSeconds;
this.gameTime = startTime; // 0..1
}
update(dt) {
this.gameTime = (this.gameTime + dt / this.dayDurationSeconds) % 1;
}
/**
* Jump time forward so the look matches the current level intensity.
* Only nudges forward (no rewind) so the cycle keeps marching.
*/
jumpToLevel(t01) {
// Map level intensity to a "preferred" time-of-day:
// t=0 β†’ 0.30 (mid-morning), t=0.5 β†’ 0.55 (mid-afternoon), t=1 β†’ 0.92 (deep night)
const target = 0.30 + t01 * 0.62;
// Take the shortest forward jump
let delta = target - this.gameTime;
if (delta < 0) delta += 1;
if (delta > 0.02) this.gameTime = target;
}
// 50/50 split β€” 10 minutes of day and 10 minutes of night for a 20-minute cycle.
// Sunrise is at gameTime 0.25, sunset at 0.75.
isDay() { return this.gameTime >= 0.25 && this.gameTime < 0.75; }
isNight() { return !this.isDay(); }
/** Returns 0..1 fraction of the daylight arc (only valid during day). */
dayPhase() {
if (!this.isDay()) return -1;
return (this.gameTime - 0.25) / 0.5; // 0.25..0.75 β†’ 0..1
}
/** Returns 0..1 fraction of the night arc (wraps over midnight). */
nightPhase() {
if (this.isDay()) return -1;
const t = this.gameTime >= 0.75 ? this.gameTime - 0.75 : (1 - 0.75) + this.gameTime;
return t / 0.5; // 0.75..1.25 β†’ 0..1
}
}