refactor: ReactiveScene

This commit is contained in:
hyper
2026-04-12 16:26:52 +08:00
parent 21a7afa276
commit 59fa0e6122
6 changed files with 105 additions and 47 deletions
+24 -12
View File
@@ -3,8 +3,13 @@ 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 const phaserContext = createContext<ReadonlySignal<Phaser.Game | undefined>>(signal(undefined));
export interface PhaserGameContext {
game: Phaser.Game;
}
export const phaserContext = createContext<ReadonlySignal<PhaserGameContext> | null>(null);
export const defaultPhaserConfig: Phaser.Types.Core.GameConfig = {
type: Phaser.AUTO,
@@ -21,7 +26,7 @@ export interface PhaserGameProps {
}
export function PhaserGame(props: PhaserGameProps) {
const gameSignal = useSignal<Phaser.Game>();
const gameSignal = useSignal<PhaserGameContext>({ game: undefined! });
useSignalEffect(() => {
const config: Phaser.Types.Core.GameConfig = {
@@ -29,10 +34,10 @@ export function PhaserGame(props: PhaserGameProps) {
...props.config,
};
const phaserGame = new Phaser.Game(config);
gameSignal.value = phaserGame;
gameSignal.value = { game: phaserGame };
return () => {
gameSignal.value = undefined;
gameSignal.value = { game: undefined! };
phaserGame.destroy(true);
};
});
@@ -46,24 +51,31 @@ export function PhaserGame(props: PhaserGameProps) {
);
}
export interface PhaserSceneProps {
export interface PhaserSceneProps<TData extends Record<string, unknown> = {}> {
sceneKey: string;
scene: Phaser.Scene;
scene: ReactiveScene<TData>;
autoStart: boolean;
data?: object;
data?: TData;
children?: any;
}
export const phaserSceneContext = createContext<ReadonlySignal<Phaser.Scene | undefined>>(signal(undefined));
export function PhaserScene(props: PhaserSceneProps) {
const context = useContext(phaserContext);
export function PhaserScene<TData extends Record<string, unknown> = {}>(props: PhaserSceneProps<TData>) {
const phaserGameSignal = useContext(phaserContext);
const sceneSignal = useSignal<Phaser.Scene>();
useSignalEffect(() => {
const game = context.value;
if (!game) return;
if (!phaserGameSignal) return;
const ctx = phaserGameSignal.value;
if (!ctx?.game) return;
game.scene.add(props.sceneKey, props.scene, props.autoStart, props.data);
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;
+1 -1
View File
@@ -1,5 +1,5 @@
export { GameUI } from './GameUI';
export type { GameUIOptions } from './GameUI';
export { PhaserGame, PhaserScene, phaserContext, defaultPhaserConfig } from './PhaserBridge';
export { PhaserGame, PhaserScene, phaserContext, defaultPhaserConfig, type PhaserGameContext } from './PhaserBridge';
export type { PhaserGameProps, PhaserSceneProps } from './PhaserBridge';