84 lines
2.0 KiB
TypeScript
84 lines
2.0 KiB
TypeScript
import { ReactiveScene } 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__";
|