trainsim/GameLoop.ts

64 lines
1.6 KiB
TypeScript

import { Doodler } from "@bearmetal/doodler";
import { StateMachine } from "./state/machine.ts";
import { getContextItem } from "./lib/context.ts";
export class GameLoop<T> {
lastTime: number;
running: boolean;
targetFps: number;
constructor(targetFps: number = 60) {
this.lastTime = performance.now();
this.running = false;
this.targetFps = targetFps;
}
async start(state: StateMachine<T>) {
if (this.running) return;
this.running = true;
this.lastTime = performance.now();
while (this.running) {
const currentTime = performance.now();
const deltaTime = (currentTime - this.lastTime) / 1000; // Convert to seconds
this.lastTime = currentTime;
try {
// Wait for state update to complete before continuing
await state.update(deltaTime);
} catch (error) {
console.error("Error in game loop:", error);
this.stop();
break;
}
// Use setTimeout to prevent immediate loop continuation
// and allow other tasks to run
await new Promise((resolve) => setTimeout(resolve, 0));
}
}
stop() {
this.running = false;
}
}
// // Usage example:
// const gameState = {
// update: async (deltaTime) => {
// console.log(`Updating with delta time: ${deltaTime.toFixed(3)}s`);
// // Simulate some async work
// await new Promise(resolve => setTimeout(resolve, 16)); // ~60fps
// }
// };
// // Create and start the loop
// const loop = new GameLoop();
// loop.start(gameState);
// // Stop the loop after 5 seconds (example)
// setTimeout(() => {
// loop.stop();
// console.log('Loop stopped');
// }, 5000);