Polish #8
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue