import Phaser from 'phaser'; import { effect, type ReadonlySignal } from '@preact/signals-core'; import { DisposableBag, type IDisposable } from '../utils'; type CleanupFn = void | (() => void); // 前向声明,避免循环导入 export interface SceneController { launch(sceneKey: string, data?: Record): Promise; currentScene: ReadonlySignal; isTransitioning: ReadonlySignal; } export interface ReactiveScenePhaserData { phaserGame: ReadonlySignal<{ game: Phaser.Game }>; sceneController: SceneController; } export interface ReactiveSceneOptions = {}> { key?: string; } /** * 通用的响应式 Scene 基类 * @typeparam TData - 通过 init(data) 接收的数据类型(必须包含 phaserGame 和 sceneController) */ export abstract class ReactiveScene = {}> extends Phaser.Scene implements IDisposable { protected disposables = new DisposableBag(); private _initData!: TData & ReactiveScenePhaserData; /** * 获取通过 init() 注入的数据 * 在 create() 阶段保证可用 */ public get initData(): TData & ReactiveScenePhaserData { return this._initData; } /** * 获取 Phaser game 实例的响应式信号 */ public get phaserGame(): ReadonlySignal<{ game: Phaser.Game }> { return this._initData.phaserGame; } /** * 获取场景控制器 */ public get sceneController(): SceneController { return this._initData.sceneController; } constructor(key?: string) { super(key); } init(data: TData & ReactiveScenePhaserData): void { this._initData = data; } create(): void { this.events.on('shutdown', this.dispose, this); } dispose(): void { this.disposables.dispose(); } public addDisposable(disposable: IDisposable): void { this.disposables.add(disposable); } /** 注册响应式监听(场景关闭时自动清理) */ public addEffect(fn: () => CleanupFn): void { this.disposables.add(effect(fn)); } }