2026-04-04 22:52:54 +08:00
|
|
|
import type { BoopState } from '@/game';
|
2026-04-04 14:22:35 +08:00
|
|
|
import { GameHostScene } from 'boardgame-phaser';
|
2026-04-04 22:52:54 +08:00
|
|
|
import { commands } from '@/game';
|
2026-04-04 16:25:36 +08:00
|
|
|
import { BoardRenderer } from './BoardRenderer';
|
|
|
|
|
import { createPieceSpawner } from './PieceSpawner';
|
|
|
|
|
import { SupplyUI } from './SupplyUI';
|
|
|
|
|
import { PieceTypeSelector } from './PieceTypeSelector';
|
|
|
|
|
import { WinnerOverlay } from './WinnerOverlay';
|
2026-04-05 00:12:05 +08:00
|
|
|
import { StartOverlay } from './StartOverlay';
|
2026-04-05 00:24:06 +08:00
|
|
|
import { ErrorOverlay } from './ErrorOverlay';
|
2026-04-04 14:22:35 +08:00
|
|
|
|
|
|
|
|
export class GameScene extends GameHostScene<BoopState> {
|
2026-04-04 16:25:36 +08:00
|
|
|
private boardRenderer!: BoardRenderer;
|
|
|
|
|
private supplyUI!: SupplyUI;
|
|
|
|
|
private pieceTypeSelector!: PieceTypeSelector;
|
|
|
|
|
private winnerOverlay!: WinnerOverlay;
|
2026-04-05 00:12:05 +08:00
|
|
|
private startOverlay!: StartOverlay;
|
2026-04-05 00:24:06 +08:00
|
|
|
private errorOverlay!: ErrorOverlay;
|
2026-04-04 14:22:35 +08:00
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
|
super('GameScene');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
create(): void {
|
|
|
|
|
super.create();
|
|
|
|
|
|
2026-04-04 16:25:36 +08:00
|
|
|
// 初始化 UI 组件
|
|
|
|
|
this.boardRenderer = new BoardRenderer(this);
|
|
|
|
|
this.supplyUI = new SupplyUI(this);
|
|
|
|
|
this.pieceTypeSelector = new PieceTypeSelector(this);
|
|
|
|
|
this.winnerOverlay = new WinnerOverlay(this, () => this.restartGame());
|
2026-04-05 00:12:05 +08:00
|
|
|
this.startOverlay = new StartOverlay(this, () => this.startGame());
|
2026-04-05 00:24:06 +08:00
|
|
|
this.errorOverlay = new ErrorOverlay(this);
|
2026-04-04 16:25:36 +08:00
|
|
|
|
|
|
|
|
// 设置棋子生成器
|
|
|
|
|
this.disposables.add(createPieceSpawner(this));
|
2026-04-04 14:22:35 +08:00
|
|
|
|
2026-04-04 16:25:36 +08:00
|
|
|
// 设置输入处理
|
2026-04-04 23:25:43 +08:00
|
|
|
this.boardRenderer.setupInput(
|
|
|
|
|
() => this.state,
|
|
|
|
|
(row, col) => this.handleCellClick(row, col),
|
2026-04-05 00:12:05 +08:00
|
|
|
() => this.gameHost.status.value !== 'running' || !!this.state.winner
|
2026-04-04 23:25:43 +08:00
|
|
|
);
|
2026-04-04 14:22:35 +08:00
|
|
|
|
2026-04-05 00:24:06 +08:00
|
|
|
// 设置棋子点击处理(用于棋盘满时选择要升级的棋子)
|
|
|
|
|
this.boardRenderer.setupPieceInput(
|
|
|
|
|
() => this.state,
|
|
|
|
|
(row, col) => this.handlePieceClick(row, col),
|
|
|
|
|
() => this.gameHost.status.value !== 'running' || !!this.state.winner
|
|
|
|
|
);
|
|
|
|
|
|
2026-04-05 00:12:05 +08:00
|
|
|
// 监听游戏状态变化
|
|
|
|
|
this.addEffect(() => {
|
|
|
|
|
const status = this.gameHost.status.value;
|
|
|
|
|
if (status === 'running') {
|
|
|
|
|
this.startOverlay.hide();
|
|
|
|
|
} else if (status === 'created') {
|
|
|
|
|
this.startOverlay.show();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 监听胜负状态
|
2026-04-04 16:34:17 +08:00
|
|
|
this.addEffect(() => {
|
2026-04-04 14:22:35 +08:00
|
|
|
const winner = this.state.winner;
|
|
|
|
|
if (winner) {
|
2026-04-04 16:25:36 +08:00
|
|
|
this.winnerOverlay.show(winner);
|
|
|
|
|
} else {
|
|
|
|
|
this.winnerOverlay.hide();
|
2026-04-04 14:22:35 +08:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-04 16:34:17 +08:00
|
|
|
this.addEffect(() => {
|
2026-04-04 14:22:35 +08:00
|
|
|
const currentPlayer = this.state.currentPlayer;
|
2026-04-04 16:25:36 +08:00
|
|
|
this.boardRenderer.updateTurnText(currentPlayer, this.state);
|
|
|
|
|
this.supplyUI.update(this.state);
|
|
|
|
|
this.pieceTypeSelector.update(this.state);
|
2026-04-04 14:22:35 +08:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-04 16:25:36 +08:00
|
|
|
private handleCellClick(row: number, col: number): void {
|
|
|
|
|
const selectedType = this.pieceTypeSelector.getSelectedType();
|
|
|
|
|
const cmd = commands.play(this.state.currentPlayer, row, col, selectedType);
|
|
|
|
|
const error = this.gameHost.onInput(cmd);
|
|
|
|
|
if (error) {
|
2026-04-05 00:24:06 +08:00
|
|
|
this.errorOverlay.show(error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private handlePieceClick(row: number, col: number): void {
|
|
|
|
|
// 棋盘满时,点击棋子触发升级
|
|
|
|
|
const cmd = commands.play(this.state.currentPlayer, row, col);
|
|
|
|
|
const error = this.gameHost.onInput(cmd);
|
|
|
|
|
if (error) {
|
|
|
|
|
this.errorOverlay.show(error);
|
2026-04-04 14:22:35 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-05 00:12:05 +08:00
|
|
|
private startGame(): void {
|
|
|
|
|
this.gameHost.setup('setup');
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-04 16:25:36 +08:00
|
|
|
private restartGame(): void {
|
|
|
|
|
this.gameHost.setup('setup');
|
2026-04-04 14:22:35 +08:00
|
|
|
}
|
|
|
|
|
}
|