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

90 lines
2.3 KiB
TypeScript

import Phaser from 'phaser';
import { ReactiveScene, type ReactiveScenePhaserData } from './ReactiveScene';
export interface FadeSceneData {
[key: string]: unknown;
}
/**
* 处理淡入淡出到黑色的过渡场景
*/
export class FadeScene extends ReactiveScene<FadeSceneData> {
private overlay!: Phaser.GameObjects.Rectangle;
private isFading = false;
constructor() {
super(FADE_SCENE_KEY);
}
create(): void {
super.create();
// 创建黑色遮罩层,覆盖整个游戏区域
const game = this.game;
this.overlay = this.add.rectangle(
0,
0,
game.scale.width,
game.scale.height,
0x000000,
1
).setOrigin(0)
.setAlpha(1)
.setDepth(999999)
.setInteractive({ useHandCursor: false });
// 防止遮罩阻挡输入
this.overlay.disableInteractive();
}
/**
* 淡入(从黑色到透明)
* @param duration 动画时长(毫秒)
*/
fadeIn(duration = 300): Promise<void> {
return this.fadeTo(0, duration);
}
/**
* 淡出(从透明到黑色)
* @param duration 动画时长(毫秒)
*/
fadeOut(duration = 300): Promise<void> {
return this.fadeTo(1, duration);
}
/**
* 淡入淡出到指定透明度
*/
private fadeTo(targetAlpha: number, duration: number): Promise<void> {
// 如果 overlay 还未初始化,直接返回 resolved promise
if (!this.overlay) {
console.warn('FadeScene: overlay 未初始化,跳过过渡动画');
return Promise.resolve();
}
if (this.isFading) {
console.warn('FadeScene: 正在进行过渡动画');
}
this.isFading = true;
this.overlay.setAlpha(targetAlpha === 1 ? 0 : 1);
return new Promise<void>((resolve) => {
this.tweens.add({
targets: this.overlay,
alpha: targetAlpha,
duration,
ease: 'Linear',
onComplete: () => {
this.isFading = false;
resolve();
},
});
});
}
}
// 导出常量供 PhaserGame 使用
export const FADE_SCENE_KEY = '__fade__';