@@ -6,7 +6,8 @@ export default class Level { | |||
this.ctx = canvas.getContext("2d"); | |||
this.lastTime = null; | |||
this.raf = null; | |||
this.minFPS = 10; | |||
this.minPhysFPS = 30; | |||
this.minFPS = 5; | |||
this.backgroundColor = "#87CEFA"; | |||
this.entities = []; | |||
@@ -77,12 +78,26 @@ export default class Level { | |||
if (this.lastTime != null) { | |||
let dt = (time - this.lastTime) / 1000; | |||
if (1 / dt > this.minFPS) { | |||
this.physics(dt); | |||
} else { | |||
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 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(); |
@@ -6,15 +6,33 @@ export default class Tile { | |||
} | |||
} | |||
Tile.createLine = function(width, name) { | |||
Tile.createLine = function(width, name, x = 0, y = 0) { | |||
if (width <= 1) { | |||
return [ new Tile(0, 0, name+"-lr") ]; | |||
return [ new Tile(x, y, name+"-lr") ]; | |||
} else { | |||
return [ | |||
new Tile(0, 0, name+"-l"), | |||
new Tile(x, y, name+"-l"), | |||
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), | |||
]; | |||
} | |||
} |
@@ -3,11 +3,14 @@ import SpriteSheet from "./SpriteSheet.js"; | |||
export default { | |||
tiles: new SpriteSheet("assets/tiles.png", 32, 32, 1) | |||
.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-l", 1, 2) |
@@ -0,0 +1,26 @@ | |||
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); | |||
} | |||
} |
@@ -8,10 +8,10 @@ import TCollider from "../traits/TCollider.js"; | |||
import TPhysics from "../traits/TPhysics.js"; | |||
export default class Platform extends Entity { | |||
constructor(level) { | |||
constructor(level, width = 5) { | |||
super(level); | |||
this.bounds.size.set(5, 0.5); | |||
this.bounds.size.set(width, 0.5); | |||
this.addTrait(new TCollider(this)); | |||
this.addTrait(new TPlatform(this)); | |||
this.addTrait(new TPhysics(this)); | |||
@@ -19,6 +19,7 @@ export default class Platform extends Entity { | |||
this.targetSpeed = 3; | |||
this.accel = 5; | |||
this.dir = 1; | |||
this.movement = 5; | |||
this.texture = new Texture(assets.tiles, | |||
Tile.createLine(this.bounds.size.x, "platform")); | |||
@@ -26,7 +27,7 @@ export default class Platform extends Entity { | |||
init() { | |||
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.velocity.y = 0; |
@@ -1,16 +1,19 @@ | |||
import Level from "./Level.js"; | |||
import Vec2 from "./Vec2.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 Vec2 from "./Vec2.js"; | |||
let canvas = document.getElementById("canvas"); | |||
let level = new Level(canvas); | |||
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(); | |||
@@ -2,7 +2,7 @@ import Structure from "./Structure.js"; | |||
import Tile from "./Tile.js"; | |||
export default { | |||
floor: width => new Structure( | |||
floor: (width, height = 1)=> new Structure( | |||
[ "wall" ], | |||
Tile.createLine(width, "grass")), | |||
Tile.createBox(width, height, "ground-top", "ground", "ground")), | |||
}; |