UNPKG

typed-loop

Version:

A loop class to enable flexible intervals for visual experiments and games. It provides delta time in various formats and uses `requestAnimationFrame` for the timeouts. It's possible to use `setTimeout` with given `targetDeltaTime`.

86 lines (85 loc) 3.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var TimeoutFunction; (function (TimeoutFunction) { TimeoutFunction["REQUEST_ANIMATION_FRAME"] = "requestAnimationFrame"; TimeoutFunction["SET_TIMEOUT"] = "setTimeout"; })(TimeoutFunction || (TimeoutFunction = {})); var DeltaTimeFormat; (function (DeltaTimeFormat) { DeltaTimeFormat["RELATIVE"] = "relative"; DeltaTimeFormat["MILLISECONDS"] = "milliseconds"; DeltaTimeFormat["SECONDS"] = "seconds"; })(DeltaTimeFormat = exports.DeltaTimeFormat || (exports.DeltaTimeFormat = {})); var Loop = /** @class */ (function () { function Loop(_a) { var onTick = _a.onTick, deltaTimeLimit = _a.deltaTimeLimit, targetTimeout = _a.targetTimeout, _b = _a.deltaTimeFormat, deltaTimeFormat = _b === void 0 ? DeltaTimeFormat.MILLISECONDS : _b, _c = _a.startWithoutDelay, startWithoutDelay = _c === void 0 ? false : _c; this.onTick = onTick; this.deltaTimeLimit = deltaTimeLimit; this.targetTimeout = targetTimeout; this.timeoutFunction = targetTimeout !== undefined ? TimeoutFunction.SET_TIMEOUT : TimeoutFunction.REQUEST_ANIMATION_FRAME; this.startWithoutDelay = startWithoutDelay; this.deltaTimeFormat = deltaTimeFormat; this.lastTickTime = 0; this.timeoutId = 0; this.active = false; this.tick = this.tick.bind(this); // to enable method reference passing directly to timeout functions } Loop.prototype.start = function () { if (this.active) return this; this.active = true; if (this.startWithoutDelay) { this.onTick(Loop.estimatedDeltaTimeMs); this.scheduleNextTick(Date.now() - Loop.estimatedDeltaTimeMs); } else { this.scheduleNextTick(); } return this; }; Loop.prototype.stop = function () { this.active = false; if (this.timeoutFunction === TimeoutFunction.REQUEST_ANIMATION_FRAME) { cancelAnimationFrame(this.timeoutId); } else { clearTimeout(this.timeoutId); } }; Loop.prototype.tick = function () { if (!this.active) return; var now = Date.now(); var actualDeltaTimeMs = now - this.lastTickTime; var limitedDeltaTimeInMs = this.deltaTimeLimit !== undefined ? Math.min(actualDeltaTimeMs, this.deltaTimeLimit) : actualDeltaTimeMs; var formattedDeltaTime = this.getFormattedDeltaTime(limitedDeltaTimeInMs); this.onTick(formattedDeltaTime); this.scheduleNextTick(now); }; Loop.prototype.getFormattedDeltaTime = function (deltaTimeInMs) { var _a; switch (this.deltaTimeFormat) { case DeltaTimeFormat.RELATIVE: return deltaTimeInMs / ((_a = this.targetTimeout) !== null && _a !== void 0 ? _a : Loop.estimatedDeltaTimeMs); case DeltaTimeFormat.SECONDS: return deltaTimeInMs * 0.001; default: return deltaTimeInMs; } }; Loop.prototype.scheduleNextTick = function (currentTime) { if (currentTime === void 0) { currentTime = Date.now(); } this.lastTickTime = currentTime; if (this.timeoutFunction === TimeoutFunction.SET_TIMEOUT) { this.timeoutId = setTimeout(this.tick, this.targetTimeout); } else { this.timeoutId = requestAnimationFrame(this.tick); } }; Loop.estimatedDeltaTimeMs = 16; return Loop; }()); exports.Loop = Loop;