import Phaser from 'phaser'; import { signal, useSignal, useSignalEffect } from '@preact/signals'; import { createContext, h } from 'preact'; import { useContext } from 'preact/hooks'; import {ReadonlySignal} from "@preact/signals-core"; import type { ReactiveScene, ReactiveScenePhaserData } from '../scenes'; export interface PhaserGameContext { game: Phaser.Game; } export const phaserContext = createContext | null>(null); export const defaultPhaserConfig: Phaser.Types.Core.GameConfig = { type: Phaser.AUTO, width: 560, height: 560, parent: 'phaser-container', backgroundColor: '#f9fafb', scene: [], }; export interface PhaserGameProps { config?: Partial; children?: any; } export function PhaserGame(props: PhaserGameProps) { const gameSignal = useSignal({ game: undefined! }); useSignalEffect(() => { const config: Phaser.Types.Core.GameConfig = { ...defaultPhaserConfig, ...props.config, }; const phaserGame = new Phaser.Game(config); gameSignal.value = { game: phaserGame }; return () => { gameSignal.value = { game: undefined! }; phaserGame.destroy(true); }; }); return (
{props.children}
); } export interface PhaserSceneProps = {}> { sceneKey: string; scene: ReactiveScene; autoStart: boolean; data?: TData; children?: any; } export const phaserSceneContext = createContext | null>(null); export function PhaserScene = {}>(props: PhaserSceneProps) { const phaserGameSignal = useContext(phaserContext); const sceneSignal = useSignal(); useSignalEffect(() => { if (!phaserGameSignal) return; const ctx = phaserGameSignal.value; if (!ctx?.game) return; const game = ctx.game; const initData = { ...props.data, phaserGame: phaserGameSignal.value, } as TData & ReactiveScenePhaserData; game.scene.add(props.sceneKey, props.scene, props.autoStart, initData); sceneSignal.value = game.scene.getScene(props.sceneKey); return () => { sceneSignal.value = undefined; game.scene.remove(props.sceneKey); }; }); return }>{props.children}; }