import { formatError, formatErrorMessage } from "./errors"; import Input from "./input"; import { nextFrame } from "./utils"; type Setup = () => Promise | T; type Frame = (dt: number, state: T) => Promise | T | void; type GameMain = () => void; export function gameLoop(frame: Frame): GameMain; export function gameLoop(setup: Setup, frame: Frame): GameMain; export function gameLoop(setupOrFrame: Setup | Frame, frame?: Frame): GameMain { return async () => { let state: T; try { if (frame) { state = await (setupOrFrame as Setup)(); } else { frame = setupOrFrame as Frame; state = {} as T; } } catch (e) { console.error(formatError(e, 'Error in game setup')); alert(formatErrorMessage(e)); return; } try { let prevFrame = performance.now(); while (true) { await nextFrame(); Input.updateKeys(); const now = performance.now(); const dt = (now - prevFrame) / 1000; if (dt < 1) { const newState = await frame(dt, state); if (newState) { state = newState; } } prevFrame = performance.now(); } } catch (e) { console.error(formatError(e, 'Error in game loop')); alert(formatErrorMessage(e)); return; } } };