diff --git a/scenes/MenuScene.js b/scenes/MenuScene.js index 9c361b6..7ff6a26 100644 --- a/scenes/MenuScene.js +++ b/scenes/MenuScene.js @@ -63,6 +63,9 @@ export default class MenuScene extends Phaser.Scene { // 添加雨天效果控制按钮 this.createRainControlButton(); + + // 添加页面可见性变化监听,处理页面切出和切回的情况 + this.setupVisibilityChangeHandler(); } /** @@ -188,7 +191,7 @@ export default class MenuScene extends Phaser.Scene { // 控制雨滴和涟漪的显示/隐藏 this.updateRainEffectVisibility(); - // 如果关闭雨天效果,清除所有与涟漪相关的延迟调用 + // 如果关闭雨天效果,清除所有与涟漪相关的延迟调用、Tween动画和涟漪对象 if (!this.isRainEnabled) { // 清除所有涟漪相关的setTimeout this.rippleTimeouts.forEach(timeoutId => { @@ -196,13 +199,92 @@ export default class MenuScene extends Phaser.Scene { }); // 清空timeout ID数组 this.rippleTimeouts = []; + + // 清除所有与涟漪相关的Tween动画 + this.tweens.killTweensOf(this.rippleGroup.getChildren()); + + // 彻底清除所有涟漪对象 + this.rippleGroup.children.each(ripple => { + if (ripple && ripple.active) { + ripple.destroy(); + } + }); + + // 清空涟漪组 + this.rippleGroup.clear(true, true); } // 如果重新开启雨天效果,重新启动涟漪生成 else { + // 重新启动涟漪生成 this.createRainRipples(this.screenWidth, this.screenHeight); + + // 检查并重新启动雨滴的Tween动画(如果需要) + this.rainGroup.children.each(raindrop => { + // 检查雨滴是否存在且激活 + if (raindrop && raindrop.active) { + // 获取雨滴的当前Tween动画 + const tweens = this.tweens.getTweensOf(raindrop); + + // 如果没有运行中的Tween动画,重新创建雨滴动画 + if (tweens.length === 0) { + // 水平方向的位移量(相对单位),固定向左下方倾斜 + const horizontalOffset = -this.unit * Phaser.Math.Between(15, 17); // 固定向左方向,8-12单位 + + // 重新设置雨滴动画 + this.tweens.add({ + targets: raindrop, + x: raindrop.x + horizontalOffset, // 水平方向位移 + y: this.screenHeight + this.unit * 2, // 垂直方向位移 + duration: Phaser.Math.Between(1000, 1050), // 随机下落速度 + ease: 'Linear', + repeat: -1, // 无限重复 + delay: Phaser.Math.Between(0, 2000), // 随机延迟,使雨滴分布更均匀 + onRepeat: (tween, targets) => { + // 检查目标是否存在,防止场景重启时的错误 + if (targets[0] && targets[0].active) { + // 重置雨滴位置,考虑到斜向下落,初始x位置可以稍微超出屏幕边缘(相对单位) + const initialX = Phaser.Math.Between(-this.unit * 10, this.screenWidth + this.unit * 10); + targets[0].x = initialX; + targets[0].y = -this.unit * 2; + + // 更新动画的x目标值 + tween.data[0].value = initialX + horizontalOffset; + } + } + }); + } + } + }); } } + /** + * 设置页面可见性变化处理器 + */ + setupVisibilityChangeHandler() { + // 保存当前场景的引用 + const scene = this; + + // 页面可见性变化事件处理函数 + const handleVisibilityChange = () => { + if (document.hidden) { + // 页面变为不可见时 + scene.onPageHidden(); + } else { + // 页面变为可见时 + scene.onPageVisible(); + } + }; + + // 添加事件监听器 + document.addEventListener('visibilitychange', handleVisibilityChange); + + // 在场景销毁时移除事件监听器,防止内存泄漏 + this.events.on('destroy', () => { + document.removeEventListener('visibilitychange', handleVisibilityChange); + }); + } + /** * 更新雨天效果的可见性 */ @@ -218,6 +300,83 @@ export default class MenuScene extends Phaser.Scene { }); } + /** + * 页面变为不可见时的处理逻辑 + */ + onPageHidden() { + // 如果雨天效果是开启的,清除所有涟漪相关的延迟调用、Tween动画和涟漪对象 + if (this.isRainEnabled) { + // 清除所有涟漪相关的setTimeout + this.rippleTimeouts.forEach(timeoutId => { + clearTimeout(timeoutId); + }); + // 清空timeout ID数组 + this.rippleTimeouts = []; + + // 清除所有与涟漪相关的Tween动画 + this.tweens.killTweensOf(this.rippleGroup.getChildren()); + } + } + + /** + * 页面重新变为可见时的处理逻辑 + */ + onPageVisible() { + // 如果雨天效果是开启的,重新启动涟漪生成 + if (this.isRainEnabled) { + // 清理所有残留的涟漪对象 + this.rippleGroup.children.each(ripple => { + if (ripple && ripple.active) { + ripple.destroy(); + } + }); + + // 清空涟漪组 + this.rippleGroup.clear(true, true); + + // 重新启动涟漪生成 + this.createRainRipples(this.screenWidth, this.screenHeight); + + // 检查并重新启动雨滴的Tween动画(如果需要) + this.rainGroup.children.each(raindrop => { + // 检查雨滴是否存在且激活 + if (raindrop && raindrop.active) { + // 获取雨滴的当前Tween动画 + const tweens = this.tweens.getTweensOf(raindrop); + + // 如果没有运行中的Tween动画,重新创建雨滴动画 + if (tweens.length === 0) { + // 水平方向的位移量(相对单位),固定向左下方倾斜 + const horizontalOffset = -this.unit * Phaser.Math.Between(15, 17); // 固定向左方向,8-12单位 + + // 重新设置雨滴动画 + this.tweens.add({ + targets: raindrop, + x: raindrop.x + horizontalOffset, // 水平方向位移 + y: this.screenHeight + this.unit * 2, // 垂直方向位移 + duration: Phaser.Math.Between(1000, 1050), // 随机下落速度 + ease: 'Linear', + repeat: -1, // 无限重复 + delay: Phaser.Math.Between(0, 2000), // 随机延迟,使雨滴分布更均匀 + onRepeat: (tween, targets) => { + // 检查目标是否存在,防止场景重启时的错误 + if (targets[0] && targets[0].active) { + // 重置雨滴位置,考虑到斜向下落,初始x位置可以稍微超出屏幕边缘(相对单位) + const initialX = Phaser.Math.Between(-this.unit * 10, this.screenWidth + this.unit * 10); + targets[0].x = initialX; + targets[0].y = -this.unit * 2; + + // 更新动画的x目标值 + tween.data[0].value = initialX + horizontalOffset; + } + } + }); + } + } + }); + } + } + /** * 为开始和退出按钮添加点击功能 */ @@ -480,7 +639,8 @@ export default class MenuScene extends Phaser.Scene { ease: 'Sine.easeOut', onComplete: (tween, targets) => { // 动画完成后销毁涟漪 - if (targets[0] && targets[0].active) { + // 确保目标对象仍然存在且未被销毁 + if (targets && targets[0] && targets[0].scene && targets[0].active) { targets[0].destroy(); } }