fix: update according to boardgame-core
This commit is contained in:
@@ -30,7 +30,7 @@ export function createInitialState() {
|
||||
{ name: 'x', min: 0, max: BOARD_SIZE - 1 },
|
||||
{ name: 'y', min: 0, max: BOARD_SIZE - 1 },
|
||||
]),
|
||||
parts: [] as TicTacToePart[],
|
||||
parts: {} as Record<string, TicTacToePart>,
|
||||
currentPlayer: 'X' as PlayerType,
|
||||
winner: null as WinnerType,
|
||||
turn: 0,
|
||||
@@ -76,7 +76,9 @@ registration.add('turn <player> <turn:number>', async function (cmd) {
|
||||
if (row < 0 || row >= BOARD_SIZE || col < 0 || col >= BOARD_SIZE) {
|
||||
return `Invalid position: (${row}, ${col}).`;
|
||||
}
|
||||
if (isCellOccupied(this.context, row, col)) {
|
||||
const state = this.context.value;
|
||||
const partId = state.board.partMap[`${row},${col}`];
|
||||
if (partId) {
|
||||
return `Cell (${row}, ${col}) is already occupied.`;
|
||||
}
|
||||
return null;
|
||||
@@ -108,18 +110,18 @@ export function hasWinningLine(positions: number[][]): boolean {
|
||||
export function checkWinner(host: MutableSignal<TicTacToeState>): WinnerType {
|
||||
const parts = host.value.parts;
|
||||
|
||||
const xPositions = parts.filter((p: TicTacToePart) => p.player === 'X').map((p: TicTacToePart) => p.position);
|
||||
const oPositions = parts.filter((p: TicTacToePart) => p.player === 'O').map((p: TicTacToePart) => p.position);
|
||||
const xPositions = Object.values(parts).filter((p: TicTacToePart) => p.player === 'X').map((p: TicTacToePart) => p.position);
|
||||
const oPositions = Object.values(parts).filter((p: TicTacToePart) => p.player === 'O').map((p: TicTacToePart) => p.position);
|
||||
|
||||
if (hasWinningLine(xPositions)) return 'X';
|
||||
if (hasWinningLine(oPositions)) return 'O';
|
||||
if (parts.length >= MAX_TURNS) return 'draw';
|
||||
if (Object.keys(parts).length >= MAX_TURNS) return 'draw';
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function placePiece(host: MutableSignal<TicTacToeState>, row: number, col: number, player: PlayerType) {
|
||||
const moveNumber = host.value.parts.length + 1;
|
||||
const moveNumber = Object.keys(host.value.parts).length + 1;
|
||||
const piece: TicTacToePart = {
|
||||
id: `piece-${player}-${moveNumber}`,
|
||||
regionId: 'board',
|
||||
@@ -127,7 +129,7 @@ export function placePiece(host: MutableSignal<TicTacToeState>, row: number, col
|
||||
player,
|
||||
};
|
||||
host.produce(state => {
|
||||
state.parts.push(piece);
|
||||
state.parts[piece.id] = piece;
|
||||
state.board.childIds.push(piece.id);
|
||||
state.board.partMap[`${row},${col}`] = piece.id;
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@ import Phaser from 'phaser';
|
||||
import { createGameContext } from 'boardgame-core';
|
||||
import { GameUI, PromptDialog, CommandLog } from 'boardgame-phaser';
|
||||
import { createInitialState, registry, type TicTacToeState } from './game/tic-tac-toe';
|
||||
import { GameScene, type GameSceneData } from './scenes/GameScene';
|
||||
import { GameScene } from './scenes/GameScene';
|
||||
import './style.css';
|
||||
|
||||
const gameContext = createGameContext<TicTacToeState>(registry, createInitialState);
|
||||
@@ -33,11 +33,6 @@ const originalRun = gameContext.commands.run.bind(gameContext.commands);
|
||||
return result;
|
||||
};
|
||||
|
||||
const sceneData: GameSceneData = {
|
||||
state: gameContext.state,
|
||||
commands: gameContext.commands,
|
||||
};
|
||||
|
||||
function App() {
|
||||
const [phaserReady, setPhaserReady] = useState(false);
|
||||
const [game, setGame] = useState<Phaser.Game | null>(null);
|
||||
@@ -53,7 +48,8 @@ function App() {
|
||||
};
|
||||
|
||||
const phaserGame = new Phaser.Game(phaserConfig);
|
||||
phaserGame.scene.add('GameScene', GameScene, true, sceneData);
|
||||
// 通过 init 传递 gameContext
|
||||
phaserGame.scene.add('GameScene', GameScene, true, { gameContext });
|
||||
|
||||
setGame(phaserGame);
|
||||
setPhaserReady(true);
|
||||
|
||||
@@ -2,17 +2,12 @@ import Phaser from 'phaser';
|
||||
import type { TicTacToeState, TicTacToePart, PlayerType } from '@/game/tic-tac-toe';
|
||||
import { isCellOccupied } from 'boardgame-core';
|
||||
import { ReactiveScene, bindRegion, createInputMapper, createPromptHandler } from 'boardgame-phaser';
|
||||
import type { PromptEvent, MutableSignal, IGameContext } from 'boardgame-core';
|
||||
import type { PromptEvent } from 'boardgame-core';
|
||||
|
||||
const CELL_SIZE = 120;
|
||||
const BOARD_OFFSET = { x: 100, y: 100 };
|
||||
const BOARD_SIZE = 3;
|
||||
|
||||
export interface GameSceneData {
|
||||
state: MutableSignal<TicTacToeState>;
|
||||
commands: IGameContext<TicTacToeState>['commands'];
|
||||
}
|
||||
|
||||
export class GameScene extends ReactiveScene<TicTacToeState> {
|
||||
private boardContainer!: Phaser.GameObjects.Container;
|
||||
private gridGraphics!: Phaser.GameObjects.Graphics;
|
||||
@@ -25,11 +20,6 @@ export class GameScene extends ReactiveScene<TicTacToeState> {
|
||||
super('GameScene');
|
||||
}
|
||||
|
||||
init(data: GameSceneData): void {
|
||||
this.state = data.state;
|
||||
this.commands = data.commands;
|
||||
}
|
||||
|
||||
protected onStateReady(_state: TicTacToeState): void {
|
||||
}
|
||||
|
||||
@@ -71,6 +61,9 @@ export class GameScene extends ReactiveScene<TicTacToeState> {
|
||||
|
||||
return text;
|
||||
},
|
||||
update: (part, obj) => {
|
||||
// 可以在这里更新部件的视觉状态
|
||||
},
|
||||
},
|
||||
this.boardContainer,
|
||||
);
|
||||
@@ -97,12 +90,6 @@ export class GameScene extends ReactiveScene<TicTacToeState> {
|
||||
onPrompt: (prompt) => {
|
||||
this.activePrompt = prompt;
|
||||
},
|
||||
onSubmit: (input) => {
|
||||
if (this.activePrompt) {
|
||||
return this.activePrompt.tryCommit(input);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onCancel: () => {
|
||||
this.activePrompt = null;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user