2d-physics-engine
Version:
A lightweight, flexible 2D physics engine with ECS architecture, built with TypeScript
140 lines • 4.63 kB
JavaScript
import { Physics } from '../systems/PhysicsSystem/Physics.system';
import { Rendering } from '../systems/Rendering.system';
export class Iterator {
constructor(inputManager, canvas, canvasCtx, config) {
Object.defineProperty(this, "inputManager", {
enumerable: true,
configurable: true,
writable: true,
value: inputManager
});
Object.defineProperty(this, "fixedTimeStep", {
enumerable: true,
configurable: true,
writable: true,
value: 1 / 60
}); // 60 FPS physics
Object.defineProperty(this, "maxDeltaTime", {
enumerable: true,
configurable: true,
writable: true,
value: 0.1
});
Object.defineProperty(this, "debug", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "systems", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
Object.defineProperty(this, "scene", {
enumerable: true,
configurable: true,
writable: true,
value: null
});
Object.defineProperty(this, "lastFrameTime", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "isRunning", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "accumulator", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
if (!canvas || !canvasCtx) {
throw new Error('Canvas and canvas-context are required for engine initialization.');
}
this.fixedTimeStep = config?.fixedTimeStep ?? this.fixedTimeStep;
this.maxDeltaTime = config?.maxDeltaTime ?? this.maxDeltaTime;
this.debug = config?.debug ?? this.debug;
// Initialize systems
this.systems.push(new Rendering(canvas, canvasCtx), new Physics());
this.loop = this.loop.bind(this);
}
setScene(scene) {
if (this.scene) {
this.scene.onUnload();
}
this.scene = scene;
scene.onLoad();
}
addSystem(system) {
this.systems.push(system);
}
start() {
if (!this.isRunning) {
this.isRunning = true;
this.lastFrameTime = performance.now();
this.accumulator = 0;
requestAnimationFrame(this.loop);
}
}
stop() {
this.isRunning = false;
}
loop(currentTime) {
if (!this.isRunning)
return;
// Clamps the delta time to maxDeltaTime in seconds to prevent large jumps if the game lags
const deltaTime = Math.min((currentTime - this.lastFrameTime) / 1000, this.maxDeltaTime);
this.lastFrameTime = currentTime;
if (this.debug) {
this.logDebugInfo(deltaTime);
}
// Fixed timestep updates for physics
this.accumulator += deltaTime;
while (this.accumulator >= this.fixedTimeStep) {
this.fixedUpdate(this.fixedTimeStep);
this.accumulator -= this.fixedTimeStep;
}
// Variable timestep updates for everything else
this.update(deltaTime);
requestAnimationFrame(this.loop);
}
logDebugInfo(deltaTime) {
// TODO: print log info on canvas instead of console
console.log({
fps: Math.round(1 / deltaTime),
deltaTime: deltaTime.toFixed(4),
entities: this.scene?.getEntities().length ?? 0,
accumulator: this.accumulator.toFixed(4),
});
}
fixedUpdate(fixedDeltaTime) {
if (this.scene) {
for (const system of this.systems) {
if (system.needsFixedUpdate) {
system.update(fixedDeltaTime, this.scene);
}
}
}
}
update(deltaTime) {
this.inputManager.update();
if (this.scene) {
// Update systems that don't need fixed timestep
for (const system of this.systems) {
if (!system.needsFixedUpdate) {
system.update(deltaTime, this.scene);
}
}
this.scene.update(deltaTime);
}
}
}
//# sourceMappingURL=Iterator.js.map