Camera implemented.

This commit is contained in:
Mal 2020-02-09 22:06:59 +01:00
parent d43cd56d65
commit f6890eec24
8 changed files with 116 additions and 23 deletions

60
js/Camera.js Normal file
View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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
);

View File

@ -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
);

View File

@ -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)

View File

@ -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);
}
}
}

View File

@ -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');