diff --git a/packages/framework/src/ui/PhaserBridge.tsx b/packages/framework/src/ui/PhaserBridge.tsx index a97db4c..af06895 100644 --- a/packages/framework/src/ui/PhaserBridge.tsx +++ b/packages/framework/src/ui/PhaserBridge.tsx @@ -9,6 +9,8 @@ import { FadeScene as FadeSceneClass, FADE_SCENE_KEY } from '../scenes/FadeScene export interface SceneController { /** 启动场景(带淡入淡出过渡) */ launch(sceneKey: string): Promise; + /** 重新启动当前场景(带淡入淡出过渡) */ + restart(): Promise; /** 当前活跃场景 key */ currentScene: ReadonlySignal; /** 是否正在过渡 */ @@ -105,6 +107,39 @@ export function PhaserGame(props: PhaserGameProps) { await fade.fadeIn(300); isTransitioning.value = false; }, + async restart() { + if (isTransitioning.value) { + console.warn('SceneController: 正在进行场景切换'); + return; + } + + if (!currentScene.value) { + console.warn('SceneController: 没有当前场景,无法 restart'); + return; + } + + const sceneKey = currentScene.value; + const scene = phaserGame.scene.getScene(sceneKey); + + if (!scene) { + console.error(`SceneController: 场景 "${sceneKey}" 不存在`); + return; + } + + isTransitioning.value = true; + const fade = phaserGame.scene.getScene(FADE_SCENE_KEY) as FadeSceneClass; + + // 淡出到黑色 + phaserGame.scene.bringToTop(FADE_SCENE_KEY); + await fade.fadeOut(300); + + // 重启当前场景 + scene.scene.restart(); + + // 淡入 + await fade.fadeIn(300); + isTransitioning.value = false; + }, currentScene, isTransitioning, }; diff --git a/packages/sts-like-viewer/src/scenes/GridViewerScene.ts b/packages/sts-like-viewer/src/scenes/GridViewerScene.ts index e332ae4..30b580a 100644 --- a/packages/sts-like-viewer/src/scenes/GridViewerScene.ts +++ b/packages/sts-like-viewer/src/scenes/GridViewerScene.ts @@ -167,20 +167,20 @@ export class GridViewerScene extends ReactiveScene { const { width, height } = this.scale; // Back button - this.createButton('返回菜单', 100, 40, () => { - this.scene.start('IndexScene'); + this.createButton('返回菜单', 100, 40, async () => { + await this.sceneController.launch('IndexScene'); }); // Clear button - this.createButton('清空', width - 260, 40, () => { + this.createButton('清空', width - 260, 40, async () => { this.inventory = createGridInventory(this.GRID_WIDTH, this.GRID_HEIGHT); - this.scene.restart(); + await this.sceneController.restart(); }); // Random fill button - this.createButton('随机填充', width - 130, 40, () => { + this.createButton('随机填充', width - 130, 40, async () => { this.randomFill(); - this.scene.restart(); + await this.sceneController.restart(); }); } diff --git a/packages/sts-like-viewer/src/scenes/IndexScene.ts b/packages/sts-like-viewer/src/scenes/IndexScene.ts index 0f04c57..845b9c6 100644 --- a/packages/sts-like-viewer/src/scenes/IndexScene.ts +++ b/packages/sts-like-viewer/src/scenes/IndexScene.ts @@ -63,8 +63,8 @@ export class IndexScene extends ReactiveScene { text.setScale(1); }); - bg.on('pointerdown', () => { - this.scene.start(targetScene); + bg.on('pointerdown', async () => { + await this.sceneController.launch(targetScene); }); } } diff --git a/packages/sts-like-viewer/src/scenes/MapViewerScene.ts b/packages/sts-like-viewer/src/scenes/MapViewerScene.ts index f2a9a54..da63648 100644 --- a/packages/sts-like-viewer/src/scenes/MapViewerScene.ts +++ b/packages/sts-like-viewer/src/scenes/MapViewerScene.ts @@ -85,8 +85,8 @@ export class MapViewerScene extends ReactiveScene { this.backButtonBg.setFillStyle(0x444466); this.backButtonText.setScale(1); }); - this.backButtonBg.on('pointerdown', () => { - this.scene.start('IndexScene'); + this.backButtonBg.on('pointerdown', async () => { + await this.sceneController.launch('IndexScene'); }); // Regenerate button diff --git a/packages/sts-like-viewer/src/scenes/ShapeViewerScene.ts b/packages/sts-like-viewer/src/scenes/ShapeViewerScene.ts index 2fb51d9..21616a4 100644 --- a/packages/sts-like-viewer/src/scenes/ShapeViewerScene.ts +++ b/packages/sts-like-viewer/src/scenes/ShapeViewerScene.ts @@ -126,8 +126,8 @@ export class ShapeViewerScene extends ReactiveScene { const { width, height } = this.scale; // Back button - this.createButton('返回菜单', 100, height - 40, () => { - this.scene.start('IndexScene'); + this.createButton('返回菜单', 100, height - 40, async () => { + await this.sceneController.launch('IndexScene'); }); // Info text