Compare commits

..

3 commits

Author SHA1 Message Date
lagaffe
5cb4c299a3 add TimedGame class, integrate it to smartmonday game 2026-04-26 00:55:27 +02:00
lagaffe
108fcf3d31 add start and reset method to each game 2026-04-25 17:25:28 +02:00
lagaffe
6220f44cf0 drag and drop brings dragged element to front 2026-04-24 19:46:36 +02:00
9 changed files with 128 additions and 39 deletions

View file

@ -1,3 +1,10 @@
import { Container } from "pixi.js";
let maxZIndex = 0; // heretic method to bring dragged sprite to the front,
// will technically overflow if you play long enough,
// it is also shitty because if you externally use zIndex on the sprites in the same container, it may not bring to front
// clean solution would be to make a draggable container class
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;
@ -43,6 +50,7 @@ function onDragStart(node, onDrop, event) {
node.on("pointerupoutside", () => onDragEnd(node, onDrop));
node.parent.eventMode =
node.parent.eventMode == "dynamic" ? "dynamic" : "static";
node.zIndex = ++maxZIndex;
const dragShift = node.parent.toLocal(event.global.clone(), null);
dragShift.x -= node.x;
dragShift.y -= node.y;

View file

@ -10,6 +10,9 @@ export class CleanupHS extends Game {
this._elementCount = this._difficulty * 6;
this._elementsPlaced = 0;
this._items = [];
this._scree_w = width;
this._scree_h = height;
this.gameContainer.layout = {
width: "100%",
@ -31,6 +34,18 @@ export class CleanupHS extends Game {
trashcan.layout = { objectFit: "contain" };
shelf.layout = { objectFit: "contain" };
this.gameContainer.addChild(this.trashLandingZone);
this.gameContainer.addChild(this.shelfLandingZone);
}
start() {
super.start();
}
reset() {
super.reset();
this._elementsPlaced = 0;
this._items = [];
for (let i = 0; i < this._elementCount; i++) {
@ -46,7 +61,7 @@ export class CleanupHS extends Game {
this._items.push(item);
// non dynamic sizes for now
const w = width * 0.04;
const w = this._scree_w * 0.04;
item.sprite.width = w;
item.sprite.height = w;
makeDragable(item.sprite, (node) => {
@ -54,13 +69,8 @@ export class CleanupHS extends Game {
});
this.gameContainer.addChild(item.sprite);
}
this.gameContainer.addChild(this.trashLandingZone);
this.gameContainer.addChild(this.shelfLandingZone);
}
reset() {}
_onItemDrop(item) {
console.log("dropped", item.type);

View file

@ -48,13 +48,13 @@ export class Fridge extends Game {
this.gameContainer.addChild(fridgeContainer);
this.gameContainer.addChild(bottleContainer);
const bottles = [];
this.bottles = [];
this._dropZones = [];
const widthPercent = 0.12;
this.gameContainer.on("layout", (event) => {
const layoutBox = event.computedLayout;
for (const bottle of bottles) {
for (const bottle of this.bottles) {
const width = layoutBox.width * widthPercent;
bottle.width = width;
bottle.height = width; // aspectRatio = 1
@ -95,14 +95,27 @@ export class Fridge extends Game {
}
});
this.gameContainer.addChild(newBottle);
bottles.push(newBottle);
newBottle.x = 800;
newBottle.y = 0;
this.bottles.push(newBottle);
}
}
reset() {}
reset() {
super.reset();
this._bottlePlaced = 0;
for (const zone of this._dropZones) {
zone.full = false;
}
for (const bottle of this.bottles) {
bottle.x = 800;
bottle.y = 0;
}
}
start() {
super.start();
}
_onBottleDrop(bottle) {
console.log("dropped at", bottle.position);

View file

@ -9,11 +9,19 @@ export class Game {
}
/* should reset the game to its initial position*/
reset() {}
reset() {
this.won = false;
}
_win() {
this.win = true;
console.log("game won");
/* start the game */
start() {
this.reset();
}
/* status indicates if its a win or a loss */
end(status) {
this.win = status;
console.log(status ? "game won" : "game lost");
// we probably want to call a callback here
}
}

View file

@ -2,3 +2,4 @@ export { Fridge } from "./fridge.js";
export { Opinator } from "./opinator.js";
export { SmartMonday } from "./smartMonday.js";
export { CleanupHS } from "./cleanupHS.js";
export { TimedGame } from "./timedGame.js";

View file

@ -1,5 +1,4 @@
import { Application, Assets, Container, Sprite } from "pixi.js";
import { backgroundLayout } from "../common";
import { Game } from "./game";
export class Opinator extends Game {
@ -8,33 +7,31 @@ export class Opinator extends Game {
this._inMove = false; // indicates if player has grabed the wire (is mouse down)
this._currentScore = 0;
this._pixelGoalScore = undefined;
this._goalScore = 10 * this._difficulty; // goal to match, measured in play area, 10 = moving the mouse on the equivalent of 10 play areas
this._goalScore = 8 * this._difficulty; // goal to match, measured in play area, 10 = moving the mouse on the equivalent of 10 play areas
this._lastMousePos = undefined; // use to compute the travelled distance
const backgroundSprite = Sprite.from("opinator");
this._backgroundSprite = Sprite.from("opinator");
this._pixelGoalScore = backgroundSprite.width * this._goalScore; // beware of resize mid game
this._backgroundSprite.eventMode = "static";
backgroundSprite.eventMode = "static";
backgroundSprite.on("pointerdown", (event) => {
this._backgroundSprite.on("pointerdown", (event) => {
console.log("Opinator grabbed");
this._inMove = true;
this._lastMousePos = event.client.clone();
});
backgroundSprite.on("pointerupoutside", () => {
this._backgroundSprite.on("pointerupoutside", () => {
console.log("Opinator released");
this._inMove = false;
this._lastMousePos = undefined;
});
backgroundSprite.on("pointerup", () => {
this._backgroundSprite.on("pointerup", () => {
console.log("Opinator released");
this._inMove = false;
this._lastMousePos = undefined;
});
backgroundSprite.on("mousemove", (event) => {
this._backgroundSprite.on("mousemove", (event) => {
if (this._inMove && !this.won) {
const newMousePos = event.client;
const progress = Math.sqrt(
@ -56,10 +53,18 @@ export class Opinator extends Game {
} //else ignore, not enough move to get some distance
}
});
backgroundSprite.layout = { objectFit: "contain" };
this._backgroundSprite.layout = { objectFit: "contain" };
this.gameContainer.layout = { width: "100%", height: "100%" };
this.gameContainer.addChild(backgroundSprite);
this.gameContainer.addChild(this._backgroundSprite);
}
reset() {}
reset() {
super.reset();
this._currentScore = 0;
this._pixelGoalScore = this._backgroundSprite.width * this._goalScore; // beware of resize mid game
}
start() {
super.start();
}
}

View file

@ -1,22 +1,36 @@
import { Application, Assets, Container, Sprite, Rectangle } from "pixi.js";
import { Game } from "./game";
import { TimedGame } from "./timedGame";
import { KeyBoardListener } from "../common";
export class SmartMonday extends Game {
export class SmartMonday extends TimedGame {
constructor() {
super();
super(10000); // 10 chars per second
this._goal = 100 * this._difficulty; // number of characters
this._currentString = "";
this.timeout = 1000 * (this._goal / 10); // 10 chars per second
const handle = KeyBoardListener.onKeyDown((event) => {
this._currentString = "";
this._keyEventHandle = undefined;
}
reset() {
super.reset();
this._currentString = "";
}
start() {
super.start();
this._keyEventHandle = KeyBoardListener.onKeyDown((event) => {
this._currentString += event.key;
console.log("current text", this._currentString);
if (this._currentString.length >= this._goal) {
this._win();
this.end(true);
}
});
}
reset() {}
end(status) {
super.end(status);
KeyBoardListener.offKeyDown(this._keyEventHandle);
}
}

28
src/games/timedGame.js Normal file
View file

@ -0,0 +1,28 @@
import { Game } from "./game";
export class TimedGame extends Game {
constructor(time) {
super();
this._timeoutId = undefined;
this.timeout = time;
}
start() {
super.start();
this._timeoutId = setInterval(() => {
console.log("time end");
this.end(this._win);
}, this.timeout);
}
reset() {
super.reset();
clearTimeout(this._timeoutId);
this._timeoutId = undefined;
}
end(status) {
super.end(status);
clearTimeout(this._timeoutId);
}
}

View file

@ -102,8 +102,10 @@ function switchToGame(gameContainer, newGame) {
const cleanupHS = new CleanupHS(root.width, root.height);
//gameContainter.addChild(fridge.gameContainer);
//gameContainter.addChild(opinator.gameContainer);
//gameContainter.addChild(smartMonday.gameContainer);
gameContainter.addChild(cleanupHS.gameContainer);
gameContainter.addChild(smartMonday.gameContainer);
//gameContainter.addChild(cleanupHS.gameContainer);
root.addChild(gameContainter);
smartMonday.start();
})();