Skip to content

Commit

Permalink
feat: Add bricks and cut rope on mini brick hit
Browse files Browse the repository at this point in the history
  • Loading branch information
johnedvard committed Aug 23, 2022
1 parent 38d4c8c commit 949e891
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 7 deletions.
32 changes: 32 additions & 0 deletions src/Brick.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export class Brick {
x;
y;
level;
width = 32;
height = 32;
constructor(x, y, { level }) {
this.x = x;
this.y = y;
this.level = level;
}

getSmallCollisionBox() {
return {
x: this.x + 10,
y: this.y + 10,
width: 12,
height: 12,
};
}
update() {}

render(ctx) {
if (!ctx) return;
ctx.lineWidth = 4;
ctx.beginPath();

ctx.rect(this.x, this.y, this.width, this.height); // Render collision box
ctx.rect(this.x + 10, this.y + 10, 12, 12);
ctx.stroke();
}
}
2 changes: 1 addition & 1 deletion src/Game.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class Game {
level;
constructor() {
// TODO (johnedvard) Play song after user interraction
playSong();
// playSong();

const game = this;
let { canvas, context } = init();
Expand Down
28 changes: 27 additions & 1 deletion src/Level.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { Brick } from './Brick';
import { Goal } from './Goal';
import { Heart } from './Heart';
import { Player } from './Player';
import { Saw } from './Saw';
import { BACK_FORTH } from './sawBehavior';
import { isBoxCollision, lineIntersection } from './utils';

export class Level {
player;
saws = [];
goals = [];
hearts = [];
bricks = [];
isLevelLoaded = false;
levelId = -1;
constructor(levelId, { game }) {
Expand All @@ -19,6 +22,7 @@ export class Level {
this.createSaws(levelData);
this.createGoals(levelData);
this.createHearts(levelData);
this.createBricks(levelData);
this.isLevelLoaded = true;
});
}
Expand Down Expand Up @@ -46,6 +50,9 @@ export class Level {
this.hearts.forEach((heart) => {
heart.render(ctx);
});
this.bricks.forEach((brick) => {
brick.render(ctx);
});
this.player.render(ctx);
this.goals.forEach((goal) => {
goal.render(ctx);
Expand All @@ -65,29 +72,42 @@ export class Level {
this.hearts.forEach((heart) => {
heart.update();
});
this.bricks.forEach((brick) => {
brick.update();
});
}

createGoals(levelData) {
levelData.g.forEach((g) => {
this.goals.push(new Goal(g.x, g.y, { level: this }));
});
}

createPlayer(levelData) {
this.player = new Player({
levelData,
game: this.game,
});
}

createSaws(levelData) {
levelData.s.forEach((saw) => {
// TODO (johnedvard) Add actual saw behaviour
this.saws.push(new Saw(saw.x, saw.y, { behavior: BACK_FORTH }));
this.saws.push(
new Saw(saw.x, saw.y, { behavior: BACK_FORTH, level: this })
);
});
}
createHearts(levelData) {
levelData.h.forEach((heart) => {
this.hearts.push(new Heart(heart.x, heart.y, { level: this }));
});
}
createBricks(levelData) {
levelData.b.forEach((brick) => {
this.bricks.push(new Brick(brick.x, brick.y, { level: this }));
});
}

// TODO (johnedvard) Move collisions to own file?
checkCollisions() {
Expand All @@ -106,6 +126,12 @@ export class Level {
this.player.cutRope(i);
}
});
this.bricks.forEach((brick) => {
if (rope[i].isAnchor()) return;
if (isBoxCollision(brick.getSmallCollisionBox(), rope[i])) {
this.player.cutRope(i);
}
});
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/Player.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export class Player {
headImg = { width: 0, height: 0 };
headOffset = { x: 10, y: 38 };
isLeft = false;
isRopeCut = false;

constructor({ game, levelData }) {
this.game = game;
Expand Down Expand Up @@ -190,6 +191,7 @@ export class Player {
}
cutRope = (index) => {
if (index >= this.rope.length - 1) index = this.rope.length - 2; // Make sure we can cut the rope if we pass the wrong index
this.isRopeCut = true;
this.rope[index].removeLink();
};

Expand Down
1 change: 1 addition & 0 deletions src/PlayerControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export class PlayerControls {
}

updateControls() {
if (this.player.isRopeCut) return;
// TODO (johnedvard) add support for touch gesture and gamepad (if enough space)
if (keyPressed('arrowleft')) {
this.player.applyForce(-1.5, 0);
Expand Down
65 changes: 63 additions & 2 deletions src/PointMass.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { Vector } from 'kontra';
import { BoneLink } from './BoneLink';
import { gravity } from './constants';
import { fgc2, RESTING_DISTANCE } from './constants';
import { isBoxCollision, lineIntersection } from './utils';

export class PointMass {
sprite; // TODO (johnedvard) maybe remove
x;
y;
width = 4;
height = 4;
lastX;
lastY;
accX = 0;
Expand All @@ -15,10 +19,12 @@ export class PointMass {
anchorY;
mass = 1;
game;
level;
restingDistance = RESTING_DISTANCE;

constructor(x, y, { isAnchor, game, mass }) {
this.game = game;
this.level = game.level;
this.x = x;
this.y = y;
this.lastX = x;
Expand Down Expand Up @@ -121,11 +127,11 @@ export class PointMass {

/* Boundary Constraints */
// These if statements keep the PointMasss within the screen
if (this.y < 1) this.y = 2 * 1 - this.y;
if (this.y < 1) this.y = 2 - this.y;
if (this.y > this.game.canvas.height - 1)
this.y = 2 * (this.game.canvas.height - 1) - this.y;

if (this.x < 1) this.x = 2 * 1 - this.x;
if (this.x < 1) this.x = 2 - this.x;
if (this.x > this.game.canvas.width - 1)
this.x = 2 * (this.game.canvas.width - 1) - this.x;

Expand All @@ -134,6 +140,61 @@ export class PointMass {
if (this.isAnchor()) {
this.x = this.anchorX;
this.y = this.anchorY;
return;
}

/* Collision on boxes */

const bricks = this.level.bricks;
bricks.forEach((b) => {
// check left edge
if (this.links.length) {
const pointB = this.links[0].pointMassB;
if (
// hit left edge
lineIntersection(
{ x: b.x - 2, y: b.y },
{ x: b.x - 2, y: b.y + b.height },
{ x: this.x, y: this.y },
{ x: pointB.x, y: pointB.y }
)
) {
this.x = b.x - 2;
}
// hit top edge
if (
lineIntersection(
{ x: b.x, y: b.y - 2 },
{ x: b.x + b.width, y: b.y - 2 },
{ x: this.x, y: this.y },
{ x: pointB.x, y: pointB.y }
)
) {
this.y = b.y - 2;
}
// hit right edge
if (
lineIntersection(
{ x: b.x + b.width + 2, y: b.y },
{ x: b.x + b.width + 2, y: b.y + b.height },
{ x: this.x, y: this.y },
{ x: pointB.x, y: pointB.y }
)
) {
this.x = b.x + b.width + 2;
}
// hit bottom edge
if (
lineIntersection(
{ x: b.x, y: b.y + b.height + 2 },
{ x: b.x + b.width, y: b.y + b.height + 2 },
{ x: this.x, y: this.y },
{ x: pointB.x, y: pointB.y }
)
) {
this.y = b.y + b.height + 2;
}
}
});
}
}
4 changes: 3 additions & 1 deletion src/Saw.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ export class Saw {
speed = 1;
scale = 4;
rotSpeed = 0.2;
level;

constructor(x, y, { behavior, distance }) {
constructor(x, y, { behavior, distance, level }) {
this.x = x;
this.y = y;
this.orgX = x;
this.orgY = y;
this.distance = distance;
this.behavior = behavior;
this.level = level;
this.createSprite();
}

Expand Down
16 changes: 14 additions & 2 deletions src/level/level1.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,19 @@
"p": { "x": 400, "y": 200 },
"r": 7,
"s": [],
"b": [{ "x": 400, "y": 400 }],
"b": [
{ "x": 0, "y": 0 },
{ "x": 272, "y": 180 },
{ "x": 304, "y": 180 },
{ "x": 336, "y": 180 },
{ "x": 368, "y": 180 },
{ "x": 400, "y": 180 },
{ "x": 432, "y": 180 },
{ "x": 464, "y": 180 },
{ "x": 496, "y": 180 },
{ "x": 440, "y": 300 },
{ "x": 304, "y": 300 }
],
"g": [{ "x": 368, "y": 700 }],
"h": [{ "x": 550, "y": 200 }]
"h": [{ "x": 550, "y": 240 }]
}

0 comments on commit 949e891

Please sign in to comment.