Polish #8

Merged
brianfertig merged 5 commits from Polish into main 2026-09-01 04:46:30 +00:00
2 changed files with 38 additions and 10 deletions
Showing only changes of commit 1298648e97 - Show all commits

View File

@ -27,6 +27,16 @@ const GRID_TRAVEL = GAME_WIDTH + 800;
export default class GameMenuScene extends Phaser.Scene {
constructor() { super('GameMenu'); }
init(data) {
// Set when coming back from the opponent picker — restore that category.
this._initialCategory = (data && data.category) || null;
// scene.start() reuses the existing scene instance, so instance props from
// the previous visit survive — reset them so this create() starts clean
// (otherwise showCategory()'s "same category" guard swallows the restore).
this._currentCategory = null;
this._gridAnim = null;
}
async create() {
playMenuMusic();
const cx = GAME_WIDTH / 2;
@ -121,9 +131,15 @@ export default class GameMenuScene extends Phaser.Scene {
this._backBtn = new Button(this, cx, GAME_HEIGHT - 60, 'Back', () => this.scene.start('Landing'), { variant: 'ghost' });
// Returning from the opponent picker: restore the category that was
// active when the game was chosen — its grid flies back in from the right.
if (this._initialCategory) {
this.showCategory(this._initialCategory);
}
// The landing scene zooms the logo out before starting us, so fade the
// menu controls in to complete the handoff.
const fadeIn = [...Object.values(this._tabs), ...Object.values(this._tabIcons), this._hintText, this._backBtn];
const fadeIn = [...Object.values(this._tabs), ...Object.values(this._tabIcons), this._hintText, this._backBtn].filter(Boolean);
for (const obj of fadeIn) obj.setAlpha(0);
this.tweens.add({
targets: fadeIn,

View File

@ -1,6 +1,7 @@
import * as Phaser from 'phaser';
import { GAME_HEIGHT, GAME_WIDTH, COLORS } from '../config.js';
import { Button } from '../ui/Button.js';
import { Plaque } from '../ui/Plaque.js';
import { playMenuMusic, stopMenuMusic, setMenuMusicVolume } from '../ui/MenuMusic.js';
import { enqueue as enqueueSpeech, resetQueue as resetSpeechQueue } from '../ui/SpeechQueue.js';
@ -17,8 +18,8 @@ const CARD_TILE_GAP = 14;
// Opponent grid scroll area
const OPP_SCROLL_W = 1780;
const OPP_SCROLL_H = 440;
const OPP_SCROLL_TOP = 155; // top edge of scroll area
const OPP_SCROLL_H = 415;
const OPP_SCROLL_TOP = 180; // top edge of scroll area (below the subtitle plaque)
export default class OpponentSelectScene extends Phaser.Scene {
constructor() { super('OpponentSelect'); }
@ -58,21 +59,32 @@ export default class OpponentSelectScene extends Phaser.Scene {
this.add.image(cx, GAME_HEIGHT / 2, bgKey).setDisplaySize(GAME_WIDTH, GAME_HEIGHT).setDepth(-1);
this.add.rectangle(cx, GAME_HEIGHT / 2, GAME_WIDTH, GAME_HEIGHT, 0x000000, 0.45).setDepth(-1);
const titleText = this.add.text(cx, 60, this.gameDef.name, {
// Brass-plaque headers, same treatment as the game menu headings. The
// subtitle plaque sits in the band between the title plaque and the
// opponent list (OPP_SCROLL_TOP) — keep those in sync if you move either.
const TITLE_Y = 55;
const PLATE_GAP = 10;
const titleText = this.add.text(cx, TITLE_Y, this.gameDef.name, {
fontFamily: 'Righteous',
fontSize: '52px',
color: COLORS.textHex,
}).setOrigin(0.5);
const titlePill = this.add.rectangle(cx, 60, titleText.width + 48, titleText.height + 20, 0x000000, 0.72);
this.children.moveBelow(titlePill, titleText);
titleText.setLetterSpacing(2);
titleText.setShadow(0, 4, 'rgba(0,0,0,0.9)', 8);
const titlePlate = new Plaque(this, titleText.width + 64, titleText.height + 28).setPosition(cx, TITLE_Y);
this.children.moveBelow(titlePlate, titleText);
const subtitleText = this.add.text(cx, 122, 'Choose your opponent', {
const subtitleText = this.add.text(cx, 0, 'Choose your opponent', {
fontFamily: 'Righteous',
fontSize: '36px',
color: COLORS.mutedHex,
}).setOrigin(0.5);
const subtitlePill = this.add.rectangle(cx, 122, subtitleText.width + 48, subtitleText.height + 20, 0x000000, 0.72);
this.children.moveBelow(subtitlePill, subtitleText);
subtitleText.setShadow(0, 3, 'rgba(0,0,0,0.8)', 5);
const subPlateH = subtitleText.height + 28;
const subtitleY = TITLE_Y + (titleText.height + 28) / 2 + PLATE_GAP + subPlateH / 2;
subtitleText.setY(subtitleY);
const subtitlePlate = new Plaque(this, subtitleText.width + 64, subPlateH, { radius: 16 }).setPosition(cx, subtitleY);
this.children.moveBelow(subtitlePlate, subtitleText);
let opponents = [];
try {
@ -87,7 +99,7 @@ export default class OpponentSelectScene extends Phaser.Scene {
}
const min = this.gameDef.minOpponents ?? 1;
new Button(this, cx - 150, 1013, 'Back', () => this.scene.start('GameMenu'), {
new Button(this, cx - 150, 1013, 'Back', () => this.scene.start('GameMenu', { category: this.gameDef.category }), {
variant: 'ghost',
width: 280,
});