From 40fdf7b37c9db476a4b754dcc67da6025d105be4 Mon Sep 17 00:00:00 2001 From: John Edvard Reiten Date: Thu, 18 Aug 2022 00:18:49 +0900 Subject: [PATCH] feat: Add sawblade --- src/Game.js | 27 +++++++++++++++++ src/Player.js | 8 ++--- src/PlayerControls.js | 2 +- src/Saw.js | 65 +++++++++++++++++++++++++++++++++++++++++ src/assets/img/saw.png | Bin 0 -> 161 bytes src/assetsUtils.js | 3 +- src/sawBehavior.js | 2 ++ src/utils.js | 14 +++++++++ 8 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 src/Saw.js create mode 100644 src/assets/img/saw.png create mode 100644 src/sawBehavior.js diff --git a/src/Game.js b/src/Game.js index b4c003d..04b774c 100644 --- a/src/Game.js +++ b/src/Game.js @@ -1,10 +1,14 @@ import { init, initPointer, initInput, GameLoop, onPointer } from 'kontra'; import { Player } from './Player'; +import { Saw } from './Saw'; +import { lineIntersection } from './utils'; +import { BACK_FORTH } from './sawBehavior'; export class Game { canvas; context; player; + saw; constructor() { const game = this; let { canvas, context } = init(); @@ -13,13 +17,17 @@ export class Game { initPointer(); initInput(); this.createPlayer(); + this.createSaw(); let loop = GameLoop({ update: function () { game.player.update(); + game.saw.update(); + game.checkCollisions(); }, render: function () { game.player.render(context); + game.saw.render(context); }, }); loop.start(); // start the game @@ -29,6 +37,25 @@ export class Game { createPlayer() { this.player = new Player(40, 40, this); } + createSaw() { + this.saw = new Saw(100, 200, { behavior: BACK_FORTH }); + } + checkCollisions() { + const rope = this.player.rope; + for (let i = 0; i < rope.length - 2; i++) { + if ( + lineIntersection( + { x: this.saw.x - 1, y: this.saw.y }, + { x: this.saw.x + 1, y: this.saw.y }, + { x: rope[i].x, y: rope[i].y }, + { x: rope[i + 1].x, y: rope[i + 1].y } + ) + ) { + console.log('intersection happened at index: ', i); + this.player.cutRope(i); + } + } + } addPointerListeners() { onPointer('down', () => { diff --git a/src/Player.js b/src/Player.js index 7803a47..e74f0ee 100644 --- a/src/Player.js +++ b/src/Player.js @@ -53,8 +53,8 @@ export class Player { }; image.onload = () => { this.sprite = Sprite({ - x: 8, - y: 8, + x: this.x, + y: this.y, anchor: { x: 0.5, y: 0.5 }, image: image, scaleX: 2, @@ -119,8 +119,8 @@ export class Player { this.playerControls.updateControls(); } - cutRope = (e) => { - this.rope[2].removeLink(); + cutRope = (index) => { + this.rope[index].removeLink(); }; toggleRope = (e) => { // TODO (johnedvard) Maybe use state machine diff --git a/src/PlayerControls.js b/src/PlayerControls.js index 2dcb077..7da6200 100644 --- a/src/PlayerControls.js +++ b/src/PlayerControls.js @@ -21,6 +21,6 @@ export class PlayerControls { initControls() { onInput(['space'], this.player.toggleRope); - onInput(['c'], this.player.cutRope); + onInput(['c'], () => this.player.cutRope(3)); } } diff --git a/src/Saw.js b/src/Saw.js new file mode 100644 index 0000000..e1de3a4 --- /dev/null +++ b/src/Saw.js @@ -0,0 +1,65 @@ +import saw from './assets/img/saw.png'; +import { Sprite } from 'kontra'; +import { BACK_FORTH, UP_DOWN } from './sawBehavior'; + +export class Saw { + x; + y; + orgX; + orgY; + sprite = { render: () => {} }; + distance = 100; + speed = 1; + + constructor(x, y, { behavior, distance }) { + this.x = x; + this.y = y; + this.orgX = x; + this.orgY = y; + this.distance = distance; + this.behavior = behavior; + this.createSprite(); + } + + update() { + this.moveDistance(this.behavior, this.distance); + this.sprite.rotation += 5; + } + moveDistance(behavior, distance) { + let axis = 'x'; + switch (behavior) { + case UP_DOWN: + axis = 'y'; + break; + case BACK_FORTH: + axis = 'x'; + break; + default: + axis = 'x'; + } + + this[axis] += this.speed; + this.sprite.x = this.x; + this.sprite.y = this.y; + } + render(_ctx) { + this.sprite.render(); + } + createSprite() { + const image = new Image(); + image.src = saw; + image.onerror = function (err) { + console.log(err); + }; + image.onload = () => { + this.sprite = Sprite({ + x: this.x, + y: this.y, + anchor: { x: 0.5, y: 0.5 }, + image: image, + scaleX: 2, + scaleY: 2, + }); + }; + } +} diff --git a/src/assets/img/saw.png b/src/assets/img/saw.png new file mode 100644 index 0000000000000000000000000000000000000000..77a746ecad8edaacf16195438418b1e7e2e461f1 GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqjKx9jP7LeL$-D$|qCH(4LnNjq zCpa+a-{1f9d;^=rMAhy2bIuPIauCka)1^-T$s4uK%J>MgHkWT=*-0)Fj2T z#MS4 { - load(skull, chain) + load(skull, chain, saw) .then(function (assets) { console.log('assets loaded'); // all assets have loaded diff --git a/src/sawBehavior.js b/src/sawBehavior.js new file mode 100644 index 0000000..b7a983a --- /dev/null +++ b/src/sawBehavior.js @@ -0,0 +1,2 @@ +export const BACK_FORTH = 0; +export const UP_DOWN = 1; diff --git a/src/utils.js b/src/utils.js index 2df9005..4174393 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,3 +1,17 @@ +import { Vector } from 'kontra'; + export const scaleToFit = () => { // TODO (johnedvard) listen for window resize, debounce, and scale to fit mac height and width whilst keeping aspect ratio }; +export const lineIntersection = (p1, p2, p3, p4) => { + const d = (p2.x - p1.x) * (p4.y - p3.y) - (p2.y - p1.y) * (p4.x - p3.x); + if (d == 0) return null; // parallel lines + const u = ((p3.x - p1.x) * (p4.y - p3.y) - (p3.y - p1.y) * (p4.x - p3.x)) / d; + const v = ((p3.x - p1.x) * (p2.y - p1.y) - (p3.y - p1.y) * (p2.x - p1.x)) / d; + if (u < 0.0 || u > 1.0) return null; // intersection point not between p1 and p2 + if (v < 0.0 || v > 1.0) return null; // intersection point not between p3 and p4 + const intersectionX = p1.x + u * (p2.x - p1.x); + const intersectionY = p1.y + u * (p2.y - p1.y); + let intersection = Vector(intersectionX, intersectionY); + return intersection; +};