diff --git a/readme.md b/readme.md index d9c49b9..9c2d946 100644 --- a/readme.md +++ b/readme.md @@ -8,6 +8,7 @@ run rundev.sh, the site will be available at http://localhost:5173/ and you shou #### to deploy run run.sh, it build the production image and starts a container +#### notes I tried to make a clean setup, so 2 docker files, one for quick tests during dev the other for production. It is not possible to merge the two dockerfiles because the dev one needs a bind volume to update code from host which we dont want in production diff --git a/src/assets/img/arduino.jpg b/src/assets/img/arduino.jpg new file mode 100644 index 0000000..72d1a93 Binary files /dev/null and b/src/assets/img/arduino.jpg differ diff --git a/src/assets/img/empty_monster.jpg b/src/assets/img/empty_monster.jpg new file mode 100644 index 0000000..4812879 Binary files /dev/null and b/src/assets/img/empty_monster.jpg differ diff --git a/src/assets/img/shelf.avif b/src/assets/img/shelf.avif new file mode 100644 index 0000000..73ce793 Binary files /dev/null and b/src/assets/img/shelf.avif differ diff --git a/src/assets/img/trashcan.png b/src/assets/img/trashcan.png new file mode 100644 index 0000000..e1b485c Binary files /dev/null and b/src/assets/img/trashcan.png differ diff --git a/src/common/dragAndDrop.js b/src/common/dragAndDrop.js index 2e7f125..31ac7ad 100644 --- a/src/common/dragAndDrop.js +++ b/src/common/dragAndDrop.js @@ -1,6 +1,7 @@ function onDragMove(node, event, shift = { x: 0, y: 0 }) { // shift is a tuple representing the shift between the coords of the node and the pointer const dragPoint = event.global; + dragPoint.x -= shift.x; dragPoint.y -= shift.y; const parent = node.parent; @@ -32,7 +33,7 @@ function onDragMove(node, event, shift = { x: 0, y: 0 }) { function onDragEnd(node, onDrop) { node.off("pointerup"); node.off("pointerupoutside"); - node.parent.off("mousemove"); + node.off("globalpointermove"); onDrop(node); } @@ -42,10 +43,10 @@ function onDragStart(node, onDrop, event) { node.on("pointerupoutside", () => onDragEnd(node, onDrop)); node.parent.eventMode = node.parent.eventMode == "dynamic" ? "dynamic" : "static"; - const dragShift = node.parent.toLocal(event.global, null); + const dragShift = node.parent.toLocal(event.global.clone(), null); dragShift.x -= node.x; dragShift.y -= node.y; - node.parent.on("mousemove", (event) => { + node.on("globalpointermove", (event) => { onDragMove(node, event, dragShift); }); } diff --git a/src/games/cleanupHS.js b/src/games/cleanupHS.js new file mode 100644 index 0000000..68371bf --- /dev/null +++ b/src/games/cleanupHS.js @@ -0,0 +1,111 @@ +import { Application, Assets, Container, Sprite, Rectangle } from "pixi.js"; +import { Game } from "./game"; +import { KeyBoardListener, makeDragable, getIntersection } from "../common"; + +const itemTypes = { TRASH: "TRASH", HARDWARE: "HARDWARE" }; + +export class CleanupHS extends Game { + constructor(width, height) { + super(); + + this._elementCount = this._difficulty * 6; + this._elementsPlaced = 0; + + this.gameContainer.layout = { + width: "100%", + height: "100%", + justifyContent: "space-between", + }; + const trashcan = Sprite.from("trashcan"); + const shelf = Sprite.from("shelf"); + this.trashLandingZone = new Container(); + this.shelfLandingZone = new Container(); + this.trashLandingZone.addChild(trashcan); + this.shelfLandingZone.addChild(shelf); + + this.trashLandingZone.layout = { width: "20%", height: "100%" }; + this.shelfLandingZone.layout = { + width: "20%", + height: "100%", + }; + trashcan.layout = { objectFit: "contain" }; + shelf.layout = { objectFit: "contain" }; + + this._items = []; + + for (let i = 0; i < this._elementCount; i++) { + const item = {}; + if (Math.random() > 0.5) { + item.type = itemTypes.TRASH; + item.sprite = Sprite.from("trash"); + } else { + item.type = itemTypes.HARDWARE; + item.sprite = Sprite.from("arduino"); + } + + this._items.push(item); + + // non dynamic sizes for now + const w = width * 0.04; + item.sprite.width = w; + item.sprite.height = w; + makeDragable(item.sprite, (node) => { + this._onItemDrop(item); + }); + this.gameContainer.addChild(item.sprite); + } + + this.gameContainer.addChild(this.trashLandingZone); + this.gameContainer.addChild(this.shelfLandingZone); + } + + reset() {} + + _onItemDrop(item) { + console.log("dropped", item.type); + + const intersection = new Rectangle(); + const overlapGreaterThan = (threshold, rect1, rect2) => { + getIntersection(rect1, rect2, intersection); + const intersectArea = intersection.width * intersection.height; + const rect1Area = rect1.width * rect1.height; + return intersectArea > threshold * rect1Area; + }; + + if ( + overlapGreaterThan( + 0.6, + item.sprite.getBounds(), + this.trashLandingZone.getBounds(), + ) + ) { + if (item.type != itemTypes.TRASH) { + this._onError(); + } + this._elementsPlaced++; + this.gameContainer.removeChild(item.sprite); + } else if ( + overlapGreaterThan( + 0.6, + item.sprite.getBounds(), + this.shelfLandingZone.getBounds(), + ) + ) { + if (item.type != itemTypes.HARDWARE) { + this._onError(); + } + this._elementsPlaced++; + this.gameContainer.removeChild(item.sprite); + } + + if (this._elementsPlaced >= this._elementCount) { + this._win(); + } + } + + _onError() { + console.log("wrong placement"); + // apply penalty for putting item in the wrong place + //probably a time loss + } +} diff --git a/src/games/index.js b/src/games/index.js index 51d25bb..3d26666 100644 --- a/src/games/index.js +++ b/src/games/index.js @@ -1,3 +1,4 @@ export { Fridge } from "./fridge.js"; export { Opinator } from "./opinator.js"; export { SmartMonday } from "./smartMonday.js"; +export { CleanupHS } from "./cleanupHS.js"; diff --git a/src/main.js b/src/main.js index 3a0718f..dbfe85b 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,6 @@ import "@pixi/layout"; import { Application, Assets, Container, Sprite } from "pixi.js"; -import { Fridge, Opinator, SmartMonday } from "./games"; +import { Fridge, Opinator, SmartMonday, CleanupHS } from "./games"; import { backgroundLayout, KeyBoardListener } from "./common"; const app = new Application(); @@ -51,6 +51,22 @@ async function preload() { alias: "mate_caisse", src: "assets/img/caisse.jpg", }, + { + alias: "trash", + src: "assets/img/empty_monster.jpg", + }, + { + alias: "trashcan", + src: "assets/img/trashcan.png", + }, + { + alias: "arduino", + src: "assets/img/arduino.jpg", + }, + { + alias: "shelf", + src: "assets/img/shelf.avif", + }, ]; await Assets.load(assets); @@ -83,9 +99,11 @@ function switchToGame(gameContainer, newGame) { const opinator = new Opinator(); const fridge = new Fridge(); const smartMonday = new SmartMonday(); + const cleanupHS = new CleanupHS(root.width, root.height); //gameContainter.addChild(fridge.gameContainer); - gameContainter.addChild(opinator.gameContainer); - gameContainter.addChild(smartMonday.gameContainer); + //gameContainter.addChild(opinator.gameContainer); + //gameContainter.addChild(smartMonday.gameContainer); + gameContainter.addChild(cleanupHS.gameContainer); root.addChild(gameContainter); })();