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
+5 -31
View File
@@ -1,24 +1,18 @@
import Phaser from 'phaser';
import { effect } from '@preact/signals-core';
import type { GameHost } from 'boardgame-core';
import { DisposableBag, type IDisposable } from '../utils';
type CleanupFn = void | (() => void);
import { ReactiveScene, type ReactiveScenePhaserData } from './ReactiveScene';
export interface GameHostSceneOptions<TState extends Record<string, unknown>> {
gameHost: GameHost<TState>;
[key: string]: unknown;
}
export abstract class GameHostScene<TState extends Record<string, unknown>>
extends Phaser.Scene
implements IDisposable
extends ReactiveScene<GameHostSceneOptions<TState>>
{
protected disposables = new DisposableBag();
private _gameHost!: GameHost<TState>;
public get gameHost(): GameHost<TState> {
return this._gameHost;
return this.initData.gameHost as GameHost<TState>;
}
public get state(): TState {
return this.gameHost?.state.value;
}
@@ -32,24 +26,4 @@ export abstract class GameHostScene<TState extends Record<string, unknown>>
resolve => tween.once('complete', resolve)
));
}
init(data: GameHostSceneOptions<TState>): void {
this._gameHost = data.gameHost;
}
create(): void {
this.events.on('shutdown', this.dispose, this);
}
dispose(): void {
this.disposables.dispose();
}
public addDisposable(disposable: IDisposable){
this.disposables.add(disposable);
}
/** 注册响应式监听(场景关闭时自动清理) */
public addEffect(fn: () => CleanupFn): void {
this.disposables.add(effect(fn));
}
}
@@ -0,0 +1,69 @@
import Phaser from 'phaser';
import { effect } from '@preact/signals-core';
import { DisposableBag, type IDisposable } from '../utils';
type CleanupFn = void | (() => void);
export interface PhaserGameContext {
game: Phaser.Game;
}
export interface ReactiveScenePhaserData {
phaserGame: PhaserGameContext;
}
export interface ReactiveSceneOptions<TData extends Record<string, unknown> = {}> {
key?: string;
}
/**
* 通用的响应式 Scene 基类
* @typeparam TData - 通过 init(data) 接收的数据类型(必须包含 phaserGame
*/
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 实例的响应式信号
*/
public get phaserGame(): PhaserGameContext {
return this._initData.phaserGame;
}
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));
}
}
+3
View File
@@ -1,2 +1,5 @@
export { ReactiveScene } from './ReactiveScene';
export type { ReactiveSceneOptions, ReactiveScenePhaserData } from './ReactiveScene';
export { GameHostScene } from './GameHostScene';
export type { GameHostSceneOptions } from './GameHostScene';