this.ctx = canvas.getContext("2d"); | this.ctx = canvas.getContext("2d"); | ||||
this.lastTime = null; | this.lastTime = null; | ||||
this.raf = null; | this.raf = null; | ||||
this.minFPS = 10; | |||||
this.minPhysFPS = 30; | |||||
this.minFPS = 5; | |||||
this.backgroundColor = "#87CEFA"; | this.backgroundColor = "#87CEFA"; | ||||
this.entities = []; | this.entities = []; | ||||
if (this.lastTime != null) { | if (this.lastTime != null) { | ||||
let dt = (time - this.lastTime) / 1000; | let dt = (time - this.lastTime) / 1000; | ||||
if (1 / dt > this.minFPS) { | |||||
this.physics(dt); | |||||
} else { | |||||
if (1 / dt < this.minFPS) { | |||||
console.log( | console.log( | ||||
"Too long between updates ("+dt.toFixed(2)+"s, "+ | "Too long between updates ("+dt.toFixed(2)+"s, "+ | ||||
(1 / dt).toFixed(2)+"FPS). Skipping."); | (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 nSteps = 1; | |||||
while (1 / dt < this.minPhysFPS) { | |||||
dt /= 2; | |||||
nSteps *= 2; | |||||
} | |||||
if (nSteps != 1) | |||||
console.log(nSteps); | |||||
for (let i = 0; i < nSteps; ++i) | |||||
this.physics(dt); | |||||
} | } | ||||
this.draw(); | this.draw(); |
} | } | ||||
} | } | ||||
Tile.createLine = function(width, name) { | |||||
Tile.createLine = function(width, name, x = 0, y = 0) { | |||||
if (width <= 1) { | if (width <= 1) { | ||||
return [ new Tile(0, 0, name+"-lr") ]; | |||||
return [ new Tile(x, y, name+"-lr") ]; | |||||
} else { | } else { | ||||
return [ | return [ | ||||
new Tile(0, 0, name+"-l"), | |||||
new Tile(x, y, name+"-l"), | |||||
Array.from({ length: width - 2 }, (_, i) => | Array.from({ length: width - 2 }, (_, i) => | ||||
new Tile(i + 1, 0, name)), | |||||
new Tile(width - 1, 0, name+"-r"), | |||||
new Tile(x + i + 1, y, name)), | |||||
new Tile(x + width - 1, y, name+"-r"), | |||||
]; | |||||
} | |||||
} | |||||
Tile.createBox = function(width, height, nameTop, nameMid, nameBottom) { | |||||
if (height <= 1) { | |||||
return Tile.createLine(width, nameTop); | |||||
} else if (height <= 2) { | |||||
return [ | |||||
Tile.createLine(width, nameTop), | |||||
Tile.createLine(width, nameBottom), | |||||
]; | |||||
} else { | |||||
return [ | |||||
Tile.createLine(width, nameTop), | |||||
Array.from({ length: height - 2 }, (_, i) => | |||||
Tile.createLine(width, nameMid, 0, i + 1)), | |||||
Tile.createLine(width, nameBottom, 0, height - 1), | |||||
]; | ]; | ||||
} | } | ||||
} | } |
export default { | export default { | ||||
tiles: new SpriteSheet("assets/tiles.png", 32, 32, 1) | tiles: new SpriteSheet("assets/tiles.png", 32, 32, 1) | ||||
.defineTile("ground", 0, 0) | .defineTile("ground", 0, 0) | ||||
.defineTile("ground-l", 1, 0) | |||||
.defineTile("ground-r", 2, 0) | |||||
.defineTile("ground-lr", 3, 0) | |||||
.defineTile("grass", 0, 1) | |||||
.defineTile("grass-l", 1, 1) | |||||
.defineTile("grass-r", 2, 1) | |||||
.defineTile("grass-lr", 3, 1) | |||||
.defineTile("ground-top", 0, 1) | |||||
.defineTile("ground-top-l", 1, 1) | |||||
.defineTile("ground-top-r", 2, 1) | |||||
.defineTile("ground-top-lr", 3, 1) | |||||
.defineTile("platform", 0, 2) | .defineTile("platform", 0, 2) | ||||
.defineTile("platform-l", 1, 2) | .defineTile("platform-l", 1, 2) |
import Entity from "../Entity.js"; | |||||
import Texture from "../Texture.js"; | |||||
import Tile from "../Tile.js"; | |||||
import assets from "../assets.js"; | |||||
import TPlatform from "../traits/TPlatform.js"; | |||||
import TCollider from "../traits/TCollider.js"; | |||||
import TPhysics from "../traits/TPhysics.js"; | |||||
export default class Platform extends Entity { | |||||
constructor(level, width = 5) { | |||||
super(level); | |||||
this.bounds.size.set(width, 0.5); | |||||
this.addTrait(new TCollider(this)); | |||||
this.addTrait(new TPlatform(this)); | |||||
this.addTrait(new TPhysics(this)); | |||||
this.texture = new Texture(assets.tiles, | |||||
Tile.createLine(this.bounds.size.x, "platform")); | |||||
} | |||||
draw(ctx) { | |||||
this.texture.drawAt(ctx, this.bounds.pos); | |||||
} | |||||
} |
import TPhysics from "../traits/TPhysics.js"; | import TPhysics from "../traits/TPhysics.js"; | ||||
export default class Platform extends Entity { | export default class Platform extends Entity { | ||||
constructor(level) { | |||||
constructor(level, width = 5) { | |||||
super(level); | super(level); | ||||
this.bounds.size.set(5, 0.5); | |||||
this.bounds.size.set(width, 0.5); | |||||
this.addTrait(new TCollider(this)); | this.addTrait(new TCollider(this)); | ||||
this.addTrait(new TPlatform(this)); | this.addTrait(new TPlatform(this)); | ||||
this.addTrait(new TPhysics(this)); | this.addTrait(new TPhysics(this)); | ||||
this.targetSpeed = 3; | this.targetSpeed = 3; | ||||
this.accel = 5; | this.accel = 5; | ||||
this.dir = 1; | this.dir = 1; | ||||
this.movement = 5; | |||||
this.texture = new Texture(assets.tiles, | this.texture = new Texture(assets.tiles, | ||||
Tile.createLine(this.bounds.size.x, "platform")); | Tile.createLine(this.bounds.size.x, "platform")); | ||||
init() { | init() { | ||||
this.targetTop = this.bounds.pos.y; | this.targetTop = this.bounds.pos.y; | ||||
this.targetBottom = this.targetTop + 5; | |||||
this.targetBottom = this.targetTop + this.movement; | |||||
this.t.physics.gravity = 0; | this.t.physics.gravity = 0; | ||||
this.t.physics.velocity.y = 0; | this.t.physics.velocity.y = 0; |
import Level from "./Level.js"; | import Level from "./Level.js"; | ||||
import Vec2 from "./Vec2.js"; | |||||
import Player from "./entities/Player.js"; | import Player from "./entities/Player.js"; | ||||
import Platform from "./entities/Platform.js"; | |||||
import FloatingPlatform from "./entities/FloatingPlatform.js"; | |||||
import FallingPlatform from "./entities/FallingPlatform.js"; | |||||
import structures from "./structures.js"; | import structures from "./structures.js"; | ||||
import Vec2 from "./Vec2.js"; | |||||
let canvas = document.getElementById("canvas"); | let canvas = document.getElementById("canvas"); | ||||
let level = new Level(canvas); | let level = new Level(canvas); | ||||
level.spawnEntity(new Player(level), 10, 1); | level.spawnEntity(new Player(level), 10, 1); | ||||
level.spawnEntity(new Platform(level), 16, 4); | |||||
level.spawnStructure(structures.floor(8), 4, 4); | |||||
level.spawnEntity(new FloatingPlatform(level), 16, 4); | |||||
level.spawnEntity(new FallingPlatform(level), 20, 1); | |||||
level.spawnStructure(structures.floor(8, 6), 4, 4); | |||||
level.start(); | level.start(); | ||||
import Tile from "./Tile.js"; | import Tile from "./Tile.js"; | ||||
export default { | export default { | ||||
floor: width => new Structure( | |||||
floor: (width, height = 1)=> new Structure( | |||||
[ "wall" ], | [ "wall" ], | ||||
Tile.createLine(width, "grass")), | |||||
Tile.createBox(width, height, "ground-top", "ground", "ground")), | |||||
}; | }; |