Spaces:
Running
Running
File size: 2,765 Bytes
30c32c8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
// Due to the existence of features such as interpolation and "0 FPS" being treated as "screen refresh rate",
// The VM loop logic has become much more complex
// Use setTimeout to polyfill requestAnimationFrame in Node.js environments
const _requestAnimationFrame = typeof requestAnimationFrame === 'function' ?
requestAnimationFrame :
(f => setTimeout(f, 1000 / 60));
const _cancelAnimationFrame = typeof requestAnimationFrame === 'function' ?
cancelAnimationFrame :
clearTimeout;
const animationFrameWrapper = callback => {
let id;
const handle = () => {
id = _requestAnimationFrame(handle);
callback();
};
const cancel = () => _cancelAnimationFrame(id);
id = _requestAnimationFrame(handle);
return {
cancel
};
};
class FrameLoop {
constructor (runtime) {
this.runtime = runtime;
this.running = false;
this.setFramerate(30);
this.setInterpolation(false);
this.stepCallback = this.stepCallback.bind(this);
this.interpolationCallback = this.interpolationCallback.bind(this);
this._stepInterval = null;
this._interpolationAnimation = null;
this._stepAnimation = null;
this._stepCounter = 0;
}
setFramerate (fps) {
this.framerate = fps;
this._restart();
}
setInterpolation (interpolation) {
this.interpolation = interpolation;
this._restart();
}
stepCallback () {
this.runtime._step();
}
interpolationCallback () {
this.runtime._renderInterpolatedPositions();
}
_restart () {
if (this.running) {
this.stop();
this.start();
}
}
start () {
this.running = true;
if (this.framerate === 0) {
this._stepAnimation = animationFrameWrapper(this.stepCallback);
this.runtime.currentStepTime = 1000 / 60;
} else {
// Interpolation should never be enabled when framerate === 0 as that's just redundant
if (this.interpolation) {
this._interpolationAnimation = animationFrameWrapper(this.interpolationCallback);
}
this._stepInterval = setInterval(this.stepCallback, 1000 / this.framerate);
this.runtime.currentStepTime = 1000 / this.framerate;
}
}
stop () {
this.running = false;
clearInterval(this._stepInterval);
if (this._interpolationAnimation) {
this._interpolationAnimation.cancel();
}
if (this._stepAnimation) {
this._stepAnimation.cancel();
}
this._interpolationAnimation = null;
this._stepAnimation = null;
}
}
module.exports = FrameLoop;
|