👽
Phaser3 + Redux + TypeScript
Reduxを使えば異なるPhaserシーン間でスコアを共有できます。以下に具体的な実装方法を説明します。
「ランダムに画面に的(ターゲット)が出現し、それをクリックすると得点がアップする」
このようなゲームは「クリックターゲットゲーム」「モグラたたき風ゲーム」などと呼ばれます。
実装手順(Phaser3 + Redux + TypeScript)
1. Redux Storeの設定
// src/redux/gameSlice.ts
import { createSlice } from '@reduxjs/toolkit';
interface GameState {
score: number;
}
const initialState: GameState = {
score: 0,
};
export const gameSlice = createSlice({
name: 'game',
initialState,
reducers: {
incrementScore: (state) => {
state.score += 1;
},
resetScore: (state) => {
state.score = 0;
}
}
});
export const { incrementScore, resetScore } = gameSlice.actions;
export default gameSlice.reducer;
2. Storeの統合
// src/redux/store.ts
import { configureStore } from '@reduxjs/toolkit';
import gameReducer from './gameSlice';
export const store = configureStore({
reducer: {
game: gameReducer
}
});
export type RootState = ReturnType;
export type AppDispatch = typeof store.dispatch;
3. HUDシーンの実装
// src/scenes/HudScene.ts
import Phaser from 'phaser';
import { store } from '../redux/store';
import { useAppSelector } from '../redux/hooks';
export class HudScene extends Phaser.Scene {
private scoreText!: Phaser.GameObjects.Text;
constructor() {
super({ key: 'HudScene' });
}
create() {
this.scoreText = this.add.text(10, 10, 'Score: 0', {
fontSize: '24px',
color: '#ffffff'
});
// Reduxの状態変化を監視
store.subscribe(() => {
const score = store.getState().game.score;
this.scoreText.setText(`Score: ${score}`);
});
}
}
4. ゲームシーンの修正
// src/scenes/GameScene.ts
import Phaser from 'phaser';
import { store } from '../redux/store';
import { incrementScore } from '../redux/gameSlice';
export class GameScene extends Phaser.Scene {
constructor() {
super({ key: 'GameScene' });
}
create() {
// 的を作成するロジック
const target = this.add.circle(400, 300, 20, 0xff0000)
.setInteractive()
.on('pointerdown', () => {
store.dispatch(incrementScore());
target.destroy();
});
}
}
5. シーン起動設定
// main.ts
import Phaser from 'phaser';
import { GameScene } from './scenes/GameScene';
import { HudScene } from './scenes/HudScene';
const config: Phaser.Types.Core.GameConfig = {
type: Phaser.AUTO,
width: 800,
height: 600,
scene: [GameScene, HudScene], // 複数シーンを同時起動
parent: 'game-container',
};
動作のポイント
-
複数シーン同時実行:
-
scene: [GameScene, HudScene]
で両シーンを並列実行 - HUDシーンは常に前面に表示される
-
-
Reduxの状態同期:
-
store.subscribe()
で状態変化を監視 - スコア更新時に自動でテキスト更新
-
-
PhaserとReactの統合:
// Reactコンポーネント例
import { useSelector } from 'react-redux';
const GameContainer = () => {
const score = useSelector((state: RootState) => state.game.score);
return (
<div>
<div id="game-container" />
<div className="overlay-score">React側スコア: {score}</div>
</div>
);
};
最適化のヒント
-
デバウンス処理: 頻繁な更新がある場合
store.subscribe(() => { this.time.delayedCall(100, () => { this.scoreText.setText(`Score: ${store.getState().game.score}`); }); });
-
パフォーマンス計測:
// store.ts import { Middleware } from '@reduxjs/toolkit'; const phaserMiddleware: Middleware = store => next => action => { const start = performance.now(); const result = next(action); console.log(`Action ${action.type} took ${performance.now() - start}ms`); return result; }; export const store = configureStore({ reducer: { /* ... */ }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(phaserMiddleware) });
Reduxを活用することで、シーン間の状態管理がシンプルになり、ゲームの状態を一元管理できます。HUDシーン以外にも、ポーズメニューやリザルト画面など、さまざまなUI要素と連携可能です。
Discussion