Gravity and ground height.
This commit is contained in:
parent
388799c97e
commit
0cd532f45a
|
@ -0,0 +1,28 @@
|
||||||
|
export default class FileLoader
|
||||||
|
{
|
||||||
|
constructor(filename)
|
||||||
|
{
|
||||||
|
this.filename = filename;
|
||||||
|
this.content = '';
|
||||||
|
this.loadContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
getContent()
|
||||||
|
{
|
||||||
|
return this.content;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadContent()
|
||||||
|
{
|
||||||
|
let request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.onreadystatechange = () => {
|
||||||
|
if (request.status === 200 && request.readyState === 4) {
|
||||||
|
this.content = request.responseText;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
request.open('GET', this.filename, false);
|
||||||
|
request.send();
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ export default class Movable
|
||||||
};
|
};
|
||||||
this.position = new GeometryPoint();
|
this.position = new GeometryPoint();
|
||||||
this.speed = speed;
|
this.speed = speed;
|
||||||
|
this.jumpHeight = 35;
|
||||||
this.fallSpeed = 0;
|
this.fallSpeed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +40,39 @@ export default class Movable
|
||||||
return this.animations[this.currentAnimation].getRect();
|
return this.animations[this.currentAnimation].getRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPositionFootLeft()
|
||||||
|
{
|
||||||
|
return new GeometryPoint(
|
||||||
|
this.position.x - this.animations[this.currentAnimation].getWidth() * 0.5, this.position.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPositionFootRight()
|
||||||
|
{
|
||||||
|
return new GeometryPoint(
|
||||||
|
this.position.x + this.animations[this.currentAnimation].getWidth() * 0.5, this.position.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
jump()
|
||||||
|
{
|
||||||
|
this.fallSpeed -= this.jumpHeight;
|
||||||
|
this.isJumping = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFootHeight()
|
||||||
|
{
|
||||||
|
return new GeometryPoint(
|
||||||
|
this.position.x,
|
||||||
|
this.position.y + this.animations[this.currentAnimation].getHeight()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
setFootHeight(height)
|
||||||
|
{
|
||||||
|
this.position.y = height - this.animations[this.currentAnimation].getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
draw(context)
|
draw(context)
|
||||||
{
|
{
|
||||||
this.animations[this.currentAnimation].setFootPosition(this.position.x, this.position.y);
|
this.animations[this.currentAnimation].setFootPosition(this.position.x, this.position.y);
|
||||||
|
|
|
@ -4,10 +4,11 @@ import RetroAnimation from "./retro/RetroAnimation.js";
|
||||||
export default class MrCroc extends Movable
|
export default class MrCroc extends Movable
|
||||||
{
|
{
|
||||||
constructor() {
|
constructor() {
|
||||||
super(new RetroAnimation('graphics/mr-croc-walk-right.png', 2, 5), 5);
|
let SCALE = 3;
|
||||||
|
super(new RetroAnimation('graphics/mr-croc-walk-right.png', 2, SCALE), 7);
|
||||||
this.addAnimation('WALK_RIGHT', new RetroAnimation('graphics/mr-croc-walk-right.png', 2, 5, 10));
|
this.isJumping = false;
|
||||||
this.addAnimation('WALK_LEFT', new RetroAnimation('graphics/mr-croc-walk-left.png', 2, 5, 10));
|
this.addAnimation('WALK_RIGHT', new RetroAnimation('graphics/mr-croc-walk-right.png', 2, SCALE, 10));
|
||||||
|
this.addAnimation('WALK_LEFT', new RetroAnimation('graphics/mr-croc-walk-left.png', 2, SCALE, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
moveRight(timestamp, delta = 1)
|
moveRight(timestamp, delta = 1)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import GeometryPoint from "./GeometryPoint.js";
|
import GeometryPoint from "./GeometryPoint.js";
|
||||||
import GeometryStroke from "./GeometryStroke.js";
|
import GeometryStroke from "./GeometryStroke.js";
|
||||||
import GeometryPointCollection from "./GeometryPointCollection.js";
|
import GeometryPointCollection from "./GeometryPointCollection.js";
|
||||||
import GeometryLine from "./GeometryLine.js";
|
|
||||||
|
|
||||||
export default class GeometryRect
|
export default class GeometryRect
|
||||||
{
|
{
|
||||||
|
@ -26,12 +25,17 @@ export default class GeometryRect
|
||||||
*/
|
*/
|
||||||
isContainingPoint(geometryPoint)
|
isContainingPoint(geometryPoint)
|
||||||
{
|
{
|
||||||
let containsHorizontally = geometryPoint.x >= this.position.x && geometryPoint.x <= this.position.x + this.width;
|
let containsHorizontally = geometryPoint.x >= this.position.x && geometryPoint.x < this.position.x + this.width;
|
||||||
let containsVertically = geometryPoint.y >= this.position.y && geometryPoint.y <= this.position.y + this.height;
|
let containsVertically = geometryPoint.y >= this.position.y && geometryPoint.y < this.position.y + this.height;
|
||||||
|
|
||||||
return containsHorizontally && containsVertically;
|
return containsHorizontally && containsVertically;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isEqual(rect)
|
||||||
|
{
|
||||||
|
return rect.x === this.x && rect.y === this.y && rect.width === this.width && rect.height === this.height;
|
||||||
|
}
|
||||||
|
|
||||||
hasIntersectionWithRect(rect)
|
hasIntersectionWithRect(rect)
|
||||||
{
|
{
|
||||||
return this.getBorderIntersectonsWithRect(rect).getLength() > 0;
|
return this.getBorderIntersectonsWithRect(rect).getLength() > 0;
|
||||||
|
@ -170,8 +174,8 @@ export default class GeometryRect
|
||||||
|
|
||||||
collection.addGeometryPoint(this.position);
|
collection.addGeometryPoint(this.position);
|
||||||
collection.addGeometryPoint(new GeometryPoint(this.position.x + this.width, this.position.y));
|
collection.addGeometryPoint(new GeometryPoint(this.position.x + this.width, this.position.y));
|
||||||
collection.addGeometryPoint(new GeometryPoint(this.position.x, this.position.y + this.height));
|
collection.addGeometryPoint(new GeometryPoint(this.position.x, this.position.y + this.height - 1));
|
||||||
collection.addGeometryPoint(new GeometryPoint(this.position.x + this.width, this.position.y + this.height));
|
collection.addGeometryPoint(new GeometryPoint(this.position.x + this.width, this.position.y + this.height - 1));
|
||||||
|
|
||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
export default class GeometryRectCollection
|
||||||
|
{
|
||||||
|
constructor()
|
||||||
|
{
|
||||||
|
this.rects = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
isContainingRect(rect)
|
||||||
|
{
|
||||||
|
for (let r = 0; r < this.rects.length; r++) {
|
||||||
|
if (rect.isEqual(this.rects[r])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getUniqueWidth()
|
||||||
|
{
|
||||||
|
if (this.getLength() === 0) {
|
||||||
|
return null;
|
||||||
|
} else if (this.getLength() === 1) {
|
||||||
|
return this.rects[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
let widths = [this.rects[0].width];
|
||||||
|
|
||||||
|
for (let r = 0; r < this.getLength(); r++) {
|
||||||
|
if (widths.indexOf(this.rects[r].width) !== -1) {
|
||||||
|
return this.rects[r];
|
||||||
|
}
|
||||||
|
|
||||||
|
widths.push(rect.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getUniqueHeight()
|
||||||
|
{
|
||||||
|
if (this.getLength() === 0) {
|
||||||
|
return null;
|
||||||
|
} else if (this.getLength() === 1) {
|
||||||
|
return this.rects[0].height;
|
||||||
|
}
|
||||||
|
|
||||||
|
let heights = [this.rects[0].height];
|
||||||
|
|
||||||
|
for (let r = 0; r < this.getLength(); r++) {
|
||||||
|
if (heights.indexOf(rect.height) !== -1) {
|
||||||
|
return rect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
heights.push(rect.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
addRect(rect)
|
||||||
|
{
|
||||||
|
if (!this.isContainingRect(rect)) {
|
||||||
|
this.rects.push(rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getLength()
|
||||||
|
{
|
||||||
|
return this.rects.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
getEqualWidths()
|
||||||
|
{
|
||||||
|
if (this.getLength() === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let width = this.rects[0].width;
|
||||||
|
|
||||||
|
for (let r = 1; r < this.getLength(); r++) {
|
||||||
|
if (this.rects[r].width === width) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasEqualWidths()
|
||||||
|
{
|
||||||
|
if (this.getLength() === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let width = this.rects[0].width;
|
||||||
|
|
||||||
|
for (let r = 1; r < this.getLength(); r++) {
|
||||||
|
if (this.rects[r].width !== width) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasEqualHeights()
|
||||||
|
{
|
||||||
|
if (this.getLength() === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let height = this.rects[0].height;
|
||||||
|
|
||||||
|
for (let r = 1; r < this.getLength(); r++) {
|
||||||
|
if (this.rects[r].height !== height) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
forEach(callback)
|
||||||
|
{
|
||||||
|
this.rects.forEach(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRect(index)
|
||||||
|
{
|
||||||
|
return this.rects[index];
|
||||||
|
}
|
||||||
|
}
|
85
js/module.js
85
js/module.js
|
@ -1,10 +1,8 @@
|
||||||
import RetroSprite from "./retro/RetroSprite.js";
|
|
||||||
import Key from "./Key.js";
|
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";
|
||||||
const MEDIA_READY_EVENT = 'mediaready';
|
import GeometryPoint from "./geometry/GeometryPoint.js";
|
||||||
const IMAGE_READY_EVENT = 'imgready';
|
|
||||||
|
|
||||||
class ImageLoader
|
class ImageLoader
|
||||||
{
|
{
|
||||||
|
@ -52,12 +50,59 @@ function MainLoop(timestamp)
|
||||||
mrCroc.moveRight(timestamp, delta);
|
mrCroc.moveRight(timestamp, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastRendered >= FRAME_DURATION) {
|
lastGroundHeight = Math.min(
|
||||||
context.clearRect(0, 0, window.innerWidth, window.innerHeight);
|
architecture.getGroundHeight(mrCroc.getPositionFootLeft()),
|
||||||
|
architecture.getGroundHeight(mrCroc.getPositionFootRight())
|
||||||
|
);
|
||||||
|
|
||||||
ground.draw(context);
|
mrCroc.position.y += mrCroc.fallSpeed;
|
||||||
mrCroc.draw(context);
|
|
||||||
|
groundHeight = Math.min(
|
||||||
|
architecture.getGroundHeight(mrCroc.getPositionFootLeft()),
|
||||||
|
architecture.getGroundHeight(mrCroc.getPositionFootRight())
|
||||||
|
);
|
||||||
|
|
||||||
|
if (mrCroc.position.y < lastGroundHeight) {
|
||||||
|
mrCroc.fallSpeed += GRAVITY * delta;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
if (architecture.hasRectCollision(mrCroc.getRect())) {
|
||||||
|
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.fallSpeed = 0;
|
||||||
|
} else {
|
||||||
|
mrCroc.fallSpeed += GRAVITY * delta;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!mrCroc.isJumping && mrCroc.fallSpeed === 0 && KeyJump.isPressed()) {
|
||||||
|
mrCroc.jump();
|
||||||
|
} else if (!KeyJump.isPressed()) {
|
||||||
|
mrCroc.isJumping = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timestamp - lastRendered >= FRAME_DURATION) {
|
||||||
|
context.clearRect(0, 0, window.innerWidth, window.innerHeight);
|
||||||
architecture.draw(context);
|
architecture.draw(context);
|
||||||
|
mrCroc.draw(context);
|
||||||
lastRendered = timestamp;
|
lastRendered = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,16 +114,23 @@ 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 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 levelJson = new FileLoader('levels/test.json');
|
||||||
|
const LEVEL = levelJson.getContent();
|
||||||
|
|
||||||
|
console.log(LEVEL);
|
||||||
|
|
||||||
let lastRendered = undefined;
|
let lastRendered = undefined;
|
||||||
let lastTimestamp = undefined;
|
let lastTimestamp = undefined;
|
||||||
|
let groundHeight = undefined;
|
||||||
|
let lastGroundHeight = undefined;
|
||||||
let context;
|
let context;
|
||||||
let ground, mrCroc, architecture;
|
let mrCroc, architecture;
|
||||||
|
|
||||||
let KeyLeft = new Key('ArrowLeft');
|
let KeyLeft = new Key('ArrowLeft');
|
||||||
let KeyRight = new Key('ArrowRight');
|
let KeyRight = new Key('ArrowRight');
|
||||||
|
let KeyJump = new Key('Space');
|
||||||
|
|
||||||
let loader = new ImageLoader();
|
let loader = new ImageLoader();
|
||||||
|
|
||||||
|
@ -99,15 +151,12 @@ imgBackground.src = 'graphics/ground.jpg';
|
||||||
loader.addImage(imgBackground);
|
loader.addImage(imgBackground);
|
||||||
|
|
||||||
let imgArch = new Image();
|
let imgArch = new Image();
|
||||||
imgArch.src = 'graphics/tileset.png';
|
imgArch.src = 'graphics/maria-world.jpg';
|
||||||
loader.addImage(imgArch);
|
loader.addImage(imgArch);
|
||||||
|
|
||||||
window.addEventListener(
|
window.addEventListener(
|
||||||
'imagesloaded',
|
'imagesloaded',
|
||||||
() => {
|
() => {
|
||||||
ground = new RetroSprite('graphics/ground.jpg', 4);
|
|
||||||
ground.position.y = window.innerHeight - ground.getRect().height;
|
|
||||||
|
|
||||||
let canvas = document.getElementById('canvas');
|
let canvas = document.getElementById('canvas');
|
||||||
canvas.width = window.innerWidth;
|
canvas.width = window.innerWidth;
|
||||||
canvas.height = window.innerHeight;
|
canvas.height = window.innerHeight;
|
||||||
|
@ -117,9 +166,11 @@ window.addEventListener(
|
||||||
architecture = RetroArchitecture.createFromJson(LEVEL);
|
architecture = RetroArchitecture.createFromJson(LEVEL);
|
||||||
|
|
||||||
mrCroc = new MrCroc();
|
mrCroc = new MrCroc();
|
||||||
mrCroc.position.x = 100;
|
mrCroc.position.x = 300;
|
||||||
mrCroc.position.y = 480;
|
mrCroc.position.y = 100;
|
||||||
ground.draw(context);
|
|
||||||
|
architecture.draw(context);
|
||||||
|
mrCroc.draw(context);
|
||||||
|
|
||||||
window.requestAnimationFrame(MainLoop);
|
window.requestAnimationFrame(MainLoop);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import RetroSprite from "./RetroSprite.js";
|
import RetroSprite from "./RetroSprite.js";
|
||||||
import GeometryRect from "../geometry/GeometryRect.js";
|
|
||||||
import RetroArchitectureTile from "./RetroArchitectureTile.js";
|
import RetroArchitectureTile from "./RetroArchitectureTile.js";
|
||||||
|
import GeometryRectCollection from "../geometry/GeometryRectCollection.js";
|
||||||
|
|
||||||
export default class RetroArchitecture
|
export default class RetroArchitecture
|
||||||
{
|
{
|
||||||
|
@ -24,6 +24,29 @@ export default class RetroArchitecture
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCollisionRects(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;
|
||||||
|
|
||||||
|
let collection = new GeometryRectCollection();
|
||||||
|
|
||||||
|
for (let y = Math.max(0, posY); y < rangeY; y++) {
|
||||||
|
for (let x = Math.max(0, posX); x < rangeX; x++) {
|
||||||
|
if (y < this.matrix.length && x < this.matrix[y].length && this.matrix[y][x] !== null) {
|
||||||
|
let intersection = this.matrix[y][x].rect.getRectIntersection(rect);
|
||||||
|
if (intersection !== null) {
|
||||||
|
collection.addRect(intersection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
|
||||||
hasRectCollision(rect)
|
hasRectCollision(rect)
|
||||||
{
|
{
|
||||||
let posX = Math.floor(rect.position.x / this.tileWidth) - 2;
|
let posX = Math.floor(rect.position.x / this.tileWidth) - 2;
|
||||||
|
|
|
@ -46,6 +46,21 @@ export default class RetroSprite
|
||||||
return this.canvas.height;
|
return this.canvas.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFootHeight()
|
||||||
|
{
|
||||||
|
return new GeometryPoint(this.position.x, this.position.y + this.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
getPositionLeftFoot()
|
||||||
|
{
|
||||||
|
return new GeometryPoint(this.position.x - this.getWidth() * 0.5, this.position.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPositionRightFoot()
|
||||||
|
{
|
||||||
|
return new GeometryPoint(this.position.x + this.getWidth() * 0.5, this.position.y);
|
||||||
|
}
|
||||||
|
|
||||||
draw(context)
|
draw(context)
|
||||||
{
|
{
|
||||||
context.drawImage(this.canvas, this.position.x, this.position.y);
|
context.drawImage(this.canvas, this.position.x, this.position.y);
|
||||||
|
|
Loading…
Reference in New Issue