class Utils { /** * "Real" modulo (always >= 0), not remainder. */ static mod(a, n) { return ((a % n) + n) % n; } /** * Return a random integer between min and max (upper bound is exclusive). */ static randomInt(maxOrMin, max) { return (max) ? maxOrMin + Math.floor(Math.random() * (max - maxOrMin)) : Math.floor(Math.random() * maxOrMin); } static randomFloat(maxOrMin, max) { return (max) ? maxOrMin + (Math.random() * (max - maxOrMin)) : Math.random() * maxOrMin; } /** * Clamp a val to [min, max] */ static clamp(val, min, max) { return Math.min(Math.max(min, val), max); } /** * Returns a promise that will resolve after the specified time * @param ms Number of ms to wait */ static delay(ms) { return new Promise((resolve, reject) => { setTimeout(() => resolve(), ms); }); } /** * Compatibility with iOS' SCNAction.wait() */ static wait(duration, range = 0) { return this.delay(duration * 1000 - range * 1000 / 2 + this.randomInt(range * 1000)); } }