90 lines
2.3 KiB
TypeScript
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__';
|