boardgame-phaser/packages/framework/src/ui/PhaserBridge.tsx

66 lines
1.7 KiB
TypeScript
Raw Normal View History

2026-04-04 13:08:28 +08:00
import Phaser from 'phaser';
import { signal, useSignal, useSignalEffect, type Signal } from '@preact/signals';
import { createContext, h } from 'preact';
import { useContext } from 'preact/hooks';
2026-04-04 13:08:28 +08:00
export const phaserContext = createContext<Signal<Phaser.Game | undefined>>(signal(undefined));
export const defaultPhaserConfig: Phaser.Types.Core.GameConfig = {
type: Phaser.AUTO,
width: 560,
height: 560,
parent: 'phaser-container',
backgroundColor: '#f9fafb',
scene: [],
};
2026-04-04 13:08:28 +08:00
export interface PhaserGameProps {
config?: Partial<Phaser.Types.Core.GameConfig>;
children?: any;
}
export function PhaserGame(props: PhaserGameProps) {
const gameSignal = useSignal<Phaser.Game>();
2026-04-04 13:08:28 +08:00
useSignalEffect(() => {
const phaserGame = new Phaser.Game(props.config || defaultPhaserConfig);
gameSignal.value = phaserGame;
2026-04-04 13:08:28 +08:00
return () => {
gameSignal.value = undefined;
phaserGame.destroy(true);
2026-04-04 13:08:28 +08:00
};
});
2026-04-04 13:08:28 +08:00
return (
<div id="phaser-container" className="w-full h-full">
<phaserContext.Provider value={gameSignal}>
{props.children}
</phaserContext.Provider>
</div>
);
}
2026-04-04 13:08:28 +08:00
export interface PhaserSceneProps {
sceneKey: string;
scene: Phaser.Scene;
autoStart: boolean;
data?: object;
}
export function PhaserScene(props: PhaserSceneProps) {
const context = useContext(phaserContext);
2026-04-04 13:08:28 +08:00
useSignalEffect(() => {
const game = context.value;
2026-04-04 13:08:28 +08:00
if (!game) return;
game.scene.add(props.sceneKey, props.scene, props.autoStart, props.data);
return () => {
game.scene.remove(props.sceneKey);
2026-04-04 13:08:28 +08:00
};
});
2026-04-04 13:08:28 +08:00
return null;
2026-04-04 13:08:28 +08:00
}