Skip to content

Commit

Permalink
feat: Add win condition and goal animation
Browse files Browse the repository at this point in the history
  • Loading branch information
johnedvard committed Aug 21, 2022
1 parent bf9889b commit 3b0c4da
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 34 deletions.
84 changes: 57 additions & 27 deletions src/Goal.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,83 @@
import * as grave from 'data-url:./assets/img/grave-4x-mini.png';

import { Sprite } from 'kontra';
import { emit } from 'kontra';

import { isBoxCollision } from './utils';
import { GOAL_COLLISION } from './gameEvents';

export class Goal {
level;
sprite;
scale = 2;
scale = 1;
width = 60;
height = 32;
originalRadius = { x: 15, y: 30 };
radiusX = 15;
radiusY = 30;
hasWon = false;
hasVanished = false;
vanishSpeed = 0.3;

constructor(x, y, { level }) {
this.x = x;
this.y = y;
this.level = level;
this.createSprite();
}
update() {
if (this.hasVanished) return;
this.checkCollision();
if (this.sprite) {
this.sprite.update();
}
}
render() {
render(ctx) {
if (!ctx || this.hasVanished) return;
ctx.lineWidth = 4;
ctx.beginPath();

if (this.hasWon) {
this.startVanishing();
}
// ctx.rect(this.x, this.y, this.width, this.height); // Render collision box
ctx.ellipse(
this.x + this.width / 2,
this.y + this.height / 2,
this.radiusX,
this.radiusY,
Math.PI / 2,
0,
Math.PI * 2
);
ctx.stroke();
if (this.sprite) {
this.sprite.render();
}
}

checkCollision() {
if (isBoxCollision(this.sprite, this.level.player.sprite)) {
console.log('collided');
startVanishing() {
this.radiusX -= this.vanishSpeed;
this.radiusY -= this.vanishSpeed * 2;
if (this.radiusX <= 0) this.radiusX = 0;
if (this.radiusY <= 0) this.radiusY = 0;
if (this.radiusX <= 0 && this.radiusY <= 0) {
this.hasVanished = true;
}
}

createSprite() {
const image = new Image();
image.src = grave;
image.onerror = function (err) {
console.log(err);
};
image.onload = () => {
this.sprite = Sprite({
x: this.x,
y: this.y,
width: 32,
height: 32,
image: image,
scaleX: this.scale,
scaleY: this.scale,
});
};
checkCollision() {
const player = this.level.player;
if (
isBoxCollision(
{
x: this.x,
y: this.y,
scaleX: this.scale,
scaleY: this.scale,
width: this.width,
height: this.height,
},
this.level.player.sprite
)
) {
this.hasWon = true;
emit(GOAL_COLLISION);
}
}
}
2 changes: 1 addition & 1 deletion src/Level.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class Level {
saw.render(ctx);
});
this.goals.forEach((goal) => {
goal.render();
goal.render(ctx);
});
}

Expand Down
30 changes: 28 additions & 2 deletions src/Player.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import skull from 'data-url:./assets/img/skull.png';

import { getPointer, Sprite } from 'kontra';
import { getPointer, Sprite, on } from 'kontra';
import { PlayerControls } from './PlayerControls';
import { PointMass } from './PointMass';
import { RESTING_DISTANCE } from './constants';
import { fgc2, RESTING_DISTANCE } from './constants';
import { GOAL_COLLISION } from './gameEvents';

export class Player {
game;
Expand All @@ -12,6 +13,7 @@ export class Player {
playerControls;
sprite = { render: () => {}, x: 0, y: 0 }; // draw sprite on pointmass position
scale = 4;
hasWon = false;

constructor({ game, levelData }) {
this.game = game;
Expand All @@ -26,15 +28,18 @@ export class Player {
this.createRope({ startX, startY, ropeLength });
this.createSprite();
this.playerControls = new PlayerControls(this);
this.listenForGameEvents();
}

updateRope() {
if (this.hasWon) return;
this.rope.forEach((p) => {
p.update();
});
}

renderRope(ctx) {
if (this.hasWon) return;
this.rope.forEach((p) => {
p.render(ctx);
});
Expand Down Expand Up @@ -107,6 +112,20 @@ export class Player {
render(ctx) {
this.renderRope(ctx);
this.renderPlayer(ctx);
// this.renderCollisionBox(ctx);
}

renderCollisionBox(ctx) {
ctx.lineWidth = 4;
ctx.strokeStyle = fgc2;
ctx.beginPath();
ctx.rect(
this.sprite.x,
this.sprite.y,
this.sprite.width * this.scale,
this.sprite.height * this.scale
);
ctx.stroke();
}

update() {
Expand Down Expand Up @@ -140,4 +159,11 @@ export class Player {
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.rope[index].removeLink();
};

listenForGameEvents() {
on(GOAL_COLLISION, this.onGoalCollision);
}
onGoalCollision = () => {
this.hasWon = true;
};
}
Binary file added src/assets/img/death.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/gameEvents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const GOAL_COLLISION = 'gc';
8 changes: 4 additions & 4 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ export const isBoxCollision = (sprite1, sprite2) => {
// TODO (johnedvard) also incorporate anchor
if (!sprite1 || !sprite2) return false;
return (
sprite1.x < sprite2.x + sprite2.width * sprite2.scaleX &&
sprite1.x + sprite1.width * sprite1.scaleX > sprite2.x &&
sprite1.y < sprite2.y + sprite2.height * sprite2.scaleY &&
sprite1.height * sprite1.scaleY + sprite1.y > sprite2.y
sprite1.x < sprite2.x + sprite2.width &&
sprite1.x + sprite1.width > sprite2.x &&
sprite1.y < sprite2.y + sprite2.height &&
sprite1.height + sprite1.y > sprite2.y
);
};
export const lineIntersection = (p1, p2, p3, p4) => {
Expand Down

0 comments on commit 3b0c4da

Please sign in to comment.