From f6890eec24fbf6228c65ef0466c3e8c7e4131d99 Mon Sep 17 00:00:00 2001 From: Mal Date: Sun, 9 Feb 2020 22:06:59 +0100 Subject: [PATCH] Camera implemented. --- js/Camera.js | 60 +++++++++++++++++++++++++++++++++++ js/Movable.js | 12 +++++-- js/module.js | 12 +++++-- js/retro/RetroAnimation.js | 6 ++-- js/retro/RetroArchitecture.js | 15 ++++++--- js/retro/RetroSprite.js | 4 +-- tilorswift/js/Terrain.js | 23 +++++++++++--- tilorswift/js/module.js | 7 ++-- 8 files changed, 116 insertions(+), 23 deletions(-) create mode 100644 js/Camera.js diff --git a/js/Camera.js b/js/Camera.js new file mode 100644 index 0000000..fbe692d --- /dev/null +++ b/js/Camera.js @@ -0,0 +1,60 @@ +import GeometryPoint from "./geometry/GeometryPoint.js"; + +export default class Camera +{ + constructor(x = 0, y = 0, width = window.innerWidth, height = window.innerHeight) + { + this.position = new GeometryPoint(x, y); + this.width = width; + this.height = height; + this.borderTop = 0; + this.borderBottom = undefined; + this.borderLeft = 0; + this.borderRight = undefined; + this.speedX = 0; + this.speedY = 0; + } + + centerCamera(x, y) + { + this.position.x = x - this.width * 0.5; + this.position.y = y - this.height * 0.5; + + if (this.position.x < this.borderLeft) { + this.position.x = this.borderLeft; + } else if (this.borderRight !== undefined && this.position.x + this.width > this.borderRight) { + this.position.x = this.borderRight - this.width; + } + + if (this.position.y < this.borderTop) { + this.position.y = this.borderTop; + } else if (this.borderBottom !== undefined && this.position.y + this.height > this.borderBottom) { + this.position.y = this.borderBottom - this.height; + } + } + + facePosition(x, y, delta, reactionSpeed = 1) + { + let positionX = x - this.width * 0.5; + let positionY = y - this.height * 0.5; + + let distanceX = this.position.x - positionX; + let distanceY = this.position.y - positionY; + + if (this.position.x !== positionX) { + this.position.x += distanceX * delta * reactionSpeed; + } + + if (distanceX < 0.01) { + this.position.x = positionX; + } + + if (this.position.y !== positionY) { + this.position.y += distanceY * delta * reactionSpeed; + } + + if (distanceY < 0.01) { + this.position.y = positionY; + } + } +} \ No newline at end of file diff --git a/js/Movable.js b/js/Movable.js index a145219..f8cb198 100644 --- a/js/Movable.js +++ b/js/Movable.js @@ -40,6 +40,14 @@ export default class Movable return this.animations[this.currentAnimation].getRect(); } + getCenter() + { + return new GeometryPoint( + this.position.x + this.getWidth() * 0.5, + this.position.y + this.getHeight() * 0.5 + ); + } + getWidth() { return this.getRect().width; @@ -99,9 +107,9 @@ export default class Movable this.position.y = height - this.animations[this.currentAnimation].getHeight(); } - draw(context) + draw(context, camera) { this.animations[this.currentAnimation].setFootPosition(this.position.x, this.position.y); - this.animations[this.currentAnimation].draw(context); + this.animations[this.currentAnimation].draw(context, camera); } } \ No newline at end of file diff --git a/js/module.js b/js/module.js index a6e31a3..6cbc85e 100644 --- a/js/module.js +++ b/js/module.js @@ -2,6 +2,7 @@ import Key from "./Key.js"; import MrCroc from "./MrCroc.js"; import RetroArchitecture from "./retro/RetroArchitecture.js"; import FileLoader from "./FileLoader.js"; +import Camera from "./Camera.js"; class ImageLoader { @@ -104,8 +105,10 @@ function MainLoop(timestamp) /* Drawing */ if (timestamp - lastRendered >= FRAME_DURATION) { context.clearRect(0, 0, window.innerWidth, window.innerHeight); - architecture.draw(context); - mrCroc.draw(context); + + camera.centerCamera(mrCroc.position.x - mrCroc.getWidth() * 0.5, mrCroc.position.y - mrCroc.getHeight() * 0.5); + architecture.draw(context, camera); + mrCroc.draw(context, camera); /* context.fillRect(0, ceilingHeight, window.innerWidth, 1); @@ -133,7 +136,7 @@ const FRAME_DURATION = 1000 / FPS; const GAME_SPEED = 1; const GRAVITY = 2; -let levelJson = new FileLoader('levels/test_startpoint.json'); +let levelJson = new FileLoader('levels/test_depth.json'); const LEVEL = JSON.parse(levelJson.getContent()); @@ -141,6 +144,7 @@ let lastRendered = undefined; let lastTimestamp = undefined; let context; let mrCroc, architecture; +let camera = new Camera(); let KeyLeft = new Key('ArrowLeft'); let KeyRight = new Key('ArrowRight'); @@ -178,6 +182,8 @@ window.addEventListener( context = canvas.getContext('2d'); architecture = RetroArchitecture.createFromData(LEVEL); + camera.borderRight = architecture.columns * architecture.tileWidth; + camera.borderBottom = architecture.rows * architecture.tileHeight; mrCroc = new MrCroc(); mrCroc.position.x = architecture.tileWidth * LEVEL.startX + architecture.tileWidth * 0.5; diff --git a/js/retro/RetroAnimation.js b/js/retro/RetroAnimation.js index 4f06db7..83a4534 100644 --- a/js/retro/RetroAnimation.js +++ b/js/retro/RetroAnimation.js @@ -42,7 +42,7 @@ export default class RetroAnimation extends RetroSprite } } - draw(context) + draw(context, camera) { if (!this.isPlaying) { this.currentFrame = 0; @@ -54,8 +54,8 @@ export default class RetroAnimation extends RetroSprite 0, this.frameWidth, this.canvas.height, - this.position.x, - this.position.y, + this.position.x - camera.position.x, + this.position.y - camera.position.y, this.frameWidth, this.canvas.height ); diff --git a/js/retro/RetroArchitecture.js b/js/retro/RetroArchitecture.js index 4070720..e50e929 100644 --- a/js/retro/RetroArchitecture.js +++ b/js/retro/RetroArchitecture.js @@ -140,10 +140,15 @@ export default class RetroArchitecture return 0; } - draw(context) + draw(context, camera = null) { - for (let y = 0; y < this.rows; y++) { - for (let x = 0; x < this.columns; x++) { + let viewX = parseInt(Math.floor(Math.max(0, camera.position.x) / this.tileWidth)); + let viewWidth = parseInt(Math.min(Math.ceil(camera.width), this.columns)); + let viewY = parseInt(Math.floor(Math.max(0, camera.position.y)) / this.tileHeight); + let viewHeight = parseInt(Math.min(Math.ceil(camera.height), this.rows)); + + for (let y = viewY; y < viewHeight; y++) { + for (let x = viewX; x < viewWidth; x++) { let field = this.matrix[y][x]; if (field !== null) { @@ -153,8 +158,8 @@ export default class RetroArchitecture 0, this.tileWidth, this.tileHeight, - x * this.tileWidth, - y * this.tileHeight, + x * this.tileWidth - camera.position.x, + y * this.tileHeight - camera.position.y, this.tileWidth, this.tileHeight ); diff --git a/js/retro/RetroSprite.js b/js/retro/RetroSprite.js index b21e3f6..4898835 100644 --- a/js/retro/RetroSprite.js +++ b/js/retro/RetroSprite.js @@ -61,9 +61,9 @@ export default class RetroSprite return new GeometryPoint(this.position.x + this.getWidth() * 0.5, this.position.y); } - draw(context) + draw(context, camera) { - context.drawImage(this.canvas, this.position.x, this.position.y); + context.drawImage(this.canvas, this.position.x - camera.position.x, this.position.y - camera.position.y); } hasRectCollisionWith(sprite) diff --git a/tilorswift/js/Terrain.js b/tilorswift/js/Terrain.js index addb5da..fbd0395 100644 --- a/tilorswift/js/Terrain.js +++ b/tilorswift/js/Terrain.js @@ -48,6 +48,16 @@ export default class Terrain return this.tileset; } + getWidth() + { + return this.tilesX * this.tilest.getTileWidth(); + } + + getHeight() + { + return this.tilesY * this.tilest.getTileHeight(); + } + addRows(index, quantity = 1) { for (let q = 0; q < quantity; q++) { @@ -70,6 +80,8 @@ export default class Terrain tr.appendChild(td); } + console.log(row.length); + if (index === undefined || index >= this.tilesY - 1) { this.fields.push(row); this.htmlElement.appendChild(tr); @@ -142,18 +154,21 @@ export default class Terrain return this.entranceTileX !== undefined && this.entranceTileY !== undefined; } - static createFromJson(json) + static createFromJson(terrainData) { - let terrainData = JSON.parse(json); let imageTileset = new Image(); imageTileset.src = terrainData.tileset; let tileset = new Tileset(imageTileset, terrainData.tiles, terrainData.scale); let terrain = new Terrain(tileset, terrainData.columns, terrainData.rows, terrainData.backgroundColor); - for (let y = 0; y < terrainData.matrix.length; y++) { - for (let x = 0; x < terrainData.matrix[y].length; x++) { + for (let y = 0; y < terrainData.rows; y++) { + for (let x = 0; x < terrainData.columns; x++) { terrain.setFieldIndex(x, y, terrainData.matrix[y][x]); + + if (x === terrainData.startX && y === terrainData.startY) { + terrain.setEntrancePoint(x, y); + } } } diff --git a/tilorswift/js/module.js b/tilorswift/js/module.js index d9afd7e..9bd3c30 100644 --- a/tilorswift/js/module.js +++ b/tilorswift/js/module.js @@ -20,16 +20,15 @@ import TilorswiftAddRowsClickedEvent from "./events/TilorswiftAddRowsClickedEven import TilorswiftAddColumnsClickedEvent from "./events/TilorswiftAddColumnsClickedEvent.js"; let loader = new FileLoader('../levels/level.json'); +let terrainData = JSON.parse(loader.getContent()); let image = new Image(); -image.src = '../graphics/tileset-landscape01.jpg'; +image.src = terrainData.tileset; image.onload = function () { - let terrain = Terrain.createFromJson(loader.getContent()); + let terrain = Terrain.createFromJson(terrainData); let map = document.getElementById('map'); map.appendChild(terrain.getElement()); - terrain.addColumns(200, 1); - let brush = new Brush(); let tileset = new Tileset(image, 8, 3); let widgetBar = new WidgetBar('widget-bar');