|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- 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.layerOrder = {
- platform: 0,
- player: 1,
- };
- this.layers = [];
- this.entities = [];
- this.colliders = [];
-
- this.structures = [];
-
- this.evts = [];
- }
-
- spawnEntity(ent, x, y) {
- ent.bounds.pos.set(x, y);
-
- let layerIdx = this.layerOrder[ent.layerName];
- console.log(ent.layerName, this.layerOrder, layerIdx);
- if (layerIdx == null)
- throw new Error("Unknown layer name: "+ent.layerName);
-
- if (this.layers[layerIdx] == null)
- this.layers[layerIdx] = [];
-
- this.entities.push(ent);
- this.layers[layerIdx].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();
- }
-
- physicsLayer(dt, layer) {
- layer.forEach(ent =>
- ent._update(dt));
- layer.forEach(ent =>
- ent._postUpdate(dt));
- }
-
- physics(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);
- });
- });
-
- this.layers.forEach(l => this.physicsLayer(dt, l));
- }
-
- draw() {
- this.ctx.resetTransform();
- this.ctx.beginPath();
- this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
-
- this.layers.forEach(l => l.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.");
- }
- }
- }
|