class Utils { /** * "Real" modulo (always >= 0), not remainder. */ static mod(a: number, n: number): number { return ((a % n) + n) % n; } /** * Return a random integer between min and max (upper bound is exclusive). */ static randomInt(maxOrMin: number, max?: number): number { return (max) ? maxOrMin + Math.floor(Math.random() * (max - maxOrMin)) : Math.floor(Math.random() * maxOrMin); } static randomFloat(maxOrMin: number, max?: number): number { return (max) ? maxOrMin + (Math.random() * (max - maxOrMin)) : Math.random() * maxOrMin; } /** * Clamp a val to [min, max] */ static clamp(val: number, min: number, max: number): number { 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: number) { return new Promise((resolve, reject) => { setTimeout(() => resolve(), ms); }); } /** * Compatibility with iOS' SCNAction.wait() */ static wait(duration: number, range: number = 0) { return this.delay( duration * 1_000 - range * 1_000 / 2 + this.randomInt(range * 1_000) ); } }