boardgame-phaser/packages/framework/src/scenes/ReactiveScene.ts

81 lines
2.1 KiB
TypeScript
Raw Normal View History

2026-04-12 16:26:52 +08:00
import Phaser from 'phaser';
2026-04-12 16:52:53 +08:00
import { effect, type ReadonlySignal } from '@preact/signals-core';
2026-04-12 16:26:52 +08:00
import { DisposableBag, type IDisposable } from '../utils';
type CleanupFn = void | (() => void);
2026-04-12 16:52:53 +08:00
// 前向声明,避免循环导入
export interface SceneController {
launch(sceneKey: string, data?: Record<string, unknown>): Promise<void>;
currentScene: ReadonlySignal<string | null>;
isTransitioning: ReadonlySignal<boolean>;
2026-04-12 16:26:52 +08:00
}
export interface ReactiveScenePhaserData {
2026-04-12 16:52:53 +08:00
phaserGame: ReadonlySignal<{ game: Phaser.Game }>;
sceneController: SceneController;
2026-04-12 16:26:52 +08:00
}
export interface ReactiveSceneOptions<TData extends Record<string, unknown> = {}> {
key?: string;
}
/**
* Scene
2026-04-12 16:52:53 +08:00
* @typeparam TData - init(data) phaserGame sceneController
2026-04-12 16:26:52 +08:00
*/
export abstract class ReactiveScene<TData extends Record<string, unknown> = {}>
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
*/
2026-04-12 16:52:53 +08:00
public get phaserGame(): ReadonlySignal<{ game: Phaser.Game }> {
2026-04-12 16:26:52 +08:00
return this._initData.phaserGame;
}
2026-04-12 16:52:53 +08:00
/**
*
*/
public get sceneController(): SceneController {
return this._initData.sceneController;
}
2026-04-12 16:26:52 +08:00
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));
}
}