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
JavaScript
"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;