timing/PreciseLoop.js

import NanoTimer from "nanotimer";

class PreciseLoop {
    /**
     * A `nanotimer` based game loop, cb is called tps times (ticks per second)
     * 
     * > **Beware** This is a more accurate version of [Loop](#Loop) which uses `setImmediate` polling under the hoop, if used with delays under 25ms it can be very cpu intensive because it is executed as fast as possible
     * @see https://www.npmjs.com/package/nanotimer#performance
     * @param {Function} cb 
     * @param {Number} tps 
     * @param {Boolean} autostart 
     */
    constructor(cb, tps, autostart = true) {
        this.cb = cb;

        this.tps = tps;
        this.target_ms = Math.floor(1000 / tps);

        /**
         * ms timestamp of the last time
         */
        this.lasttick = null;

        this.timer = new NanoTimer();
        this.running = false;

        if (autostart) this.start();
    }

    /**
     * start the loop
     */
    start() {
        if (!this.running) {
            this.timer.setInterval(() => {
                this.tick();
            }, '', this.target_ms + "m");
            this.running = true;
        }
    }

    /**
     * stop the loop
     */
    stop() {
        if (this.running) {
            this.timer.clearInterval();
            this.running = false;
        }
    }

    tick() {
        this.cb(this.target_ms);
        this.lasttick = Date.now();
    }
}

export default PreciseLoop