summaryrefslogtreecommitdiff
path: root/2026/games/cammymoop/js
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2026-08-26 23:47:59 -0400
committerLLLL Colonq <llll@colonq>2026-08-26 23:47:59 -0400
commit0d2d8cd897e94bd94e0b3ae7c6ce9aa580a44a0a (patch)
treee9039d1c3aedca515d6cb499451d4b73aca4f5fd /2026/games/cammymoop/js
parent242943e5b023ce40eb3be826c418a478d4672f78 (diff)
Add a_tension_span
Diffstat (limited to '2026/games/cammymoop/js')
-rw-r--r--2026/games/cammymoop/js/dice_game.js622
-rw-r--r--2026/games/cammymoop/js/goblin.js521
-rw-r--r--2026/games/cammymoop/js/hints.js83
-rw-r--r--2026/games/cammymoop/js/micro.js158
-rw-r--r--2026/games/cammymoop/js/stopwatch.js59
5 files changed, 0 insertions, 1443 deletions
diff --git a/2026/games/cammymoop/js/dice_game.js b/2026/games/cammymoop/js/dice_game.js
deleted file mode 100644
index 2810872..0000000
--- a/2026/games/cammymoop/js/dice_game.js
+++ /dev/null
@@ -1,622 +0,0 @@
-
-function randOffset(size) {
- return Math.round((Math.random() - 0.5) * 2 * size);
-}
-
-function smoothRandOffset(size) {
- return (Math.random() - 0.5) * 2 * size;
-}
-
-M.Ease = Phaser.Math.Easing;
-
-const ROLL_TOTAL = 290;
-const ROLL_ONCE = 60;
-
-const battles = [
- // difficulty tier 0
- [
- [3, "Goblin", "Goblin"],
- [2, "BombGnome", "Goblin"],
- [2, "BombGnome", "BombGnome"],
- ],
- // difficulty tier 1
- [
- [3, "Goblin", "Goblin", "BombGnome"],
- [2, "Goblin", "Goblin"],
- [1, "Goblin"],
- [4, "ShieldGoblin"],
- ],
- // difficulty tier 2
- [
- [4, "ShieldGoblin", "ShieldGoblin"],
- [7, "Goblin", "Goblin", "Goblin", "Goblin"],
- [3, "ShieldGoblin", "BombGnome"],
- [3, "Goblin", "BombGnome", "Goblin", "Goblin"],
- [1, "BombGnome", "BombGnome", "BombGnome", "Goblin"],
- ],
- // difficulty tier 3
- [
- [2, "ShieldGoblin", "BombGnome"],
- [3, "ShieldGoblin", "BombGnome", "BombGnome", "ShieldGoblin"],
- [7, "Goblin", "Goblin", "Goblin", "ShieldGoblin", "Goblin"],
- [7, "ShieldGoblin", "ShieldGoblin", "ShieldGoblin"],
- ],
- // difficulty tier 4
- [
- [3, "ShieldGoblin", "Goblin", "BombGnome"],
- [6, "Goblin", "Goblin", "Goblin", "ShieldGoblin", "Goblin"],
- [7, "ShieldGoblin", "ShieldGoblin", "ShieldGoblin"],
- ],
- // difficulty tier 5
- [
- [10, "ShieldGoblin", "ShieldGoblin", "ShieldGoblin", "ShieldGoblin", "ShieldGoblin"],
- [8, "ShieldGoblin", "ShieldGoblin", "ShieldGoblin", "ShieldGoblin", "BombGnome"],
- ],
-
-];
-const maxTier = battles.length - 1;
-
-const battleBags = [[],[],[],[],[], []];
-
-const timerTimes = [12, 14, 16, 14, 10, 14];
-
-function arrShuffle(inArr) {
- return inArr.map((v) => ({v: v, r: Math.random()})).sort((a, b) => a.r - b.r).map(({v}) => v);
-}
-
-function getBattle(tier) {
- tier = Math.min(battles.length - 1, tier);
- if (battleBags[tier].length < 1) {
- battleBags[tier] = arrShuffle([...battles[tier]]);
- }
- return [...battleBags[tier].pop()];
-}
-
-const enemyTypes = {
- "Goblin": (s) => new M.Goblin(s),
- "ShieldGoblin": (s) => new M.Goblin(s, true),
- "BombGnome": (s) => new M.BombGnome(s),
-};
-
-M.DiceGame = class extends Phaser.Scene
-{
- create(data)
- {
- this.finished = false;
- this.victory = false;
- this.usedGrace = false;
-
- this.difficultyVal = data.difficulty;
- this.tier = Math.min(maxTier, Math.max(0, Math.floor(this.difficultyVal * 0.2)));
-
- this.battle = getBattle(this.tier);
- this.timeLimit = timerTimes[Math.min(timerTimes.length - 1, this.tier)]
- // make it a bit easier for now
- this.timeLimit = Math.ceil(this.timeLimit * 1.4);
-
- console.log("STARTED!!!!!!!!!!!!!!!!");
- M.gameStarted();
-
- this.diceIsActive = false;
-
- this.justClickedLMB = false;
- this.LMBWasClicked = false;
-
- this.bg = this.add.image(-30, -22, 'background').setOrigin(0, 0);
-
- this.stopwatch = new M.Stopwatch(this, this.timeLimit, new M.Vec2(26, 26));
- this.stopwatch.depth = 5;
-
- this.circle = this.add.image(-6000, 0, "red_circle");
- this.targetArrow = this.add.image(-6000, 0, "target_arrow");
- this.targetArrow.setOrigin(1, 0.5);
- this.targetArrow.depth = 2;
-
- this.allEnemies = [];
-
- const enemySpacing = 50;
- const enemyYOffset = -12;
- const startOffset = ((this.battle.length - 2) / 2) * enemySpacing;
- for (let i = 1; i < this.battle.length; i++) {
- const newEnemy = enemyTypes[this.battle[i]](this);
- const xOffset = ((i - 1) * enemySpacing) - startOffset;
- newEnemy.setHomePos(this.screenCenterPos().add(new M.Vec2(
- xOffset, enemyYOffset + ((i % 2) * 6)
- )));
- newEnemy.addToDisplayUpdate();
- this.allEnemies.push(newEnemy);
- }
-
- this.reroll = this.add.image(220, 132, "reroll");
- this.reroll.depth = 1;
-
- this.numDice = this.battle[0];
- this.allDice = [];
- this.rollDice(this.numDice);
- }
-
- screenCenterPos() {
- const h_center = this.game.scale.gameSize.width / 2;
- const v_center = this.game.scale.gameSize.height / 2;
- return new M.Vec2(h_center, v_center);
- }
-
- update(t, dt) {
- let pickableDice = 0;
- for (let dice of this.allDice) {
- if (dice.throwing) {
- this.updateThrownDice(dice, dt);
- } else if (dice.rolling) {
- dice.roll_timer += dt;
- dice.roll_anim_timer += dt;
-
- if (dice.roll_anim_timer > ROLL_ONCE) {
- dice.roll_anim_timer = 0;
- let rand_side = Math.floor(Math.random() * 5);
- let cur_side = parseInt(dice.frame.name);
- if (rand_side >= cur_side) {
- rand_side += 1;
- }
- dice.setFrame(rand_side);
- }
-
- const progress = dice.roll_timer / dice.total_roll_time;
-
- const elevation = Math.sin(progress * Math.PI) * 38;
- const rollVec = dice.roll_target_pos.clone().subtract(dice.roll_from_pos);
- dice.setPosVec(dice.roll_from_pos);
- dice.addPosVec(rollVec.scale(progress));
- dice.addPosVec(M.Vec2.UP.clone().scale(elevation));
-
- if (dice.roll_timer >= dice.total_roll_time) {
- this.sound.play('land_sfx');
- dice.total_roll_time = ROLL_TOTAL;
- dice.rolling = false;
- pickableDice += 1;
- dice.setPosVec(dice.roll_target_pos);
- this.setupRolledDice(dice);
- }
- } else {
- pickableDice += 1;
- }
- }
-
- const activePointer = this.input.activePointer;
- activePointer.updateWorldPoint(this.cameras.default);
- const pVec = new M.Vec2(activePointer.worldX, activePointer.worldY);
-
- const clicked = activePointer.primaryDown
- this.justClickedLMB = !this.LMBWasClicked && clicked
- this.LMBWasClicked = clicked
-
- let closestEnemy = null;
- let closestDice = null;
- let minDist = 0;
- for (let dice of this.allDice) {
- if (dice.rolling) {
- continue;
- }
- let pointerDist = pVec.distance(dice.getPosVec());
- if (pointerDist > 49 || (!dice.emphasis && pointerDist > 45)) {
- continue;
- } else if (!closestDice || pointerDist < minDist) {
- minDist = pointerDist;
- closestDice = dice;
- }
- }
- for (let enemy of this.allEnemies) {
- if (!enemy.alive) {
- continue;
- }
- let pointerDist = pVec.distance(enemy.getPosVec());
- if (pointerDist > 49) {
- continue;
- } else if (!closestEnemy || pointerDist < minDist) {
- minDist = pointerDist;
- closestEnemy = enemy;
- }
- }
-
- if (this.isOverReroll(pVec)) {
- closestDice = null;
- closestEnemy = null;
- if (this.justClickedLMB && pickableDice > 0) {
- this.rerollUnused();
- }
- }
-
- // If close enough to click dice or enemy and any dice is already selected, only consider enemy
- if (closestDice && closestEnemy && this.diceIsActive) {
- closestDice = null;
- }
-
- let clickedDice = false;
- this.changeEmphasisDice(closestDice);
- if (this.justClickedLMB) {
- if (closestDice && (!closestEnemy || !this.diceIsActive)) {
- clickedDice = true;
- this.changeActiveDice(closestDice);
- }
- }
- for (let enemy of this.allEnemies) {
- if (closestEnemy && enemy === closestEnemy) {
- enemy.showHint();
- } else {
- enemy.hideHint();
- }
- }
-
- if (closestEnemy && this.diceIsActive && !clickedDice) {
- const activeDice = this.getActiveDice();
- let diceToTargetVec = closestEnemy.getPosVec().subtract(activeDice.getPosVec());
-
- this.targetArrow.setPosVec(closestEnemy.getPosVec());
- this.targetArrow.rotation = diceToTargetVec.angle();
- if (this.justClickedLMB) {
- const activeDiceVal = this.getDiceVal(activeDice);
- this.throwDice(activeDice, closestEnemy);
- //closestEnemy.attack(activeDiceVal);
- //this.removeDice(activeDice);
- }
- } else {
- this.targetArrow.x = -6000
- }
-
- if (!this.finished) {
- let aliveEnemies = this.aliveEnemiesCount();
- if (aliveEnemies < 1) {
- this.nowFinished(true);
- } else if (this.unusedDiceNum() < 1) {
- this.nowFinished(false);
- }
- }
- }
-
- aliveEnemiesCount() {
- let aliveEnemies = 0;
- for (let e of this.allEnemies) {
- if (e.alive) {
- aliveEnemies += 1;
- }
- }
- return aliveEnemies;
- }
-
- aliveEnemyNames() {
- let names = [];
- for (let e of this.allEnemies) {
- if (e.alive) {
- names.push(e.enemyName);
- }
- }
- return names;
- }
-
- nowFinished(won, fromTimer = false) {
- if (this.finished) {
- return;
- }
- this.victory = won;
- if (!won) {
- battleBags[this.tier].push([...this.battle]);
- battleBags[this.teir] = arrShuffle(battleBags[this.tier]);
- }
- this.finished = true;
- const timeLeft = this.stopwatch.getTimeLeft();
-
- const waitForText = Math.min(timeLeft, 200);
- if (waitForText <= 0) {
- this.showEndText(won);
- } else {
- setTimeout( () => this.showEndText(won), waitForText);
- }
-
- if (fromTimer) {
- setTimeout(() => this.timeUp(), 300);
- } else {
- const continueDelay = Math.max(Math.min(2200, timeLeft), 300);
- setTimeout(() => this.timeUp(), continueDelay);
- }
- }
-
- showEndText(won) {
- const c = this.screenCenterPos();
- if (won) {
- this.add.image(c.x, c.y, "yes");
- } else {
- this.add.image(c.x, c.y, "ohno");
- }
- }
-
- getDiceVal(dice) {
- return parseInt(dice.frame.name) + 1;
- }
-
- setupRolledDice(dice) {
- dice.tint = 0xdddddd;
- dice.emphasis = false;
- dice.activeDice = false;
- if (this.stopwatch.getTimeLeft() < 3500 && !this.usedGrace) {
- this.grace(dice);
- }
- }
-
- grace(dice) {
- const unusedCount = this.unusedDiceNum();
- const enemyNames = this.aliveEnemyNames();
- let rolledNumbers = [];
- for (let otherDice of this.allDice) {
- if (otherDice === dice || otherDice.throwing) {
- continue;
- }
- rolledNumbers.push(this.getDiceVal(otherDice));
- }
- if (enemyNames.length < 1) {
- return;
- }
- if (enemyNames.includes("BombGnome")) {
- if (enemyNames.length > unusedCount) {
- this.usedGrace = true;
- this.setDiceTo(dice, 6);
- } else if (unusedCount === 1) {
- this.usedGrace = true;
- this.setDiceTo(dice, 2);
- }
- } else {
- if (enemyNames.includes("ShieldGoblin")) {
- this.usedGrace = true;
- this.setDiceTo(dice, 3);
- } else if (unusedCount === 1) {
- this.usedGrace = true;
- this.setDiceTo(dice, Math.floor(Math.random() * 4) + 3);
- } else if (unusedCount - rolledNumbers.length === 1) {
- let greaterThanTwo = false;
- for (let rolledNum of rolledNumbers) {
- if (rolledNum > 2) {
- greaterThanTwo = true;
- }
- }
- if (!greaterThanTwo) {
- this.usedGrace = true;
- this.setDiceTo(dice, 3);
- }
- }
- }
-
- if (this.usedGrace) {
- console.log("halleluyah");
- }
- }
-
- setDiceTo(dice, toNum) {
- dice.setFrame(toNum - 1);
- }
-
- throwDice(dice, atEnemy) {
- if (!atEnemy || !atEnemy.alive) {
- return;
- }
- if (dice.activeDice) {
- this.clearDiceActive(dice);
- }
- atEnemy.preattack(this.getDiceVal(dice));
- dice.throwing = true;
- dice.throwingAt = atEnemy;
- dice.throwFrom = dice.getPosVec();
- dice.throwTo = atEnemy.getPosVec();
- dice.throwTimer = 0;
- dice.throwTotalTime = 80;
- }
-
- updateThrownDice(dice, dt) {
- dice.throwTimer += dt;
- if (dice.throwTimer > dice.throwTotalTime) {
- this.finishThrownDice(dice);
- } else {
- const progress = dice.throwTimer / dice.throwTotalTime;
- dice.scale = Math.max(0.1, 1 - progress);
- const delta = dice.throwTo.clone().subtract(dice.throwFrom);
- dice.setPosVec(dice.throwFrom);
- dice.addPosVec(delta.scale(M.Ease.Cubic.Out(progress)));
- }
- }
-
- finishThrownDice(dice) {
- dice.throwingAt.attack(this.getDiceVal(dice));
- this.removeDice(dice);
- }
-
- removeDice(dice) {
- const diceIndex = this.allDice.indexOf(dice);
- if (diceIndex < 0) {
- return;
- }
- this.clearDiceActive(dice);
- this.allDice.splice(diceIndex, 1);
- dice.destroy();
- this.numDice = this.allDice.length;
- }
-
- setDiceEmphasis(dice) {
- if (dice.emphasis) {
- return;
- }
- dice.emphasis = true;
- dice.clearTint();
- dice.y -= 4;
- }
- clearDiceEmphasis(dice) {
- if (!dice.emphasis) {
- return;
- }
- dice.emphasis = false;
- dice.y += 4;
- if (!dice.activeDice) {
- dice.tint = 0xdddddd;
- }
- }
-
- isOverReroll(pointerPos) {
- const relPointer = pointerPos.clone().subtract(this.reroll.getPosVec());
- if (Math.abs(relPointer.x) * 2 > this.reroll.width) {
- return false;
- } else if (Math.abs(relPointer.y) * 2 > this.reroll.height) {
- return false;
- }
- return true;
- }
-
- setDiceActive(dice) {
- dice.activeDice = true;
- dice.clearTint();
- this.circle.setPosVec(dice.getPosVec());
- if (dice.emphasis) {
- this.circle.y += 4;
- }
- }
- clearDiceActive(dice) {
- dice.activeDice = false;
- this.circle.x = -6000;
- this.diceIsActive = false;
- }
-
- changeEmphasisDice(newEmphasis) {
- for (let dice of this.allDice) {
- if (dice === newEmphasis) {
- this.setDiceEmphasis(dice);
- } else if (dice.emphasis) {
- this.clearDiceEmphasis(dice);
- }
- }
- }
-
- changeActiveDice(newActiveDice) {
- for (let dice of this.allDice) {
- if (dice !== newActiveDice) {
- this.clearDiceActive(dice);
- }
- }
- this.diceIsActive = true;
- this.setDiceActive(newActiveDice);
- }
-
- enemyExploded(explodingEnemy) {
- this.sound.play('boom_sfx');
- const enemyIndex = this.allEnemies.indexOf(explodingEnemy);
- if (enemyIndex === -1) {
- console.log("exploding enemy not found in allEnemies");
- return;
- }
- if (enemyIndex > 0) {
- const leftEnemy = this.allEnemies[enemyIndex - 1];
- if (!leftEnemy.gone) {
- leftEnemy.attack(8);
- }
- }
- if (enemyIndex < this.allEnemies.length - 1) {
- const rightEnemy = this.allEnemies[enemyIndex + 1];
- if (!rightEnemy.gone) {
- rightEnemy.attack(8);
- }
- }
- }
-
- preExplode(explodingEnemy) {
- const enemyIndex = this.allEnemies.indexOf(explodingEnemy);
- if (enemyIndex === -1) {
- console.log("pre-exploding enemy not found in allEnemies");
- return;
- }
- if (enemyIndex > 0) {
- const leftEnemy = this.allEnemies[enemyIndex - 1];
- if (leftEnemy.alive) {
- leftEnemy.preattack(8);
- }
- }
- if (enemyIndex < this.allEnemies.length - 1) {
- const rightEnemy = this.allEnemies[enemyIndex + 1];
- if (rightEnemy.alive) {
- rightEnemy.preattack(8);
- }
- }
- }
-
- getActiveDice() {
- if (!this.diceIsActive || this.allDice.length === 0) {
- return null;
- }
- for (let dice of this.allDice) {
- if (dice.activeDice) {
- return dice;
- }
- }
- return null;
- }
-
- clearUnusedDice() {
- const oldDice = this.allDice;
- this.allDice = [];
- for (let dice of oldDice) {
- if (dice.throwing) {
- this.allDice.push(dice);
- continue;
- }
- if (dice.activeDice) {
- this.clearDiceActive(dice);
- }
- dice.destroy();
- }
- }
-
- unusedDiceNum() {
- let num = 0;
- for (let dice of this.allDice) {
- if (!dice.throwing) {
- num += 1;
- }
- }
- return num;
- }
-
- rerollUnused() {
- let unusedNum = this.unusedDiceNum();
- this.clearUnusedDice();
- this.rollDice(unusedNum);
- }
-
- rollDice(num) {
- this.sound.play('fwoof_sfx');
- let diceSpacing = 52;
- if (num > 1) {
- diceSpacing = Math.min(diceSpacing, Math.round(154 / (num - 1)));
- }
- const center = this.screenCenterPos();
- for (let i = 0; i < num; i++) {
- const xPos = Math.round(center.x - ((num - 1) * diceSpacing * 0.5) + (i * diceSpacing) - 10);
- const dice = this.add.sprite(xPos, center.y + 52, 'dices');
- this.allDice.push(dice);
-
- dice.addPosVec(new M.Vec2(randOffset(3), randOffset(11)));
- dice.roll_target_pos = dice.getPosVec();
- dice.addPosVec(new M.Vec2(randOffset(16), 30));
- dice.roll_from_pos = dice.getPosVec();
-
- dice.rolling = true;
- dice.roll_anim_timer = 0;
- dice.roll_timer = 0;
- dice.total_roll_time = ROLL_TOTAL + Math.random() * 400;
- }
- }
-
- timeUp() {
- let difficulty = this.difficultyVal
- if (battleBags[this.tier].length < 1) {
- difficulty += 1;
- M.gameDifficulty = difficulty
- }
- M.gameEnd(this.victory);
- this.scene.switch("wait");
- this.scene.stop();
- //this.scene.restart({difficulty: difficulty});
- }
-}
diff --git a/2026/games/cammymoop/js/goblin.js b/2026/games/cammymoop/js/goblin.js
deleted file mode 100644
index 2514cdf..0000000
--- a/2026/games/cammymoop/js/goblin.js
+++ /dev/null
@@ -1,521 +0,0 @@
-
-M.Enemy = class extends Phaser.GameObjects.Container
-{
- constructor(scene) {
- super(scene);
- this.sprites = {}
- this.spriteNames = [];
- this.homePos = M.Vec2.ZERO;
- this.hint = null;
- this.alive = true;
- this.gone = false;
- this.deathAnimating = false;
- }
-
- setHomePos(newHomePos) {
- this.setPosVec(newHomePos);
- this.homePos = new M.Vec2(newHomePos.x, newHomePos.y);
- }
-
- addToDisplayUpdate() {
- this.addToDisplayList();
- this.addToUpdateList();
- }
-
- setupHint(height, hintData) {
- this.addHintData(hintData);
- this.hint.y = -height;
- }
-
- addHintData(hintData) {
- if (this.hint) {
- this.remove(this.hint);
- this.hint.destroy();
- }
- this.hint = new M.Hint(this.scene);
- this.add(this.hint);
- this.hint.setup(hintData);
- }
-
- hideHint() {
- if (this.hint) {
- this.hint.visible = false;
- }
- }
-
- showHint() {
- if (this.hint) {
- this.hint.visible = true;
- }
- }
-
- removeSprite(spriteName) {
- if (!this.sprites[spriteName]) {
- return;
- }
- if (this.exists(this.sprites[spriteName])) {
- this.sprites[spriteName].destroy();
- this.remove(this.sprites[spriteName]);
- }
- const nameIndex = this.spriteNames.indexOf(spriteName);
- if (nameIndex >= 0) {
- this.spriteNames.splice(nameIndex, 1);
- }
- delete this.sprites[spriteName];
- }
-
- addSprite(spriteName, pos, textureKey, frameIdx) {
- if (!pos) {
- pos = {x: 0, y: 0};
- }
- if (this.sprites[spriteName]) {
- removeSprite(spriteName);
- }
- if (!this.spriteNames.includes(spriteName)) {
- this.spriteNames.push(spriteName);
- }
- const spr = new Phaser.GameObjects.Sprite(this.scene, pos.x, pos.y, textureKey, frameIdx);
- this.sprites[spriteName] = spr;
- this.add(spr);
- }
-
- tintSprites(newTint) {
- for (let spName of this.spriteNames) {
- this.sprites[spName].setTint(newTint);
- }
- }
-
- resetSpritesTint() {
- for (let spName of this.spriteNames) {
- this.sprites[spName].clearTint();
- }
- }
-
- preUpdate (t, dt) {
- super.preUpdate(t, dt);
- }
-
- attack(diceValue) {
- console.log("base enemy attacked: " + diceValue);
- }
-
-}
-
-M.Goblin = class extends M.Enemy
-{
- constructor(scene, withShield = false) {
- super(scene);
- this.baseAnimInterval = 160;
- this.anim_interval = this.baseAnimInterval;
- this.anim_timer = 0;
-
- this.current_animation = 1;
- this.anim_state = { side: -1 }
-
- this.head_shift = 1;
-
- this.dyingTint = Phaser.Display.Color.IntegerToColor(0x003300);
-
- this.addSprite("body", M.Vec2.ZERO, "gob_small", 0);
- this.addSprite("shield", M.Vec2.ZERO, "gob_small", 2);
- this.addSprite("head", M.Vec2.ZERO, "gob_small", 4);
-
- this.shieldBreaking = false;
- this.shielded = withShield;
- if (!this.shielded) {
- this.enemyName = "Goblin";
- this.sprites.shield.visible = false;
- } else {
- this.enemyName = "ShieldGoblin";
- }
-
- this.refreshHint();
- this.hideHint();
- }
-
- refreshHint() {
- if (this.shielded) {
- this.setupHint(20, [["less", "4", "", "arrow", "", "guard_break"]]);
- } else {
- this.setupHint(20, [["greater", "2", "", "arrow", "", "skull"]]);
- }
- }
-
- preUpdate (t, dt) {
-
- this.anim_timer += dt;
- this.animProcess(dt);
- if (this.anim_timer > this.anim_interval) {
- this.anim_timer = 0;
- this.animUpdate();
- }
- }
-
- changeAnim(animNumber) {
- this.current_animation = animNumber;
- this.resetAnim();
- }
-
- resetAnim() {
- this.sprites.head.y = 0;
- this.anim_interval = this.baseAnimInterval;
- switch (this.current_animation) {
- case 1:
- this.sprites.head.setFrame(4);
- this.sprites.body.setFrame(0);
- this.sendToBack(this.sprites.body);
- break;
- case 2:
- this.sprites.head.setFrame(5);
- this.sprites.head.scaleX = 1;
- this.sprites.head.x = 0;
- this.sprites.body.setFrame(1);
- this.bringToTop(this.sprites.body);
- this.anim_state.death_timer = 0;
- this.anim_state.death_total_time = 400;
- break;
- case 3: // laugh
- this.sprites.head.setFrame(4);
- this.sprites.head.x = 0;
- this.anim_interval = 60;
- this.anim_timer = 30;
- this.anim_state.anim_timer = 0;
- this.anim_state.anim_total_time = 600;
- break;
- case 4: // shield break
- this.sprites.head.setFrame(5);
- this.bringToTop(this.sprites.body);
- this.anim_state.anim_timer = 0;
- this.anim_state.anim_total_time = 280;
- break;
- }
- }
-
- animProcess (dt) {
- switch (this.current_animation) {
- case 2:
- this.anim_state.death_timer += dt;
- const progress = this.anim_state.death_timer / this.anim_state.death_total_time;
- const tintProgress = Math.min(1, progress * 2.2);
-
- let tintColor = this.dyingTint;
- if (tintProgress < 1) {
- const colorWhite = Phaser.Display.Color.IntegerToColor(0xffffff);
- tintColor = Phaser.Display.Color.Interpolate.ColorWithColor(
- colorWhite, this.dyingTint, 1, tintProgress
- );
- }
- this.tintSprites(tintColor.color);
-
- const scaleProgress = Math.max(0, (M.Ease.Cubic.In(progress) * 1.5) - 0.5);
- for (let spName of this.spriteNames) {
- this.sprites[spName].scaleY = 1 - scaleProgress;
- }
-
- if (progress >= 1) {
- this.finishDie();
- }
- break;
- case 3:
- this.anim_state.anim_timer += dt;
- if (this.anim_state.anim_timer > this.anim_state.anim_total_time) {
- this.changeAnim(1);
- }
- break;
- case 4:
- this.anim_state.anim_timer += dt;
- if (this.anim_state.anim_timer > this.anim_state.anim_total_time) {
- this.changeAnim(1);
- }
- break;
- }
- }
-
- animUpdate () {
- const head = this.sprites.head;
- switch (this.current_animation) {
- case 1:
- this.anim_state.side *= -1;
- head.x = this.head_shift * this.anim_state.side;
- if (Math.random() < 0.05) {
- head.scaleX *= -1;
- if (Math.random() < 0.7) {
- const pitchScale = Math.random() * 0.3 + 0.9
- this.scene.sound.play('gob2_sfx', {pitch: pitchScale});
- }
- }
- break;
- case 3:
- if (head.y === 0) {
- head.y = 1;
- } else {
- head.y = 0;
- }
- break;
- }
- }
-
- attack(diceValue) {
- if (this.shielded) {
- if (diceValue <= 3 || diceValue > 6) {
- this.scene.sound.play('crack_sfx');
- this.breakShield();
-
- if (Math.random() < 0.2) {
- this.scene.sound.play('gob_grunt_sfx');
- }
- } else {
- const laughNum = Math.floor(Math.random() * 2 + 1);
- this.scene.sound.play('laugh' + laughNum + '_sfx');
- this.changeAnim(3); // laugh
- }
- } else {
- if (diceValue <= 2) {
- const laughNum = Math.floor(Math.random() * 2 + 1);
- this.scene.sound.play('laugh' + laughNum + '_sfx');
- this.changeAnim(3); // laugh
- } else {
- this.scene.sound.play('punch_sfx');
- if (Math.random() < 0.75) {
- this.scene.sound.play('gob_grunt_sfx');
- } else {
- this.scene.sound.play('gob1_sfx');
- }
- this.startDie();
- }
- }
- }
-
- preattack(diceValue) {
- if (this.shielded && !this.shieldBreaking) {
- if (diceValue <= 3 || diceValue > 6) {
- this.shieldBreaking = true;
- }
- } else {
- if (diceValue > 2) {
- this.alive = false;
- }
- }
- }
-
- breakShield() {
- this.enemyName = "Goblin";
- this.shielded = false;
- this.sprites.shield.visible = false;
- this.refreshHint();
- this.changeAnim(4);
- }
-
- startDie() {
- this.alive = false;
- this.gone = true;
- this.deathAnimating = true;
- this.changeAnim(2);
- }
-
- finishDie() {
- this.deathAnimating = false;
- this.removeFromDisplayList();
- this.removeFromUpdateList();
- }
-}
-
-M.BombGnome = class extends M.Enemy
-{
- constructor(scene) {
- super(scene);
- this.enemyName = "BombGnome";
-
- this.anim_interval = 320;
- this.anim_timer = 0;
- this.total_time = 0;
-
- this.current_animation = 1;
- this.anim_state = {};
-
- this.arm_speed = 200 + Math.random() * 20;
- this.arm_angle_delta = (Math.PI / 6);
- this.snap = Math.PI / 64;
-
- this.addSprite("body", M.Vec2.ZERO, "bomb_gnome", 0);
- this.addSprite("arm", M.Vec2.ZERO, "bomb_gnome", 2);
- this.addSprite("bomb", M.Vec2.ZERO, "bomb_gnome", 4);
- this.addSprite("head", M.Vec2.ZERO, "bomb_gnome", 6);
-
- this.dyingTint = Phaser.Display.Color.IntegerToColor(0x330000);
-
- this.setupHint(26, [
- ["greater", "1", "", "arrow", "", "skull", ""],
- ["equal", "6", "", "arrow", "", "skull", "boom"],
- ]);
- this.hideHint();
- }
-
- preUpdate (t, dt) {
- this.total_time += dt;
- this.animProcess(dt);
-
- this.anim_timer += dt;
- if (this.anim_timer > this.anim_interval) {
- this.anim_timer = 0;
- this.animInterval();
- }
- }
-
- animProcess (dt) {
- let progress
- let tintProgress
- switch (this.current_animation) {
- case 1:
- const arm = this.sprites.arm
- const smoothAngle = this.arm_angle_delta * (
- Math.cos(this.total_time / this.arm_speed) / 2 - 0.5
- );
- arm.rotation = Math.round(smoothAngle / this.snap) * this.snap;
- break;
- case 2:
- this.anim_state.death_timer += dt;
- progress = this.anim_state.death_timer / this.anim_state.death_total_time;
-
- tintProgress = Math.min(1, progress * 2.2);
- this.setDeathTint(tintProgress);
-
- this.setDeathScale(progress, 0.5);
-
- if (progress >= 1) {
- this.finishDie();
- }
- break;
- case 3:
- this.anim_state.death_timer += dt;
- progress = this.anim_state.death_timer / this.anim_state.death_total_time;
-
- tintProgress = Math.min(1, progress * 4.2);
- this.setDeathTint(tintProgress);
-
- this.setDeathScale(progress, 1.2);
-
- const boomThreshold = 0.45;
- if (this.spriteNames.includes("boom")) {
- if (progress < boomThreshold) {
- const boomScaleProg = M.Ease.Back.Out(Math.min(1, progress * 3.0));
- this.sprites.boom.scale = 0.75 + boomScaleProg * 0.25
- } else {
- this.removeSprite("boom");
- }
- }
-
- if (progress >= 1) {
- this.finishDie();
- }
- break;
- }
- }
-
- setDeathTint(tintProgress) {
- let tintColor = this.dyingTint;
- if (tintProgress < 1) {
- const colorWhite = Phaser.Display.Color.IntegerToColor(0xffffff);
- tintColor = Phaser.Display.Color.Interpolate.ColorWithColor(
- colorWhite, this.dyingTint, 1, tintProgress
- );
- }
- this.tintSprites(tintColor.color);
- if (this.spriteNames.includes("boom")) {
- this.sprites.boom.clearTint();
- }
- }
-
- setDeathScale(deathProgress, shrinkOffset) {
- const clampedAdjusted = Math.max(0, Math.min(1, (deathProgress * (1 + shrinkOffset)) - 0.5))
- const scaleProgress = M.Ease.Cubic.In(clampedAdjusted);
- for (let spName of this.spriteNames) {
- this.sprites[spName].scaleY = 1 - scaleProgress;
- }
- }
-
- animInterval () {
- switch (this.current_animation) {
- case 1:
- const head = this.sprites.head;
- head.y = head.y > 0 ? 0 : 1;
- break;
- }
- }
-
- changeAnim(animNumber) {
- this.current_animation = animNumber;
- this.resetAnim();
- }
-
- resetAnim() {
- this.sprites.arm.rotation = 0;
- switch (this.current_animation) {
- case 1:
- this.sprites.body.setFrame(0);
- this.sprites.arm.setFrame(2);
- this.sprites.head.setFrame(6);
- break;
- case 2:
- this.sprites.body.setFrame(1);
- this.sprites.arm.setFrame(3);
- this.sprites.head.setFrame(7);
-
- this.anim_state.death_timer = 0;
- this.anim_state.death_total_time = 600;
- break;
- case 3:
- this.addSprite("boom", M.Vec2.ZERO, "explosion");
- this.sprites.boom.scale = 0.75;
-
- this.sprites.body.setFrame(1);
- this.sprites.arm.setFrame(3);
- this.sprites.bomb.visible = false;
- this.sprites.head.setFrame(7);
-
- this.anim_state.death_timer = 0;
- this.anim_state.death_total_time = 900;
- break;
- }
- }
-
- attack(diceValue) {
- if (diceValue <= 1) {
- this.scene.sound.play('hoo_sfx');
- } else if (diceValue >= 6) {
- this.startDie(true);
- } else {
- this.scene.sound.play('punch_sfx');
- this.startDie(false);
- }
- }
-
- preattack(diceValue) {
- if (diceValue > 1) {
- this.alive = false;
- if (diceValue >= 6) {
- this.scene.preExplode(this);
- }
- }
- }
-
- startDie(exploding) {
- this.alive = false;
- this.gone = true;
- this.deathAnimating = true;
- this.changeAnim(exploding ? 3 : 2);
- if (exploding) {
- setTimeout(() => this.scene.enemyExploded(this), 150);
- //this.scene.enemyExploded(this);
- } else {
- const gruntNum = Math.floor(Math.random() * 3 + 1);
- this.scene.sound.play('gnome_grunt' + gruntNum + '_sfx');
- }
- }
-
- finishDie() {
- this.deathAnimating = false;
- this.removeFromDisplayList();
- this.removeFromUpdateList();
- }
-}
diff --git a/2026/games/cammymoop/js/hints.js b/2026/games/cammymoop/js/hints.js
deleted file mode 100644
index 250c080..0000000
--- a/2026/games/cammymoop/js/hints.js
+++ /dev/null
@@ -1,83 +0,0 @@
-
-const nums = ['1', '2', '3', '4', '5', '6'];
-const shortNames = [];
-
-M.Hint = class extends Phaser.GameObjects.Container
-{
- constructor(scene) {
- super(scene);
- this.rows = [];
- this.allImgs = [];
- this.maxWidth = 0;
- }
-
- setupExample() {
- this.addToDisplayList();
- this.addRow(["equal", "5", "", "arrow", "", "skull", "dice"]);
- this.addRow(["greater", "2", "", "arrow", "", "skull"]);
- this.build();
- }
-
- setup(hintData) {
- this.addToDisplayList();
- this.rows = [];
- for (let row of hintData) {
- this.addRow(row);
- }
- this.build();
- }
-
- addRow(contents) {
- this.rows.push(contents);
- }
-
- clearRows() {
- this.rows = [];
- }
-
- clearImgs() {
- for (let img of this.allImgs) {
- img.destroy();
- }
- this.allImgs = [];
- }
-
- build() {
- this.clearImgs();
-
- for (let i = 0; i < this.rows.length; i++) {
- // Place rows in reverse order from bottom to top, moving coords upward so the end result is in order
- const row = this.rows[this.rows.length - 1 - i];
- if (row.length < 1) {
- continue;
- }
- const row_width = row.length * 8;
- for (let j = 0; j < row.length; j++) {
- if (row[j] === '') {
- continue;
- }
- const charImg = this.getImageForKey(row[j]);
- this.allImgs.push(charImg);
- this.add(charImg);
- charImg.x = (8 * j) - (row_width/2);
- charImg.y = -i * 10;
- }
- }
- }
-
- getImageForKey(charKey) {
- if (nums.includes(charKey)) {
- return this.newImage("number_icons", parseInt(charKey) - 1);
- } else {
- return this.newImage(charKey + "_icon");
- }
- }
-
- newImage(texKey, frame = '') {
- if (frame !== '') {
- return new Phaser.GameObjects.Image(this.scene, 0, 0, texKey, frame);
- } else {
- return new Phaser.GameObjects.Image(this.scene, 0, 0, texKey);
- }
- }
-};
diff --git a/2026/games/cammymoop/js/micro.js b/2026/games/cammymoop/js/micro.js
deleted file mode 100644
index c825081..0000000
--- a/2026/games/cammymoop/js/micro.js
+++ /dev/null
@@ -1,158 +0,0 @@
-
-M.Vec2 = Phaser.Math.Vector2;
-
-// Extend Phaser game objects for vector usage
-Phaser.GameObjects.GameObject.prototype.setPosVec = function (newPos) {
- this.x = newPos.x;
- this.y = newPos.y;
-};
-
-Phaser.GameObjects.GameObject.prototype.addPosVec = function (newPos) {
- this.x += newPos.x;
- this.y += newPos.y;
-};
-
-Phaser.GameObjects.GameObject.prototype.getPosVec = function () {
- return new M.Vec2(this.x, this.y);
-};
-
-M.WaitScene = class extends Phaser.Scene
-{
- preload()
- {
- //this.load.image('image', 'assets/image.png');
- this.load.image('background', 'assets/background.png');
- this.load.image('goblin', 'assets/goblin.png');
-
- this.load.image('explosion', 'assets/explosion.png');
-
- this.load.image('red_circle', 'assets/red_circle.png');
- this.load.image('target_arrow', 'assets/target_arrow.png');
- this.load.image('reroll', 'assets/reroll.png');
-
- this.load.image('yes', 'assets/yes.png');
- this.load.image('ohno', 'assets/ohno.png');
-
- this.load.image('stopwatch_frame', 'assets/stopwatch_frame.png');
- this.load.spritesheet('stopwatch_numbers', 'assets/stopwatch_numbers.png', {
- "frameWidth": 12, "frameHeight": 14,
- });
-
- this.load.image('arrow_icon', 'assets/arrow_icon.png');
- this.load.image('boom_icon', 'assets/boom_icon.png');
- this.load.image('dice_icon', 'assets/dice_icon.png');
- this.load.image('equal_icon', 'assets/equal_icon.png');
- this.load.image('greater_icon', 'assets/greater_icon.png');
- this.load.image('guard_break_icon', 'assets/guard_break_icon.png');
- this.load.image('less_icon', 'assets/less_icon.png');
- this.load.image('skull_icon', 'assets/skull_icon.png');
- this.load.spritesheet('number_icons', 'assets/number_icons.png', {
- "frameWidth": 8, "frameHeight": 8,
- });
-
- this.load.spritesheet('gob_small', 'assets/gob_small.png', {
- "frameWidth": 48, "frameHeight": 46,
- });
- this.load.spritesheet('bomb_gnome', 'assets/bomb_gnome.png', {
- "frameWidth": 42, "frameHeight": 50,
- });
-
- this.load.spritesheet('dices', 'assets/dices.png', {
- "frameWidth": 30, "frameHeight": 30,
- });
-
- this.load.audio('boom_sfx', 'assets/sfx/boom.wav');
- this.load.audio('fwoof_sfx', 'assets/sfx/fwoof.wav');
- this.load.audio('land_sfx', 'assets/sfx/land.wav');
- this.load.audio('punch_sfx', 'assets/sfx/punch.wav');
- this.load.audio('crack_sfx', 'assets/sfx/crack.wav');
-
- this.load.audio('laugh1_sfx', 'assets/sfx/laugh1.wav');
- this.load.audio('laugh2_sfx', 'assets/sfx/laugh2.wav');
- this.load.audio('hoo_sfx', 'assets/sfx/hoo.wav');
-
- this.load.audio('gnome_grunt1_sfx', 'assets/sfx/gnome_grunt1.wav');
- this.load.audio('gnome_grunt2_sfx', 'assets/sfx/gnome_grunt2.wav');
- this.load.audio('gnome_grunt3_sfx', 'assets/sfx/gnome_grunt3.wav');
-
- this.load.audio('gob1_sfx', 'assets/sfx/gob1.wav');
- this.load.audio('gob2_sfx', 'assets/sfx/gob2.wav');
- this.load.audio('gob_grunt_sfx', 'assets/sfx/gob_grunt.wav');
- }
-
- create()
- {
- this.difficulty = M.gameDifficulty;
- this.textures.get("bomb_gnome").setFilter(Phaser.Textures.FilterMode.Nearest);
- this.textures.get("dices").setFilter(Phaser.Textures.FilterMode.Nearest);
-
- Phaser.Display.Canvas.CanvasInterpolation.setCrisp(this.game.canvas);
- window.parent.postMessage({op: "ready"});
- }
-
- update(t, dt)
- {
- if (M.standalone && this.input.activePointer.primaryDown) {
- this.startDiceGame();
- }
- }
-
- timeToStart(difficulty) {
- this.difficulty = difficulty;
- this.startDiceGame();
- }
-
- startDiceGame()
- {
- const data = { difficulty: this.difficulty };
- this.scene.switch("play", data);
- this.scene.stop();
- }
-}
-
-M.gameDifficulty = 0;
-
-M.waitingScene = new M.WaitScene("wait");
-M.gameScene = new M.DiceGame({key: "play", active: false});
-
-M.gameStarted = function () {
- window.parent.postMessage({op: "started", verb: "Defeat!"});
-};
-
-M.gameEnd = function (won) {
- window.parent.postMessage({op: "done", win: won});
-};
-
-M.handleMessage = function (msgData) {
- if (!msgData) {
- return;
- }
- if (msgData.data.op == "start") {
- console.log("detected start!");
- M.waitingScene.timeToStart(msgData.data.difficulty);
- }
-}
-window.addEventListener("message", M.handleMessage);
-
-const config = {
- scale: {
- mode: Phaser.Scale.FIT,
- autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
- },
- type: Phaser.AUTO,
- parent: 'game-container',
- width: 240,
- height: 160,
- backgroundColor: '#304858',
- scene: [
- M.waitingScene, M.gameScene,
- ],
- smoothPixelArt: true,
- //antialias: false,
- //antialiasGL: true,
-};
-
-M.standalone = window.self === window.top
-
-const game = new Phaser.Game(config);
-M.game = game;
diff --git a/2026/games/cammymoop/js/stopwatch.js b/2026/games/cammymoop/js/stopwatch.js
deleted file mode 100644
index 4578ee9..0000000
--- a/2026/games/cammymoop/js/stopwatch.js
+++ /dev/null
@@ -1,59 +0,0 @@
-
-M.Stopwatch = class extends Phaser.GameObjects.Container
-{
- constructor(scene, totalSeconds, pos) {
- super(scene);
- this.setPosVec(pos);
-
- this.elapsed = 0;
- this.totalSeconds = totalSeconds;
-
- this.frame = new Phaser.GameObjects.Image(scene, 0, -3, 'stopwatch_frame');
- this.add(this.frame);
- this.tens = new Phaser.GameObjects.Image(scene, 0, 0, 'stopwatch_numbers', 0);
- this.add(this.tens);
- this.tens.setOrigin(1, 0.5);
- this.ones = new Phaser.GameObjects.Image(scene, 0, 0, 'stopwatch_numbers', 0);
- this.add(this.ones);
- this.ones.setOrigin(0, 0.5);
-
- this.addToDisplayList();
- this.addToUpdateList();
- this.showNumber(totalSeconds - 1);
- }
-
- pause() {
- this.removeFromUpdateList();
- }
-
- resume() {
- this.addToUpdateList();
- }
-
- getTimeLeft() {
- return this.totalSeconds * 1000 - this.elapsed;
- }
-
- setupHint(height, hintData) {
- this.addHintData(hintData);
- this.hint.y = -height;
- }
-
- preUpdate (t, dt) {
- this.elapsed += dt;
-
- const dispSeconds = Math.max(0, Math.floor(this.totalSeconds - (this.elapsed / 1000)));
- this.showNumber(dispSeconds);
-
- if (this.elapsed / 1000 > this.totalSeconds) {
- this.scene.nowFinished(false, true);
- this.pause();
- }
- }
-
- showNumber(dispNumber) {
- const num = Math.round(dispNumber) % 100;
- this.tens.setFrame(Math.floor(num / 10));
- this.ones.setFrame(num % 10);
- }
-};