boardgame-phaser/packages/boop-game/src/scenes/GameScene.ts

85 lines
2.6 KiB
TypeScript

import type { BoopState } from '@/game';
import { GameHostScene } from 'boardgame-phaser';
import { prompts } from '@/game';
import { BoardRenderer } from './BoardRenderer';
import { createPieceSpawner } from './PieceSpawner';
import { SupplyUI } from './SupplyUI';
import { PieceTypeSelector } from './PieceTypeSelector';
import { WinnerOverlay } from './WinnerOverlay';
import { ErrorOverlay } from './ErrorOverlay';
export class GameScene extends GameHostScene<BoopState> {
private boardRenderer!: BoardRenderer;
private supplyUI!: SupplyUI;
private pieceTypeSelector!: PieceTypeSelector;
private winnerOverlay!: WinnerOverlay;
private errorOverlay!: ErrorOverlay;
constructor() {
super('GameScene');
}
create(): void {
super.create();
// 初始化 UI 组件
this.boardRenderer = new BoardRenderer(this);
this.supplyUI = new SupplyUI(this);
this.pieceTypeSelector = new PieceTypeSelector(this);
this.winnerOverlay = new WinnerOverlay(this, () => this.gameHost.start());
this.errorOverlay = new ErrorOverlay(this);
// 设置棋子生成器
this.disposables.add(createPieceSpawner(this));
// 设置输入处理(空单元格和已有棋子统一处理)
this.boardRenderer.setupInput(
() => this.state,
(row, col) => this.handleCellClick(row, col),
(row, col) => this.handlePieceClick(row, col),
() => this.gameHost.status.value !== 'running' || !!this.state.winner
);
// 监听胜负状态
this.addEffect(() => {
const winner = this.state.winner;
if (winner) {
this.winnerOverlay.show(winner);
} else {
this.winnerOverlay.hide();
}
});
this.addEffect(() => {
const currentPlayer = this.state.currentPlayer;
this.boardRenderer.updateTurnText(currentPlayer, this.state);
this.supplyUI.update(this.state);
this.pieceTypeSelector.update(this.state);
});
// 启动游戏
this.gameHost.start();
}
private handleCellClick(row: number, col: number): void {
const selectedType = this.pieceTypeSelector.getSelectedType();
const error = this.gameHost.tryAnswerPrompt(prompts.play, this.state.currentPlayer, row, col, selectedType);
if (error) {
this.errorOverlay.show(error);
}
}
private handlePieceClick(row: number, col: number): void {
// 棋盘满时,点击棋子触发升级
const error = this.gameHost.tryAnswerPrompt(prompts.choose, this.state.currentPlayer, row, col);
if (error) {
this.errorOverlay.show(error);
}
}
/** 跳转到菜单场景 */
private async goToMenu(): Promise<void> {
await this.sceneController.launch('MenuScene');
}
}