this.lastTime = null; | this.lastTime = null; | ||||
this.raf = null; | this.raf = null; | ||||
this.minFPS = 10; | this.minFPS = 10; | ||||
this.backgroundColor = "#87CEFA"; | |||||
this.entities = []; | this.entities = []; | ||||
this.colliders = []; | this.colliders = []; | ||||
} | } | ||||
start() { | start() { | ||||
this.canvas.style.background = this.backgroundColor; | |||||
if (this.raf == null) { | if (this.raf == null) { | ||||
this.lastTime = null; | this.lastTime = null; | ||||
this.update(); | this.update(); |
this.ready = true; | this.ready = true; | ||||
this.waiting.forEach(f => f()); | this.waiting.forEach(f => f()); | ||||
}; | }; | ||||
this.img.onerror = err => { | |||||
console.error("Failed to load "+url+"."); | |||||
}; | |||||
} | } | ||||
whenReady(fn) { | whenReady(fn) { |
export default class Structure { | export default class Structure { | ||||
constructor(attrs, nestedArr) { | constructor(attrs, nestedArr) { | ||||
this.texture = new Texture(nestedArr); | |||||
this.texture = new Texture(assets.tiles, nestedArr); | |||||
this.attrs = { | this.attrs = { | ||||
wall: false, | wall: false, |
import assets from "./assets.js"; | import assets from "./assets.js"; | ||||
export default class Texture { | export default class Texture { | ||||
constructor(nestedArr) { | |||||
constructor(sheet, nestedArr) { | |||||
this.sheet = sheet; | |||||
this.nestedArr = nestedArr; | this.nestedArr = nestedArr; | ||||
this.can = document.createElement("canvas"); | this.can = document.createElement("canvas"); | ||||
this.ctx = this.can.getContext("2d"); | this.ctx = this.can.getContext("2d"); | ||||
this.width = 0; | this.width = 0; | ||||
this.height = 0; | this.height = 0; | ||||
assets.tiles.whenReady(() => this.init()); | |||||
this.sheet.whenReady(() => this.init()); | |||||
} | } | ||||
findWidthHeight(arr) { | findWidthHeight(arr) { | ||||
if (e instanceof Array) { | if (e instanceof Array) { | ||||
this.findWidthHeight(e); | this.findWidthHeight(e); | ||||
} else { | } else { | ||||
let right = (e.x + 1) * assets.tiles.tileWidth; | |||||
let bottom = (e.y + 1) * assets.tiles.tileHeight; | |||||
let right = (e.x + 1) * this.sheet.tileWidth; | |||||
let bottom = (e.y + 1) * this.sheet.tileHeight; | |||||
if (right > this.width) | if (right > this.width) | ||||
this.width = right; | this.width = right; | ||||
if (bottom > this.height) | if (bottom > this.height) | ||||
if (e instanceof Array) { | if (e instanceof Array) { | ||||
this.fillCanvas(e); | this.fillCanvas(e); | ||||
} else { | } else { | ||||
assets.tiles.drawTile(this.ctx, e.name, e.x, e.y); | |||||
this.sheet.drawTile(this.ctx, e.name, e.x, e.y); | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
draw(ctx, x, y) { | draw(ctx, x, y) { | ||||
ctx.drawImage(this.can, x, y, this.width, this.height); | ctx.drawImage(this.can, x, y, this.width, this.height); | ||||
} | } | ||||
drawAt(ctx, vec) { | |||||
this.draw(ctx, vec.pixelX, vec.pixelY); | |||||
} | |||||
} | } |
this.name = name; | this.name = name; | ||||
} | } | ||||
} | } | ||||
Tile.createLine = function(width, name) { | |||||
if (width <= 1) { | |||||
return [ new Tile(0, 0, name+"-lr") ]; | |||||
} else { | |||||
return [ | |||||
new Tile(0, 0, name+"-l"), | |||||
Array.from({ length: width - 2 }, (_, i) => | |||||
new Tile(i + 1, 0, name)), | |||||
new Tile(width - 1, 0, name+"-r"), | |||||
]; | |||||
} | |||||
} |
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("grass", 1, 0) | |||||
.defineTile("grass-l", 2, 0) | |||||
.defineTile("grass-r", 3, 0) | |||||
.defineTile("grass-lr", 4, 0), | |||||
.defineTile("grass", 0, 1) | |||||
.defineTile("grass-l", 1, 1) | |||||
.defineTile("grass-r", 2, 1) | |||||
.defineTile("grass-lr", 3, 1) | |||||
.defineTile("platform", 0, 2) | |||||
.defineTile("platform-l", 1, 2) | |||||
.defineTile("platform-r", 2, 2) | |||||
.defineTile("platform-lr", 3, 2), | |||||
entities: new SpriteSheet("assets/entities.png", 19, 32, 2) | |||||
.defineTile("player-head", 0, 0), | |||||
} | } |
import Entity from "../Entity.js"; | 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 TPlatform from "../traits/TPlatform.js"; | ||||
import TCollider from "../traits/TCollider.js"; | import TCollider from "../traits/TCollider.js"; | ||||
constructor(level) { | constructor(level) { | ||||
super(level); | super(level); | ||||
this.bounds.size.set(5, 1); | |||||
this.bounds.size.set(5, 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.texture = new Texture(assets.tiles, | |||||
Tile.createLine(this.bounds.size.x, "platform")); | |||||
} | } | ||||
init() { | init() { | ||||
} | } | ||||
draw(ctx) { | draw(ctx) { | ||||
this.bounds.draw(ctx); | |||||
this.texture.drawAt(ctx, this.bounds.pos); | |||||
} | } | ||||
} | } |
import Entity from "../Entity.js"; | import Entity from "../Entity.js"; | ||||
import Texture from "../Texture.js"; | |||||
import Tile from "../Tile.js"; | |||||
import assets from "../assets.js"; | |||||
import TKeyboardController from "../traits/TKeyboardController.js"; | import TKeyboardController from "../traits/TKeyboardController.js"; | ||||
import TPhysics from "../traits/TPhysics.js"; | import TPhysics from "../traits/TPhysics.js"; | ||||
this.addTrait(new TCollider(this)); | this.addTrait(new TCollider(this)); | ||||
this.addTrait(new TKeyboardController(this)); | this.addTrait(new TKeyboardController(this)); | ||||
this.addTrait(new TPhysics(this)); | this.addTrait(new TPhysics(this)); | ||||
this.texture = new Texture(assets.entities, [ | |||||
new Tile(0, 0, "player-head"), | |||||
]); | |||||
} | } | ||||
draw(ctx) { | draw(ctx) { | ||||
this.bounds.draw(ctx); | |||||
this.texture.draw(ctx, | |||||
this.bounds.pos.pixelX - assets.entities.scale * 1.5, | |||||
this.bounds.pos.pixelY); | |||||
} | } | ||||
} | } |
import Structure from "./Structure.js"; | import Structure from "./Structure.js"; | ||||
import tiles from "./tiles.js"; | |||||
import Tile from "./Tile.js"; | |||||
export default { | export default { | ||||
floor: width => new Structure( | floor: width => new Structure( | ||||
[ "wall" ], | [ "wall" ], | ||||
tiles.fromLine(width, "grass")), | |||||
Tile.createLine(width, "grass")), | |||||
}; | }; |
import Tile from "./Tile.js" | |||||
export default { | |||||
fromLine: function(width, name) { | |||||
if (width <= 1) { | |||||
return [ new Tile(0, 0, name+"-lr") ]; | |||||
} else { | |||||
return [ | |||||
new Tile(0, 0, name+"-l"), | |||||
Array.from({ length: width - 2 }, (_, i) => | |||||
new Tile(i + 1, 0, name)), | |||||
new Tile(width - 1, 0, name+"-r"), | |||||
]; | |||||
} | |||||
}, | |||||
} |
this.jump = 8; | this.jump = 8; | ||||
this.jumpTimeMax = 0.4; | this.jumpTimeMax = 0.4; | ||||
this.updrift = 100; | this.updrift = 100; | ||||
this.jumpLeeway = 0.4; | |||||
this.jumpLeeway = 0.2; | |||||
this.map = { | this.map = { | ||||
KeyA: 'left', | KeyA: 'left', | ||||
phys.velocity.x += speed * dt; | phys.velocity.x += speed * dt; | ||||
let canJump = | let canJump = | ||||
!this.jumped && onGround && | |||||
!this.jumped && | |||||
this.entity.time -phys.timeLastOnGround < this.jumpLeeway; | this.entity.time -phys.timeLastOnGround < this.jumpLeeway; | ||||
if (this.pressed.jump && canJump) { | if (this.pressed.jump && canJump) { |