UNPKG

@spearwolf/twopoint5d

Version:

Create 2.5D realtime graphics and pixelart with WebGL and three.js

98 lines 3.03 kB
import { emit, eventize, off, on, once } from '@spearwolf/eventize'; import { OnDisplayDispose, OnDisplayRenderFrame } from '../events.js'; const OnTick = Symbol.for('twopoint5d:FixedFrameLoop.OnTick'); const OnRender = Symbol.for('twopoint5d:FixedFrameLoop.OnRender'); export class FixedFrameLoop { static { this.OnTick = OnTick; } static { this.OnRender = OnRender; } static { this.DefaultFps = 60; } static { this.DefaultMaxStepsPerFrame = 5; } #fps; #fixedDelta; #accumulator; #tickTime; #tickNo; #alpha; #disposed; get fps() { return this.#fps; } set fps(value) { if (!Number.isFinite(value) || value <= 0) return; this.#fps = value; this.#fixedDelta = 1 / value; } get fixedDelta() { return this.#fixedDelta; } get tickTime() { return this.#tickTime; } get tickNo() { return this.#tickNo; } get alpha() { return this.#alpha; } get isDisposed() { return this.#disposed; } constructor(display, options) { this.#accumulator = 0; this.#tickTime = 0; this.#tickNo = 0; this.#alpha = 0; this.#disposed = false; this.onTick = on.bind(undefined, this, OnTick); this.onRender = on.bind(undefined, this, OnRender); eventize(this); this.display = display; this.#fps = options?.fps ?? FixedFrameLoop.DefaultFps; this.#fixedDelta = 1 / this.#fps; this.maxStepsPerFrame = options?.maxStepsPerFrame ?? FixedFrameLoop.DefaultMaxStepsPerFrame; on(display, OnDisplayRenderFrame, this); once(display, OnDisplayDispose, () => this.dispose()); } [OnDisplayRenderFrame](props) { if (this.#disposed) return; this.#accumulator += props.deltaTime; let steps = 0; while (this.#accumulator >= this.#fixedDelta && steps < this.maxStepsPerFrame) { emit(this, OnTick, { fixedDelta: this.#fixedDelta, tickTime: this.#tickTime, tickNo: this.#tickNo, }); this.#accumulator -= this.#fixedDelta; this.#tickTime += this.#fixedDelta; this.#tickNo += 1; steps += 1; } if (steps >= this.maxStepsPerFrame && this.#accumulator >= this.#fixedDelta) { this.#accumulator = 0; } this.#alpha = this.#accumulator / this.#fixedDelta; emit(this, OnRender, { ...props, alpha: this.#alpha, tickTime: this.#tickTime, tickNo: this.#tickNo, }); } reset() { this.#accumulator = 0; this.#tickTime = 0; this.#tickNo = 0; this.#alpha = 0; } dispose() { if (this.#disposed) return; this.#disposed = true; off(this.display, OnDisplayRenderFrame, this); off(this); } } //# sourceMappingURL=FixedFrameLoop.js.map