fuzzyworld

herd / files / src / game / GameLoop.ts

GameLoop.ts

Blame: the commit that last changed each line · file · history

1001e9ef 2026-05-17 Pavel Safronov1const FIXED_STEP_MS = 16 // ~60 Hz physics
2
3export class GameLoop {
4 private rafId = 0
5 private lastTime = 0
6 private accumulator = 0
7 private running = false
8 private onUpdate: (dt: number) => void
9 private onRender: (alpha: number) => void
10
11 constructor(onUpdate: (dt: number) => void, onRender: (alpha: number) => void) {
12 this.onUpdate = onUpdate
13 this.onRender = onRender
14 }
15
16 start() {
17 if (this.running) return
18 this.running = true
19 this.lastTime = performance.now()
20 this.rafId = requestAnimationFrame(this.tick)
21 }
22
23 stop() {
24 this.running = false
25 cancelAnimationFrame(this.rafId)
26 }
27
28 private tick = (now: number) => {
29 if (!this.running) return
30 this.rafId = requestAnimationFrame(this.tick)
31
32 const elapsed = Math.min(now - this.lastTime, 200) // cap at 200ms to avoid spiral of death
33 this.lastTime = now
34 this.accumulator += elapsed
35
36 while (this.accumulator >= FIXED_STEP_MS) {
37 this.onUpdate(FIXED_STEP_MS / 1000) // pass seconds
38 this.accumulator -= FIXED_STEP_MS
39 }
40
41 this.onRender(this.accumulator / FIXED_STEP_MS)
42 }
43}