From 1ad29422416102e31c2b58b78f9017dbfd5e0349 Mon Sep 17 00:00:00 2001 From: Brian Fertig Date: Mon, 27 Jul 2026 19:31:51 -0600 Subject: [PATCH] Added Characters and Backgrounds to Puzzle Mode on Tetris Attack --- src/games/tetrisattack/TetrisAttackGame.js | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/games/tetrisattack/TetrisAttackGame.js b/src/games/tetrisattack/TetrisAttackGame.js index e2dc8c4..43a41f3 100644 --- a/src/games/tetrisattack/TetrisAttackGame.js +++ b/src/games/tetrisattack/TetrisAttackGame.js @@ -182,6 +182,10 @@ export default class TetrisAttackGame extends Phaser.Scene { const p = this.puzzles[puzzleIndex] ?? this.puzzles[0]; this.currentPuzzle = p; this.state = newGame({ mode: 'puzzle', puzzle: { grid: p.grid, maxMoves: p.maxMoves }, rng }); + const { round, bgKey } = this.getPuzzleHeroInfo(puzzleIndex); + this.currentRound = round; + this._puzzleBgKey = bgKey; + this.ensureRoundAssets(round); } else if (mode === 'stageclear') { this.currentRound = round; this.stageNumber = stageNumber; @@ -211,6 +215,7 @@ export default class TetrisAttackGame extends Phaser.Scene { if (mode === 'stageclear') this.setStageBackground(round.characterId, stageNumber); else if (mode === 'endless') this.setEndlessHeroBackground(0); + else if (mode === 'puzzle') this.setPuzzleBackground(); else this.setStageBackground(null); this.buildHUD(); this.playing = true; @@ -301,6 +306,9 @@ export default class TetrisAttackGame extends Phaser.Scene { const idx = (this.state.level - 1) % this.endlessHeroOrder.length; this.setEndlessHeroBackground(idx); } + if (this.mode === 'puzzle') { + this.setPuzzleBackground(); + } // an intro cutscene waiting on this friend's art can dress itself now this.onBackgroundsLoaded?.(); }); @@ -362,6 +370,25 @@ export default class TetrisAttackGame extends Phaser.Scene { this.hostPortrait.setPose('happy', 1500); } + // ── Puzzle-mode hero mapping ──────────────────────────────────────────────── + // 24 puzzles / 6 heroes = 4 puzzles per hero, in Stage Clear order. + // Beth puzzles 0–3 → backgrounds r1–r4 + // Jerry puzzles 4–7 → backgrounds r1–r4 + // etc. + getPuzzleHeroInfo(puzzleIndex) { + const heroIndex = Math.floor(puzzleIndex / 4); + const stageNumber = (puzzleIndex % 4) + 1; + const round = this.rounds[heroIndex] ?? this.rounds[0]; + return { round, bgKey: `tetrisattack-bg-${round.characterId}-r${stageNumber}`, stageNumber, spriteIndex: heroIndex }; + } + + setPuzzleBackground() { + const key = this._puzzleBgKey; + if (!key || !this.textures.exists(key)) return; + if (this.heroBg) { this.heroBg.destroy(); this.heroBg = null; } + this.heroBg = this.add.image(GAME_WIDTH / 2, GAME_HEIGHT / 2, key).setDepth(D.bg + 2); + } + // ── Character voice ─────────────────────────────────────────────────────── // The friend reacts out loud to big clears and to how the round ends. Only // one line is ever in the air: a newer request replaces a pending one, and a @@ -889,6 +916,17 @@ export default class TetrisAttackGame extends Phaser.Scene { }).setOrigin(0.5); this.hudLayer.add(this._heroNameLabel); } + } else if (this.mode === 'puzzle') { + const round = this.currentRound; + if (round) { + this.hudLayer.add(this.add.text(GAME_WIDTH - 260, 138, 'PUZZLE', { + fontFamily: FONT, fontSize: '24px', color: '#9fb0c8', + }).setOrigin(0.5)); + this.hostPortrait = createHostPortrait(this, GAME_WIDTH - 260, 360, round, this.rounds.indexOf(round)); + this.hudLayer.add(this.add.text(GAME_WIDTH - 260, 560, round.name.toUpperCase(), { + fontFamily: FONT, fontSize: '34px', color: '#ffe66e', + }).setOrigin(0.5)); + } } const controls = ['◀ ▲ ▼ ▶ move', 'SPACE / Z swap'];