Terrain collision.

This commit is contained in:
Mal 2020-01-25 23:30:36 +01:00
parent 0cd532f45a
commit b7f669224d
3 changed files with 146 additions and 44 deletions

View File

@ -40,6 +40,16 @@ export default class Movable
return this.animations[this.currentAnimation].getRect(); return this.animations[this.currentAnimation].getRect();
} }
getWidth()
{
return this.getRect().width;
}
getHeight()
{
return this.getRect().height;
}
getPositionFootLeft() getPositionFootLeft()
{ {
return new GeometryPoint( return new GeometryPoint(
@ -50,7 +60,23 @@ export default class Movable
getPositionFootRight() getPositionFootRight()
{ {
return new GeometryPoint( return new GeometryPoint(
this.position.x + this.animations[this.currentAnimation].getWidth() * 0.5, this.position.y this.position.x + this.getWidth() * 0.5, this.position.y
);
}
getPositionHeadLeft()
{
return new GeometryPoint(
this.position.x - this.animations[this.currentAnimation].getWidth() * 0.5,
this.position.y - this.animations[this.currentAnimation].getHeight()
);
}
getPositionHeadRight()
{
return new GeometryPoint(
this.position.x + this.getWidth() * 0.5,
this.position.y - this.animations[this.currentAnimation].getHeight()
); );
} }

View File

@ -2,7 +2,6 @@ import Key from "./Key.js";
import MrCroc from "./MrCroc.js"; import MrCroc from "./MrCroc.js";
import RetroArchitecture from "./retro/RetroArchitecture.js"; import RetroArchitecture from "./retro/RetroArchitecture.js";
import FileLoader from "./FileLoader.js"; import FileLoader from "./FileLoader.js";
import GeometryPoint from "./geometry/GeometryPoint.js";
class ImageLoader class ImageLoader
{ {
@ -44,11 +43,10 @@ function MainLoop(timestamp)
let delta = (timestamp - lastTimestamp) / (10 / GAME_SPEED); let delta = (timestamp - lastTimestamp) / (10 / GAME_SPEED);
if (KeyLeft.isPressed()) { let lastCeilingHeight = Math.max(
mrCroc.moveLeft(timestamp, delta); architecture.getCeilingHeight(mrCroc.getPositionHeadLeft()),
} else if (KeyRight.isPressed()) { architecture.getCeilingHeight(mrCroc.getPositionHeadRight()),
mrCroc.moveRight(timestamp, delta); );
}
lastGroundHeight = Math.min( lastGroundHeight = Math.min(
architecture.getGroundHeight(mrCroc.getPositionFootLeft()), architecture.getGroundHeight(mrCroc.getPositionFootLeft()),
@ -62,47 +60,76 @@ function MainLoop(timestamp)
architecture.getGroundHeight(mrCroc.getPositionFootRight()) architecture.getGroundHeight(mrCroc.getPositionFootRight())
); );
if (mrCroc.position.y < lastGroundHeight) {
mrCroc.fallSpeed += GRAVITY * delta; mrCroc.fallSpeed += GRAVITY * delta;
}
/*
if (architecture.hasRectCollision(mrCroc.getRect())) { if (mrCroc.position.y >= lastGroundHeight) {
mrCroc.position.x = lastPosition.x;
}
let archIntersections = architecture.getCollisionRects(mrCroc.getRect());
let width = archIntersections.getUniqueWidth();
if (width !== null) {
if (width.x === mrCroc.position.x) {
mrCroc.position.x += width.width;
} else {
mrCroc.position.x = width.x - mrCroc.getRect().width;
}
}
*/
if (mrCroc.position.y !== lastGroundHeight) {
if (lastGroundHeight < groundHeight) {
mrCroc.position.y = lastGroundHeight; mrCroc.position.y = lastGroundHeight;
mrCroc.fallSpeed = 0; mrCroc.fallSpeed = 0;
} else {
mrCroc.fallSpeed += GRAVITY * delta;
} }
} else {
if (!mrCroc.isJumping && mrCroc.fallSpeed === 0 && KeyJump.isPressed()) { if (mrCroc.position.y - mrCroc.getHeight() <= lastCeilingHeight) {
mrCroc.fallSpeed = 0;
mrCroc.position.y = lastCeilingHeight + mrCroc.getHeight() + 1;
}
if (!mrCroc.isJumping && mrCroc.fallSpeed === 0 && mrCroc.position.y === groundHeight && KeyJump.isPressed()) {
mrCroc.jump(); mrCroc.jump();
} else if (!KeyJump.isPressed()) { } else if (!KeyJump.isPressed()) {
mrCroc.isJumping = false; mrCroc.isJumping = false;
} }
let lastWallRight = Math.min(
architecture.getWallRight(mrCroc.getPositionHeadRight()),
architecture.getWallRight(mrCroc.getPositionFootRight())
);
let lastWallLeft = Math.max(
architecture.getWallLeft(mrCroc.getPositionHeadLeft()),
architecture.getWallLeft(mrCroc.getPositionFootLeft())
);
if (KeyLeft.isPressed()) {
mrCroc.moveLeft(timestamp, delta);
let wallLeft = Math.max(
architecture.getWallLeft(mrCroc.getPositionHeadLeft()),
architecture.getWallLeft(mrCroc.getPositionFootLeft())
);
if (wallLeft < lastWallLeft) {
mrCroc.position.x = lastWallLeft + 1;
}
} else if (KeyRight.isPressed()) {
mrCroc.moveRight(timestamp, delta);
let wallRight = Math.min(
architecture.getWallRight(mrCroc.getPositionHeadRight()),
architecture.getWallRight(mrCroc.getPositionFootRight())
);
if (wallRight > lastWallRight) {
mrCroc.position.x = lastWallRight - 1;
}
} }
if (timestamp - lastRendered >= FRAME_DURATION) { if (timestamp - lastRendered >= FRAME_DURATION) {
context.clearRect(0, 0, window.innerWidth, window.innerHeight); context.clearRect(0, 0, window.innerWidth, window.innerHeight);
architecture.draw(context); architecture.draw(context);
mrCroc.draw(context); mrCroc.draw(context);
/*
context.fillRect(0, lastCeilingHeight, window.innerWidth, 1);
context.fillRect(0, lastGroundHeight, window.innerWidth, 1);
context.fillStyle = 'black';
context.fillRect(lastWallRight, 0, 1, window.innerHeight);
context.fillStyle = 'red';
context.fillRect(lastWallLeft, 0, 1, window.innerHeight);
mrCroc.getPositionHeadRight().draw(context);
mrCroc.getPositionFootRight().draw(context);
mrCroc.getPositionHeadLeft().draw(context);
mrCroc.getPositionFootLeft().draw(context);
*/
lastRendered = timestamp; lastRendered = timestamp;
} }
@ -114,13 +141,11 @@ function MainLoop(timestamp)
const FPS = 60; const FPS = 60;
const FRAME_DURATION = 1000 / FPS; const FRAME_DURATION = 1000 / FPS;
const GAME_SPEED = 1; const GAME_SPEED = 1;
const GRAVITY = 1; const GRAVITY = 2;
let levelJson = new FileLoader('levels/test.json'); let levelJson = new FileLoader('levels/test.json');
const LEVEL = levelJson.getContent(); const LEVEL = levelJson.getContent();
console.log(LEVEL);
let lastRendered = undefined; let lastRendered = undefined;
let lastTimestamp = undefined; let lastTimestamp = undefined;
let groundHeight = undefined; let groundHeight = undefined;
@ -151,7 +176,7 @@ imgBackground.src = 'graphics/ground.jpg';
loader.addImage(imgBackground); loader.addImage(imgBackground);
let imgArch = new Image(); let imgArch = new Image();
imgArch.src = 'graphics/maria-world.jpg'; imgArch.src = 'graphics/tileset-landscape01.jpg';
loader.addImage(imgArch); loader.addImage(imgArch);
window.addEventListener( window.addEventListener(
@ -161,6 +186,14 @@ window.addEventListener(
canvas.width = window.innerWidth; canvas.width = window.innerWidth;
canvas.height = window.innerHeight; canvas.height = window.innerHeight;
window.addEventListener(
'resize',
function () {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
);
context = canvas.getContext('2d'); context = canvas.getContext('2d');
architecture = RetroArchitecture.createFromJson(LEVEL); architecture = RetroArchitecture.createFromJson(LEVEL);
@ -169,9 +202,6 @@ window.addEventListener(
mrCroc.position.x = 300; mrCroc.position.x = 300;
mrCroc.position.y = 100; mrCroc.position.y = 100;
architecture.draw(context);
mrCroc.draw(context);
window.requestAnimationFrame(MainLoop); window.requestAnimationFrame(MainLoop);
} }
); );

View File

@ -1,6 +1,7 @@
import RetroSprite from "./RetroSprite.js"; import RetroSprite from "./RetroSprite.js";
import RetroArchitectureTile from "./RetroArchitectureTile.js"; import RetroArchitectureTile from "./RetroArchitectureTile.js";
import GeometryRectCollection from "../geometry/GeometryRectCollection.js"; import GeometryRectCollection from "../geometry/GeometryRectCollection.js";
import GeometryPoint from "../geometry/GeometryPoint.js";
export default class RetroArchitecture export default class RetroArchitecture
{ {
@ -67,10 +68,10 @@ export default class RetroArchitecture
return false; return false;
} }
getTileForPosition(position) getTileForPosition(position, offsetX = 0, offsetY = 0)
{ {
let x = parseInt(position.x / this.tileWidth); let x = parseInt(position.x / this.tileWidth) + offsetX;
let y = parseInt(position.y / this.tileHeight); let y = parseInt(position.y / this.tileHeight) + offsetY;
if (x < 0 || x >= this.columns || y < 0 || y >= this.rows) { if (x < 0 || x >= this.columns || y < 0 || y >= this.rows) {
return null; return null;
@ -79,13 +80,28 @@ export default class RetroArchitecture
return {x: x, y: y}; return {x: x, y: y};
} }
getCeilingHeight(position)
{
let tilePosition = this.getTileForPosition(position, 0);
while (tilePosition !== null && tilePosition.y > 0) {
if (this.matrix[tilePosition.y][tilePosition.x] !== null) {
return tilePosition.y * this.tileHeight + this.tileHeight;
}
tilePosition.y--;
}
return 0;
}
getGroundHeight(position) getGroundHeight(position)
{ {
let tilePosition = this.getTileForPosition(position); let tilePosition = this.getTileForPosition(position);
while (tilePosition !== null && tilePosition.y < this.rows) { while (tilePosition !== null && tilePosition.y < this.rows) {
if (this.matrix[tilePosition.y][tilePosition.x] !== null) { if (this.matrix[tilePosition.y][tilePosition.x] !== null) {
return tilePosition.y * this.tileHeight return tilePosition.y * this.tileHeight;
} }
tilePosition.y++; tilePosition.y++;
@ -94,6 +110,36 @@ export default class RetroArchitecture
return this.tileHeight * this.rows; return this.tileHeight * this.rows;
} }
getWallRight(position)
{
let tilePosition = this.getTileForPosition(new GeometryPoint(position.x, position.y), 1, -1);
while (tilePosition !== null && tilePosition.x < this.columns) {
if (this.matrix[tilePosition.y][tilePosition.x] !== null) {
return tilePosition.x * this.tileWidth - this.tileWidth * 0.5;
}
tilePosition.x++;
}
return this.tileWidth * this.columns;
}
getWallLeft(position)
{
let tilePosition = this.getTileForPosition(new GeometryPoint(position.x, position.y), -1,-1);
while (tilePosition !== null && tilePosition.x > 0) {
if (this.matrix[tilePosition.y][tilePosition.x] !== null) {
return tilePosition.x * this.tileWidth + this.tileWidth * 1.5;
}
tilePosition.x--;
}
return 0;
}
draw(context) draw(context)
{ {
for (let y = 0; y < this.rows; y++) { for (let y = 0; y < this.rows; y++) {