diff --git a/js/Movable.js b/js/Movable.js index 558da18..62cd10b 100644 --- a/js/Movable.js +++ b/js/Movable.js @@ -10,6 +10,7 @@ export default class Movable }; this.position = new GeometryPoint(); this.speed = speed; + this.fallSpeed = 0; } playAnimation(animation, timestamp) @@ -33,6 +34,11 @@ export default class Movable this.position.x += this.speed * delta; } + getRect() + { + return this.animations[this.currentAnimation].getRect(); + } + draw(context) { this.animations[this.currentAnimation].setFootPosition(this.position.x, this.position.y); diff --git a/js/module.js b/js/module.js index 6643323..128d987 100644 --- a/js/module.js +++ b/js/module.js @@ -1,6 +1,7 @@ import RetroSprite from "./retro/RetroSprite.js"; import Key from "./Key.js"; import MrCroc from "./MrCroc.js"; +import RetroArchitecture from "./retro/RetroArchitecture.js"; const MEDIA_READY_EVENT = 'mediaready'; const IMAGE_READY_EVENT = 'imgready'; @@ -56,6 +57,7 @@ function MainLoop(timestamp) ground.draw(context); mrCroc.draw(context); + architecture.draw(context); lastRendered = timestamp; } @@ -68,10 +70,12 @@ const FPS = 60; const FRAME_DURATION = 1000 / FPS; const GAME_SPEED = 1; +const LEVEL = '{"tileset": "graphics/tileset.png", "tiles": 1, "scale": 3, "rows": 9, "columns": 16, "matrix": [[0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0], [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0], [null, null, null, null, null, 0, 0, 0, 0, 0, null, null, null, null, null, 0], [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0], [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null], [0, 0, 0, 0, 0, null, null, null, null, null, null, null, null, null, null, null], [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null], [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null], [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null]]}'; + let lastRendered = undefined; let lastTimestamp = undefined; let context; -let ground, mrCroc; +let ground, mrCroc, architecture; let KeyLeft = new Key('ArrowLeft'); let KeyRight = new Key('ArrowRight'); @@ -94,10 +98,13 @@ let imgBackground = new Image(); imgBackground.src = 'graphics/ground.jpg'; loader.addImage(imgBackground); +let imgArch = new Image(); +imgArch.src = 'graphics/tileset.png'; +loader.addImage(imgArch); + window.addEventListener( 'imagesloaded', () => { - console.log('Loaded'); ground = new RetroSprite('graphics/ground.jpg', 4); ground.position.y = window.innerHeight - ground.getRect().height; @@ -107,9 +114,11 @@ window.addEventListener( context = canvas.getContext('2d'); + architecture = RetroArchitecture.createFromJson(LEVEL); + mrCroc = new MrCroc(); mrCroc.position.x = 100; - mrCroc.position.y = window.innerHeight - ground.getHeight(); + mrCroc.position.y = 480; ground.draw(context); window.requestAnimationFrame(MainLoop); diff --git a/js/retro/RetroAnimation.js b/js/retro/RetroAnimation.js index 5ecadd7..4f06db7 100644 --- a/js/retro/RetroAnimation.js +++ b/js/retro/RetroAnimation.js @@ -1,4 +1,5 @@ import RetroSprite from "./RetroSprite.js"; +import GeometryRect from "../geometry/GeometryRect.js"; export default class RetroAnimation extends RetroSprite { @@ -18,6 +19,10 @@ export default class RetroAnimation extends RetroSprite return this.frameWidth; } + getRect() { + return new GeometryRect(this.position.x, this.position.y, this.frameWidth, this.canvas.height); + } + setFootPosition(x, y) { this.position.x = x - this.frameWidth * 0.5; this.position.y = y - this.canvas.height; diff --git a/js/retro/RetroArchitecture.js b/js/retro/RetroArchitecture.js new file mode 100644 index 0000000..d8b9ffe --- /dev/null +++ b/js/retro/RetroArchitecture.js @@ -0,0 +1,126 @@ +import RetroSprite from "./RetroSprite.js"; +import GeometryRect from "../geometry/GeometryRect.js"; +import RetroArchitectureTile from "./RetroArchitectureTile.js"; + +export default class RetroArchitecture +{ + constructor(tilesetSprite, tiles, columns, rows) + { + this.tileset = tilesetSprite; + this.tiles = tiles; + this.rows = rows; + this.columns = columns; + this.matrix = []; + this.tileWidth = this.tileset.getWidth() / this.tiles; + this.tileHeight = this.tileset.getHeight(); + + this.init(); + } + + init() + { + for (let y = 0; y < this.rows; y++) { + this.matrix.push(Array(this.columns).fill(null)); + } + } + + hasRectCollision(rect) + { + let posX = Math.floor(rect.position.x / this.tileWidth) - 2; + let posY = Math.floor(rect.position.y / this.tileHeight) - 2; + let rangeX = parseInt( posX + rect.width / this.tileWidth) + 4; + let rangeY = parseInt(posY + rect.height / this.tileHeight) + 4; + + for (let y = Math.max(0, posY); y < rangeY; y++) { + for (let x = Math.max(0, posX); x < rangeX; x++) { + if (this.matrix[y][x] !== null) { + if (this.matrix[y][x].rect.getRectIntersection(rect) !== null) { + return true; + } + } + } + } + + return false; + } + + getTileForPosition(position) + { + let x = parseInt(position.x / this.tileWidth); + let y = parseInt(position.y / this.tileHeight); + + if (x < 0 || x >= this.columns || y < 0 || y >= this.rows) { + return null; + } + + return {x: x, y: y}; + } + + getGroundHeight(position) + { + let tilePosition = this.getTileForPosition(position); + + while (tilePosition !== null && tilePosition.y < this.rows) { + if (this.matrix[tilePosition.y][tilePosition.x] !== null) { + return tilePosition.y * this.tileHeight + } + + tilePosition.y++; + } + + return this.tileHeight * this.rows; + } + + draw(context) + { + for (let y = 0; y < this.rows; y++) { + for (let x = 0; x < this.columns; x++) { + let field = this.matrix[y][x]; + + if (field !== null) { + context.drawImage( + this.tileset.canvas, + field.tile * this.tileWidth, + 0, + this.tileWidth, + this.tileHeight, + x * this.tileWidth, + y * this.tileHeight, + this.tileWidth, + this.tileHeight + ); + } + } + } + } + + static createFromJson(json) + { + let data = JSON.parse(json); + + let tileset = new RetroSprite(data.tileset, data.scale); + + let architecture = new RetroArchitecture( + tileset, + data.tiles, + data.columns, + data.rows + ); + + for (let y = 0; y < data.rows; y++) { + for (let x = 0; x < data.columns; x++) { + if (data.matrix[y][x] !== null) { + architecture.matrix[y][x] = new RetroArchitectureTile( + data.matrix[y][x], + x * architecture.tileWidth, + y * architecture.tileHeight, + architecture.tileWidth, + architecture.tileHeight + ) + } + } + } + + return architecture; + } +} \ No newline at end of file diff --git a/js/retro/RetroArchitectureTile.js b/js/retro/RetroArchitectureTile.js new file mode 100644 index 0000000..f26a1db --- /dev/null +++ b/js/retro/RetroArchitectureTile.js @@ -0,0 +1,9 @@ +import GeometryRect from "../geometry/GeometryRect.js"; + +export default class RetroArchitectureTile +{ + constructor(tile, x, y, width, height) { + this.tile = tile; + this.rect = new GeometryRect(x, y, width, height); + } +} \ No newline at end of file