import structures from "./structures.js"; export default class Level { constructor(canvas) { this.canvas = canvas; this.ctx = canvas.getContext("2d"); this.lastTime = null; this.raf = null; this.minPhysFPS = 20; this.minFPS = 5; this.backgroundColor = "#87CEFA"; this.entities = []; this.colliders = []; this.structures = []; this.evts = []; } spawnEntity(ent, x, y) { ent.bounds.pos.set(x, y); this.entities.push(ent); if (ent.has("collider")) this.colliders.push(ent); ent._init(); } spawnStructure(structure, x, y) { structure.bounds.pos.set(x, y); this.structures.push(structure); structure.init(); } physics(dt) { this.entities.forEach(ent => ent._update(dt)); this.entities.forEach(ent => ent._postUpdate(dt)); // Collide with structures this.structures.forEach(s => { if (!s.attrs.wall && !s.attrs.platform) return; this.colliders.forEach(ent => { let bounds = s.collidesWith(ent.bounds); if (!bounds) return; ent.t.collider.collideStructure(s, bounds); }); }); // Collide with entities this.colliders.forEach(ent => { this.colliders.forEach(ent2 => { if (ent === ent2 || !ent.bounds.intersects(ent2.bounds)) return; ent.t.collider.collideEntity(ent2); }); }); } draw() { this.ctx.resetTransform(); this.ctx.beginPath(); this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); this.entities.forEach(ent => ent.draw(this.ctx)); this.structures.forEach(struct => struct.draw(this.ctx)); } update(time) { if (this.lastTime != null) { let dt = (time - this.lastTime) / 1000; if (1 / dt < this.minFPS) { console.log( "Too long between updates ("+dt.toFixed(2)+"s, "+ (1 / dt).toFixed(2)+"FPS). Skipping."); } else { // We accept really low FPSes, // but if the FPS gets too low, we want to run multiple // physics steps in the frame. let physdt = dt; let nSteps = 1; while (1 / physdt < this.minPhysFPS) { physdt /= 2; nSteps *= 2; } if (nSteps > 1) { console.log( "Too long between frames for physics ("+dt.toFixed(2)+"s). "+ "Running "+nSteps+" simulations ("+physdt.toFixed(2)+"s) in one frame."); } for (let i = 0; i < nSteps; ++i) this.physics(physdt); } this.draw(); } this.lastTime = time; this.raf = requestAnimationFrame(this.update.bind(this)); } start() { this.canvas.style.background = this.backgroundColor; if (this.raf == null) { this.lastTime = null; this.update(); console.log("Started."); } } stop() { if (this.raf != null) { cancelAnimationFrame(this.raf); this.raf = null; console.log("Stopped."); } } }