90 lines
5.9 KiB
JavaScript
90 lines
5.9 KiB
JavaScript
import * as Phaser from 'phaser';
|
|
import { GAME_HEIGHT, GAME_WIDTH, COLORS } from '../config.js';
|
|
import { Button } from '../ui/Button.js';
|
|
import { missingGameAssets, ensureGameAssets } from '../services/assetLoader.js';
|
|
|
|
// Generic room shell. Dispatches to the concrete game scene
|
|
// (Backgammon, Blackjack, etc.) based on `data.game.slug`.
|
|
export default class GameRoomScene extends Phaser.Scene {
|
|
constructor() { super('GameRoom'); }
|
|
|
|
init(data) {
|
|
this.game = data.game;
|
|
this.opponents = data.opponents ?? [];
|
|
this.playfield = data.playfield ?? null;
|
|
this.cardBack = data.cardBack ?? null;
|
|
this.tilePlacement = data.tilePlacement ?? 'standard';
|
|
this.expansion = data.expansion ?? 'base';
|
|
this.scenario = data.scenario ?? null;
|
|
this.deckMode = data.deckMode ?? 'standard';
|
|
this.wordLength = data.wordLength ?? 4;
|
|
this.secretRevealType = data.secretRevealType ?? 'standard';
|
|
this.difficulty = data.difficulty ?? 'novice';
|
|
}
|
|
|
|
create() {
|
|
const slugDispatch = { backgammon: 'Backgammon', holdem: 'HoldemGame', blackjack: 'BlackjackGame', parchisi: 'ParchisiGame', yatzi: 'YatziGame', skipbo: 'SkipBoGame', phase10: 'Phase10Game', chinesecheckers: 'ChineseCheckersGame', gofish: 'GoFishGame', uno: 'UnoGame', craps: 'CrapsGame', roulette: 'RouletteGame', mexicantrain: 'MexicanTrainGame', hearts: 'HeartsGame', catan: 'CatanGame', tickettoride: 'TicketToRideGame', nerts: 'NertsGame', bingo: 'BingoGame', baccarat: 'BaccaratGame', dominion: 'DominionGame', checkers: 'CheckersGame', chess: 'ChessGame', wordle: 'WordleGame', scrabble: 'ScrabbleGame', ghost: 'GhostGame', wordladder: 'WordLadderGame', wordsearch: 'WordSearchGame', hangman: 'HangmanGame', sudoku: 'SudokuGame', othello: 'OthelloGame', go: 'GoGame', battleship: 'BattleshipGame', mastermind: 'MastermindGame', connect4: 'Connect4Game', boggle: 'BoggleGame', oldmaid: 'OldMaidGame', blokus: 'BlokusGame', spellingbee: 'SpellingBeeGame', minicrossword: 'MiniCrosswordGame', forbiddenisland: 'ForbiddenIslandGame', solitairetour: 'SolitaireTourGame', splendor: 'SplendorGame', tectonic: 'TectonicGame', labyrinth: 'LabyrinthGame', videopoker: 'VideoPokerGame', farkel: 'FarkelGame', stratego: 'StrategoGame', kiitos: 'KiitosGame', monopoly: 'MonopolyGame', triominoes: 'TriominoesGame', freecell: 'FreecellGame', rushhour: 'RushHourGame', hexsweeper: 'HexsweeperGame', puddingmonsters: 'PuddingMonstersGame', shift: 'ShiftGame', blockfighter: 'BlockFighterGame', mahjongmatch: 'MahjongMatchGame', mahjong: 'MahjongGame', jewelquest: 'JewelQuestGame', zuma: 'ZumaGame', bejeweled: 'BejeweledGame', minimotorways: 'MiniMotorwaysGame', slots: 'SlotsGame', cribbage: 'CribbageGame', canasta: 'CanastaGame', dotlink: 'DotLinkGame', '2048': '2048Game', rummikub: 'RummikubGame', ginrummy: 'GinRummyGame', risk: 'RiskGame', geniussquare: 'GeniusSquareGame', katamino: 'KataminoGame', bookwork: 'BookworkGame', paigow: 'PaiGowPokerGame', spireclimb: 'SpireClimbGame', azul: 'AzulGame', jumble: 'JumbleGame', dungeonboss: 'DungeonBossGame', swdbg: 'SWDBGGame', balatro: 'BalatroGame', peggle: 'PeggleGame', coloradodefense: 'ColoradoDefenseGame', starcontrol: 'StarControlGame', civilization: 'CivilizationGame', tempest: 'TempestGame', superkart: 'SuperKartGame', advancewars: 'AdvanceWarsGame', tetrisattack: 'TetrisAttackGame', totalannihilation: 'TotalAnnihilationGame', bloxorz: 'BloxorzGame', gootower: 'GooTowerGame', excitebike: 'ExcitebikeGame', mastervega: 'MasterOfVegaGame' };
|
|
if (slugDispatch[this.game.slug]) {
|
|
const sceneKey = slugDispatch[this.game.slug];
|
|
const startData = {
|
|
game: this.game,
|
|
opponents: this.opponents,
|
|
playfield: this.playfield,
|
|
cardBack: this.cardBack,
|
|
tilePlacement: this.tilePlacement,
|
|
expansion: this.expansion,
|
|
scenario: this.scenario,
|
|
deckMode: this.deckMode,
|
|
wordLength: this.wordLength,
|
|
secretRevealType: this.secretRevealType,
|
|
difficulty: this.difficulty,
|
|
};
|
|
|
|
// Game art is lazy-loaded on first entry (see data/assetManifest.js).
|
|
// Anything already cached makes this a synchronous fast path.
|
|
if (missingGameAssets(this, this.game.slug).length === 0) {
|
|
this.scene.start(sceneKey, startData);
|
|
return;
|
|
}
|
|
|
|
const barWidth = 600;
|
|
this.add.rectangle(GAME_WIDTH / 2, GAME_HEIGHT / 2, barWidth + 8, 28, COLORS.panel)
|
|
.setStrokeStyle(2, COLORS.accent);
|
|
const bar = this.add.rectangle(GAME_WIDTH / 2 - barWidth / 2, GAME_HEIGHT / 2, 0, 20, COLORS.accent)
|
|
.setOrigin(0, 0.5);
|
|
this.add.text(GAME_WIDTH / 2, GAME_HEIGHT / 2 - 60, `Loading ${this.game.name}…`, {
|
|
fontFamily: '"Julius Sans One"',
|
|
fontSize: '32px',
|
|
color: COLORS.textHex,
|
|
}).setOrigin(0.5);
|
|
|
|
let gone = false;
|
|
this.events.once('shutdown', () => { gone = true; });
|
|
ensureGameAssets(this, this.game.slug, { onProgress: (p) => { bar.width = barWidth * p; } })
|
|
.then(() => { if (!gone) this.scene.start(sceneKey, startData); });
|
|
return;
|
|
}
|
|
const cx = GAME_WIDTH / 2;
|
|
|
|
this.add.text(cx, 80, `${this.game.name}`, {
|
|
fontFamily: 'Righteous',
|
|
fontSize: '52px',
|
|
color: COLORS.textHex,
|
|
}).setOrigin(0.5);
|
|
|
|
this.add.text(cx, 150, 'Single-player table',
|
|
{ fontSize: '24px', color: COLORS.mutedHex }).setOrigin(0.5);
|
|
|
|
// Placeholder table felt
|
|
this.add.rectangle(cx, GAME_HEIGHT / 2 + 40, 1400, 700, 0x14532d).setStrokeStyle(4, COLORS.accent);
|
|
this.add.text(cx, GAME_HEIGHT / 2 + 40, `${this.game.name} board placeholder\n(game logic plugs in here)`, {
|
|
fontFamily: '"Julius Sans One"',
|
|
fontSize: '28px',
|
|
color: COLORS.mutedHex,
|
|
align: 'center',
|
|
}).setOrigin(0.5);
|
|
|
|
new Button(this, cx, GAME_HEIGHT - 100, 'Leave table', () => this.scene.start('GameMenu'));
|
|
}
|
|
}
|