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 12:14:26 +08:00
|
|
|
|
2026-04-04 13:08:28 +08:00
|
|
|
export const phaserContext = createContext<Signal<Phaser.Game | undefined>>(signal(undefined));
|
2026-04-04 12:14:26 +08:00
|
|
|
|
|
|
|
|
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) {
|
2026-04-04 12:14:26 +08:00
|
|
|
const gameSignal = useSignal<Phaser.Game>();
|
2026-04-04 13:08:28 +08:00
|
|
|
|
2026-04-04 12:14:26 +08:00
|
|
|
useSignalEffect(() => {
|
|
|
|
|
const phaserGame = new Phaser.Game(props.config || defaultPhaserConfig);
|
|
|
|
|
gameSignal.value = phaserGame;
|
2026-04-04 13:08:28 +08:00
|
|
|
|
2026-04-04 12:14:26 +08:00
|
|
|
return () => {
|
|
|
|
|
gameSignal.value = undefined;
|
|
|
|
|
phaserGame.destroy(true);
|
2026-04-04 13:08:28 +08:00
|
|
|
};
|
2026-04-04 12:14:26 +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 12:14:26 +08:00
|
|
|
}
|
|
|
|
|
|
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) {
|
2026-04-04 12:14:26 +08:00
|
|
|
const context = useContext(phaserContext);
|
2026-04-04 13:08:28 +08:00
|
|
|
|
2026-04-04 12:14:26 +08:00
|
|
|
useSignalEffect(() => {
|
|
|
|
|
const game = context.value;
|
2026-04-04 13:08:28 +08:00
|
|
|
if (!game) return;
|
|
|
|
|
|
2026-04-04 12:14:26 +08:00
|
|
|
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 12:14:26 +08:00
|
|
|
});
|
2026-04-04 13:08:28 +08:00
|
|
|
|
2026-04-04 12:14:26 +08:00
|
|
|
return null;
|
2026-04-04 13:08:28 +08:00
|
|
|
}
|