| @@ -7,6 +7,7 @@ export default class Level { | |||
| this.lastTime = null; | |||
| this.raf = null; | |||
| this.minFPS = 10; | |||
| this.backgroundColor = "#87CEFA"; | |||
| this.entities = []; | |||
| this.colliders = []; | |||
| @@ -92,6 +93,7 @@ export default class Level { | |||
| } | |||
| start() { | |||
| this.canvas.style.background = this.backgroundColor; | |||
| if (this.raf == null) { | |||
| this.lastTime = null; | |||
| this.update(); | |||
| @@ -16,6 +16,9 @@ export default class SpriteSheet { | |||
| this.ready = true; | |||
| this.waiting.forEach(f => f()); | |||
| }; | |||
| this.img.onerror = err => { | |||
| console.error("Failed to load "+url+"."); | |||
| }; | |||
| } | |||
| whenReady(fn) { | |||
| @@ -99,7 +99,7 @@ function flattened(arr, newArr = []) { | |||
| export default class Structure { | |||
| constructor(attrs, nestedArr) { | |||
| this.texture = new Texture(nestedArr); | |||
| this.texture = new Texture(assets.tiles, nestedArr); | |||
| this.attrs = { | |||
| wall: false, | |||
| @@ -2,14 +2,15 @@ import Rect from "./Rect.js"; | |||
| import assets from "./assets.js"; | |||
| export default class Texture { | |||
| constructor(nestedArr) { | |||
| constructor(sheet, nestedArr) { | |||
| this.sheet = sheet; | |||
| this.nestedArr = nestedArr; | |||
| this.can = document.createElement("canvas"); | |||
| this.ctx = this.can.getContext("2d"); | |||
| this.width = 0; | |||
| this.height = 0; | |||
| assets.tiles.whenReady(() => this.init()); | |||
| this.sheet.whenReady(() => this.init()); | |||
| } | |||
| findWidthHeight(arr) { | |||
| @@ -17,8 +18,8 @@ export default class Texture { | |||
| if (e instanceof Array) { | |||
| this.findWidthHeight(e); | |||
| } 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) | |||
| this.width = right; | |||
| if (bottom > this.height) | |||
| @@ -32,7 +33,7 @@ export default class Texture { | |||
| if (e instanceof Array) { | |||
| this.fillCanvas(e); | |||
| } else { | |||
| assets.tiles.drawTile(this.ctx, e.name, e.x, e.y); | |||
| this.sheet.drawTile(this.ctx, e.name, e.x, e.y); | |||
| } | |||
| }); | |||
| } | |||
| @@ -47,4 +48,8 @@ export default class Texture { | |||
| draw(ctx, x, y) { | |||
| ctx.drawImage(this.can, x, y, this.width, this.height); | |||
| } | |||
| drawAt(ctx, vec) { | |||
| this.draw(ctx, vec.pixelX, vec.pixelY); | |||
| } | |||
| } | |||
| @@ -5,3 +5,16 @@ export default class Tile { | |||
| 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"), | |||
| ]; | |||
| } | |||
| } | |||
| @@ -3,8 +3,17 @@ import SpriteSheet from "./SpriteSheet.js"; | |||
| export default { | |||
| tiles: new SpriteSheet("assets/tiles.png", 32, 32, 1) | |||
| .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), | |||
| } | |||
| @@ -1,4 +1,7 @@ | |||
| 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"; | |||
| @@ -8,7 +11,7 @@ export default class Platform extends Entity { | |||
| constructor(level) { | |||
| super(level); | |||
| this.bounds.size.set(5, 1); | |||
| this.bounds.size.set(5, 0.5); | |||
| this.addTrait(new TCollider(this)); | |||
| this.addTrait(new TPlatform(this)); | |||
| this.addTrait(new TPhysics(this)); | |||
| @@ -16,6 +19,9 @@ export default class Platform extends Entity { | |||
| this.targetSpeed = 3; | |||
| this.accel = 5; | |||
| this.dir = 1; | |||
| this.texture = new Texture(assets.tiles, | |||
| Tile.createLine(this.bounds.size.x, "platform")); | |||
| } | |||
| init() { | |||
| @@ -44,6 +50,6 @@ export default class Platform extends Entity { | |||
| } | |||
| draw(ctx) { | |||
| this.bounds.draw(ctx); | |||
| this.texture.drawAt(ctx, this.bounds.pos); | |||
| } | |||
| } | |||
| @@ -1,4 +1,7 @@ | |||
| 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 TPhysics from "../traits/TPhysics.js"; | |||
| @@ -12,9 +15,15 @@ export default class Player extends Entity { | |||
| this.addTrait(new TCollider(this)); | |||
| this.addTrait(new TKeyboardController(this)); | |||
| this.addTrait(new TPhysics(this)); | |||
| this.texture = new Texture(assets.entities, [ | |||
| new Tile(0, 0, "player-head"), | |||
| ]); | |||
| } | |||
| draw(ctx) { | |||
| this.bounds.draw(ctx); | |||
| this.texture.draw(ctx, | |||
| this.bounds.pos.pixelX - assets.entities.scale * 1.5, | |||
| this.bounds.pos.pixelY); | |||
| } | |||
| } | |||
| @@ -1,8 +1,8 @@ | |||
| import Structure from "./Structure.js"; | |||
| import tiles from "./tiles.js"; | |||
| import Tile from "./Tile.js"; | |||
| export default { | |||
| floor: width => new Structure( | |||
| [ "wall" ], | |||
| tiles.fromLine(width, "grass")), | |||
| Tile.createLine(width, "grass")), | |||
| }; | |||
| @@ -1,16 +0,0 @@ | |||
| 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"), | |||
| ]; | |||
| } | |||
| }, | |||
| } | |||
| @@ -10,7 +10,7 @@ export default class TKeyboardController extends Trait { | |||
| this.jump = 8; | |||
| this.jumpTimeMax = 0.4; | |||
| this.updrift = 100; | |||
| this.jumpLeeway = 0.4; | |||
| this.jumpLeeway = 0.2; | |||
| this.map = { | |||
| KeyA: 'left', | |||
| @@ -49,7 +49,7 @@ export default class TKeyboardController extends Trait { | |||
| phys.velocity.x += speed * dt; | |||
| let canJump = | |||
| !this.jumped && onGround && | |||
| !this.jumped && | |||
| this.entity.time -phys.timeLastOnGround < this.jumpLeeway; | |||
| if (this.pressed.jump && canJump) { | |||