mirror of
http://junepve.top:3000/chicrobot/CINC.git
synced 2026-10-30 05:41:29 +08:00
feat(menu) 添加雨天特效开启和关闭
This commit is contained in:
1 parent
cb5c7ac51b
commit
0765e44a02
3 files changed
+198
-38
No files matched your search
+1
-1
@@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Multi-Control Demo</title>
|
||||
<title>CINC</title>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
|
||||
+12
-3
@@ -3,16 +3,25 @@ export default {
|
||||
"#^": {
|
||||
"title": "#*^#",
|
||||
'start': "@%!$%",
|
||||
"exit": "#@*%"
|
||||
"exit": "#@*%",
|
||||
"rain": "$!*^",
|
||||
"on": "(^",
|
||||
"off": "($$"
|
||||
},
|
||||
"en": {
|
||||
"title": "CINC",
|
||||
"start": "start",
|
||||
"exit": "exit"
|
||||
"exit": "exit",
|
||||
"rain": "rain",
|
||||
"on": "on",
|
||||
"off": "off"
|
||||
},
|
||||
"中文": {
|
||||
"title": "游戏",
|
||||
"start": "开始",
|
||||
"exit": "退出"
|
||||
"exit": "退出",
|
||||
"rain": "雨天",
|
||||
"on": "开启",
|
||||
"off": "关闭"
|
||||
}
|
||||
}
|
||||
+185
-34
@@ -12,6 +12,19 @@ export default class MenuScene extends Phaser.Scene {
|
||||
// 获取主相机对象
|
||||
const cam = this.cameras.main;
|
||||
|
||||
// 获取屏幕尺寸,用于计算相对单位
|
||||
this.screenWidth = this.sys.game.config.width;
|
||||
this.screenHeight = this.sys.game.config.height;
|
||||
|
||||
// 计算相对单位:以屏幕高度为基准
|
||||
this.unit = this.screenHeight / 100;
|
||||
|
||||
// 初始化雨天效果状态
|
||||
this.isRainEnabled = true;
|
||||
|
||||
// 初始化setTimeout ID数组,用于管理所有与涟漪相关的延迟调用
|
||||
this.rippleTimeouts = [];
|
||||
|
||||
// 添加落雨落效果
|
||||
this.createRainEffect();
|
||||
|
||||
@@ -21,9 +34,9 @@ export default class MenuScene extends Phaser.Scene {
|
||||
// 添加菜单文本 - 使用多语言
|
||||
this.titleText = this.add.text(
|
||||
cam.centerX, // 文本在x轴上的位置,相机中心
|
||||
cam.centerY - 80, // 文本在y轴上的位置,相机中心上方
|
||||
cam.centerY - this.unit * 8, // 文本在y轴上的位置,相机中心上方
|
||||
LanguageManager.t('title'),
|
||||
{ fontSize: '24px', color: '#ffffff' }
|
||||
{ fontSize: this.unit * 2.4, color: '#ffffff' }
|
||||
).setOrigin(0.5, 0.5);
|
||||
|
||||
// 添加菜单文本 - 使用多语言
|
||||
@@ -31,15 +44,15 @@ export default class MenuScene extends Phaser.Scene {
|
||||
cam.centerX, // 文本在x轴上的位置,相机中心
|
||||
cam.centerY, // 文本在y轴上的位置,相机中心
|
||||
LanguageManager.t('start'),
|
||||
{ fontSize: '32px', color: '#ffffff' }
|
||||
{ fontSize: this.unit * 3.2, color: '#ffffff' }
|
||||
).setOrigin(0.5, 0.5);
|
||||
|
||||
// 添加退出按钮文本 - 使用多语言
|
||||
this.exitText = this.add.text(
|
||||
cam.centerX, // 文本在x轴上的位置,相机中心
|
||||
cam.centerY + 50, // 文本在y轴上的位置,开始按钮下方
|
||||
cam.centerY + this.unit * 5, // 文本在y轴上的位置,开始按钮下方
|
||||
LanguageManager.t('exit'),
|
||||
{ fontSize: '24px', color: '#ffffff' }
|
||||
{ fontSize: this.unit * 2.4, color: '#ffffff' }
|
||||
).setOrigin(0.5, 0.5);
|
||||
|
||||
// 为开始和退出按钮添加点击功能
|
||||
@@ -47,6 +60,9 @@ export default class MenuScene extends Phaser.Scene {
|
||||
|
||||
// 添加语言切换按钮(仅用于测试)
|
||||
this.createLanguageToggle();
|
||||
|
||||
// 添加雨天效果控制按钮
|
||||
this.createRainControlButton();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,22 +74,22 @@ export default class MenuScene extends Phaser.Scene {
|
||||
let currentLangIndex = languages.indexOf(LanguageManager.currentLanguage);
|
||||
|
||||
// 按钮基础位置(在退出按钮下方)
|
||||
const baseY = cam.centerY + 110;
|
||||
const baseY = cam.centerY + this.unit * 11;
|
||||
|
||||
// 创建主按钮文本
|
||||
const toggleText = this.add.text(
|
||||
cam.centerX,
|
||||
baseY,
|
||||
`${LanguageManager.currentLanguage}`,
|
||||
{ fontSize: '16px', color: '#ffffff' }
|
||||
{ fontSize: this.unit * 1.6, color: '#ffffff' }
|
||||
).setOrigin(0.5, 0.5);
|
||||
|
||||
// 创建倒影文本
|
||||
const reflectionText = this.add.text(
|
||||
cam.centerX,
|
||||
baseY + 20, // 倒影位置在主文本下方
|
||||
baseY + this.unit * 2, // 倒影位置在主文本下方
|
||||
`${LanguageManager.currentLanguage}`,
|
||||
{ fontSize: '16px', color: '#ffffff' }
|
||||
{ fontSize: this.unit * 1.6, color: '#ffffff' }
|
||||
).setOrigin(0.5, 0.5);
|
||||
|
||||
// 设置倒影效果
|
||||
@@ -86,9 +102,9 @@ export default class MenuScene extends Phaser.Scene {
|
||||
// 创建透明的点击区域(与文本大小匹配)
|
||||
const clickArea = this.add.rectangle(
|
||||
cam.centerX,
|
||||
baseY,
|
||||
baseY + this.unit,
|
||||
toggleText.width,
|
||||
toggleText.height,
|
||||
toggleText.height + this.unit * 2,
|
||||
0x000000,
|
||||
0 // 完全透明
|
||||
).setOrigin(0.5, 0.5);
|
||||
@@ -115,6 +131,90 @@ export default class MenuScene extends Phaser.Scene {
|
||||
this.titleText.setText(LanguageManager.t('title'));
|
||||
this.startText.setText(LanguageManager.t('start'));
|
||||
this.exitText.setText(LanguageManager.t('exit'));
|
||||
|
||||
// 更新雨天控制按钮文本
|
||||
const rainText = LanguageManager.t('rain');
|
||||
const stateText = this.isRainEnabled ? LanguageManager.t('on') : LanguageManager.t('off');
|
||||
this.rainToggleText.setText(`${rainText} ${stateText}`);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建雨天效果控制按钮
|
||||
*/
|
||||
createRainControlButton() {
|
||||
const cam = this.cameras.main;
|
||||
|
||||
// 按钮基础位置(在语言切换按钮下方)
|
||||
const baseY = cam.centerY + this.unit * 17;
|
||||
|
||||
// 创建主按钮文本
|
||||
this.rainToggleText = this.add.text(
|
||||
cam.centerX,
|
||||
baseY,
|
||||
LanguageManager.t('rain')+" "+LanguageManager.t('on'),
|
||||
{ fontSize: this.unit * 1.6, color: '#ffffff' }
|
||||
).setOrigin(0.5, 0.5);
|
||||
|
||||
// 创建透明的点击区域(与文本大小匹配)
|
||||
this.rainClickArea = this.add.rectangle(
|
||||
cam.centerX,
|
||||
baseY,
|
||||
this.rainToggleText.width + 40,
|
||||
this.rainToggleText.height + 20,
|
||||
0x000000,
|
||||
0 // 完全透明
|
||||
).setOrigin(0.5, 0.5);
|
||||
|
||||
// 设置点击区域可交互
|
||||
this.rainClickArea.setInteractive({ useHandCursor: true });
|
||||
|
||||
// 添加点击事件
|
||||
this.rainClickArea.on('pointerdown', () => {
|
||||
this.toggleRainEffect();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换雨天效果的开启和关闭
|
||||
*/
|
||||
toggleRainEffect() {
|
||||
// 切换雨天效果状态
|
||||
this.isRainEnabled = !this.isRainEnabled;
|
||||
|
||||
// 更新按钮文本
|
||||
this.rainToggleText.setText(this.isRainEnabled ? `${LanguageManager.t('rain')} ${LanguageManager.t('on')}` : `${LanguageManager.t('rain')} ${LanguageManager.t('off')}`);
|
||||
|
||||
// 控制雨滴和涟漪的显示/隐藏
|
||||
this.updateRainEffectVisibility();
|
||||
|
||||
// 如果关闭雨天效果,清除所有与涟漪相关的延迟调用
|
||||
if (!this.isRainEnabled) {
|
||||
// 清除所有涟漪相关的setTimeout
|
||||
this.rippleTimeouts.forEach(timeoutId => {
|
||||
clearTimeout(timeoutId);
|
||||
});
|
||||
// 清空timeout ID数组
|
||||
this.rippleTimeouts = [];
|
||||
}
|
||||
// 如果重新开启雨天效果,重新启动涟漪生成
|
||||
else {
|
||||
this.createRainRipples(this.screenWidth, this.screenHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新雨天效果的可见性
|
||||
*/
|
||||
updateRainEffectVisibility() {
|
||||
// 控制雨滴的显示/隐藏
|
||||
this.rainGroup.children.each(raindrop => {
|
||||
raindrop.visible = this.isRainEnabled;
|
||||
});
|
||||
|
||||
// 控制涟漪的显示/隐藏
|
||||
this.rippleGroup.children.each(ripple => {
|
||||
ripple.visible = this.isRainEnabled;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -139,7 +239,7 @@ export default class MenuScene extends Phaser.Scene {
|
||||
startClickArea.on('pointerover', () => {
|
||||
this.tweens.add({
|
||||
targets: this.startText,
|
||||
y: this.startText.y - 5, // 字体上移
|
||||
y: this.startText.y - this.unit * 0.5, // 字体上移
|
||||
duration: 100,
|
||||
ease: 'Sine.easeOut'
|
||||
});
|
||||
@@ -149,7 +249,7 @@ export default class MenuScene extends Phaser.Scene {
|
||||
startClickArea.on('pointerout', () => {
|
||||
this.tweens.add({
|
||||
targets: this.startText,
|
||||
y: this.startText.y + 5, // 字体恢复原位
|
||||
y: this.startText.y + this.unit * 0.5, // 字体恢复原位
|
||||
duration: 100,
|
||||
ease: 'Sine.easeOut'
|
||||
});
|
||||
@@ -183,7 +283,7 @@ export default class MenuScene extends Phaser.Scene {
|
||||
exitClickArea.on('pointerover', () => {
|
||||
this.tweens.add({
|
||||
targets: this.exitText,
|
||||
y: this.exitText.y - 5, // 字体上移
|
||||
y: this.exitText.y - this.unit * 0.5, // 字体上移
|
||||
duration: 100,
|
||||
ease: 'Sine.easeOut'
|
||||
});
|
||||
@@ -193,7 +293,7 @@ export default class MenuScene extends Phaser.Scene {
|
||||
exitClickArea.on('pointerout', () => {
|
||||
this.tweens.add({
|
||||
targets: this.exitText,
|
||||
y: this.exitText.y + 5, // 字体恢复原位
|
||||
y: this.exitText.y + this.unit * 0.5, // 字体恢复原位
|
||||
duration: 100,
|
||||
ease: 'Sine.easeOut'
|
||||
});
|
||||
@@ -219,7 +319,7 @@ export default class MenuScene extends Phaser.Scene {
|
||||
// 创建波纹动画
|
||||
this.tweens.add({
|
||||
targets: text,
|
||||
y: originalY + 5, // 上下波动
|
||||
y: originalY + this.unit * 0.5, // 上下波动
|
||||
duration: 1500,
|
||||
ease: 'Sine.easeInOut',
|
||||
yoyo: true,
|
||||
@@ -254,6 +354,9 @@ export default class MenuScene extends Phaser.Scene {
|
||||
// 创建雨滴精灵组
|
||||
this.rainGroup = this.add.group();
|
||||
|
||||
// 创建涟漪组,用于管理所有涟漪效果
|
||||
this.rippleGroup = this.add.group();
|
||||
|
||||
// 雨的参数
|
||||
const rainCount = 50; // 雨滴数量
|
||||
const screenWidth = this.sys.game.config.width;
|
||||
@@ -263,10 +366,10 @@ export default class MenuScene extends Phaser.Scene {
|
||||
for (let i = 0; i < rainCount; i++) {
|
||||
// 创建雨滴精灵(使用简单的白色矩形)
|
||||
const raindrop = this.add.rectangle(
|
||||
Phaser.Math.Between(0, screenWidth), // 随机x位置
|
||||
Phaser.Math.Between(0, screenWidth * 1.2), // 随机x位置,从屏幕右侧外开始
|
||||
Phaser.Math.Between(-screenHeight, 0), // 初始y位置在屏幕上方
|
||||
2, // 雨滴宽度
|
||||
10, // 雨滴高度
|
||||
this.unit * 0.2, // 雨滴宽度
|
||||
this.unit * 1, // 雨滴高度
|
||||
0xffffff, // 白色
|
||||
0.3 // 半透明
|
||||
);
|
||||
@@ -274,20 +377,29 @@ export default class MenuScene extends Phaser.Scene {
|
||||
// 添加到组
|
||||
this.rainGroup.add(raindrop);
|
||||
|
||||
// 设置雨滴动画 - 斜向落下(固定方向)
|
||||
// 水平方向的位移量(相对单位),固定向左下方倾斜
|
||||
const horizontalOffset = -this.unit * Phaser.Math.Between(15, 17); // 固定向左方向,8-12单位
|
||||
|
||||
// 设置雨滴动画
|
||||
this.tweens.add({
|
||||
targets: raindrop,
|
||||
y: screenHeight + 20, // 下落到底部
|
||||
duration: Phaser.Math.Between(1000, 2000), // 随机下落速度
|
||||
x: raindrop.x + horizontalOffset, // 水平方向位移
|
||||
y: 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) {
|
||||
// 重置雨滴位置
|
||||
targets[0].x = Phaser.Math.Between(0, screenWidth);
|
||||
targets[0].y = -20;
|
||||
// 重置雨滴位置,考虑到斜向下落,初始x位置可以稍微超出屏幕边缘(相对单位)
|
||||
const initialX = Phaser.Math.Between(-this.unit * 10, screenWidth + this.unit * 10);
|
||||
targets[0].x = initialX;
|
||||
targets[0].y = -this.unit * 2;
|
||||
|
||||
// 更新动画的x目标值
|
||||
tween.data[0].value = initialX + horizontalOffset;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -303,14 +415,20 @@ export default class MenuScene extends Phaser.Scene {
|
||||
* @param {number} screenHeight - 屏幕高度
|
||||
*/
|
||||
createRainRipples(screenWidth, screenHeight) {
|
||||
// 涟漪数量
|
||||
const rippleCount = 15;
|
||||
// 只有在雨天效果开启时,才创建涟漪
|
||||
if (this.isRainEnabled) {
|
||||
// 增加涟漪数量
|
||||
const rippleCount = 25;
|
||||
|
||||
for (let i = 0; i < rippleCount; i++) {
|
||||
// 随机延迟开始
|
||||
setTimeout(() => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
this.createSingleRipple(screenWidth, screenHeight);
|
||||
}, Phaser.Math.Between(0, 2000));
|
||||
}, Phaser.Math.Between(0, 3000));
|
||||
|
||||
// 将timeout ID保存到数组中
|
||||
this.rippleTimeouts.push(timeoutId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,6 +442,15 @@ export default class MenuScene extends Phaser.Scene {
|
||||
const x = Phaser.Math.Between(0, screenWidth);
|
||||
const y = Phaser.Math.Between(0, screenHeight); // 整个屏幕高度
|
||||
|
||||
// 每个雨滴产生多个同心涟漪
|
||||
const rippleLayers = 3;
|
||||
const baseDelay = 100;
|
||||
|
||||
for (let i = 0; i < rippleLayers; i++) {
|
||||
// 延迟创建后续的涟漪层
|
||||
const timeoutId = setTimeout(() => {
|
||||
// 只有在雨天效果开启时,才创建新的涟漪
|
||||
if (this.isRainEnabled) {
|
||||
// 创建涟漪圆圈(只保留边框)
|
||||
const ripple = this.add.circle(
|
||||
x,
|
||||
@@ -331,24 +458,48 @@ export default class MenuScene extends Phaser.Scene {
|
||||
0, // 初始半径
|
||||
0xffffff, // 白色
|
||||
0 // 透明填充
|
||||
).setStrokeStyle(1, 0xffffff, 0.2); // 1像素白色边框,半透明
|
||||
).setStrokeStyle(this.unit * 0.08, 0xffffff, 0.3); // 更细的边框,更高的透明度
|
||||
|
||||
// 将涟漪添加到涟漪组中
|
||||
this.rippleGroup.add(ripple);
|
||||
|
||||
// 随机化每个涟漪的参数,增加自然感
|
||||
const maxRadius = this.unit * Phaser.Math.Between(2, 3);
|
||||
const duration = Phaser.Math.Between(800, 1500);
|
||||
const startAlpha = Phaser.Math.Between(0.3, 0.5);
|
||||
|
||||
// 设置初始透明度
|
||||
ripple.setAlpha(startAlpha);
|
||||
|
||||
// 创建扩散动画
|
||||
this.tweens.add({
|
||||
targets: ripple,
|
||||
radius: 20, // 最大半径
|
||||
radius: maxRadius, // 最大半径
|
||||
alpha: 0, // 逐渐消失
|
||||
duration: 1000, // 动画持续时间
|
||||
duration: duration, // 动画持续时间
|
||||
ease: 'Sine.easeOut',
|
||||
onComplete: (tween, targets) => {
|
||||
// 动画完成后销毁涟漪
|
||||
if (targets[0] && targets[0].active) {
|
||||
targets[0].destroy();
|
||||
}
|
||||
|
||||
// 递归创建新的涟漪
|
||||
this.createSingleRipple(screenWidth, screenHeight);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, i * baseDelay);
|
||||
|
||||
// 将timeout ID保存到数组中
|
||||
this.rippleTimeouts.push(timeoutId);
|
||||
}
|
||||
|
||||
// 只有在雨天效果开启时,才递归创建新的涟漪
|
||||
if (this.isRainEnabled) {
|
||||
const timeoutId = setTimeout(() => {
|
||||
this.createSingleRipple(screenWidth, screenHeight);
|
||||
}, Phaser.Math.Between(500, 1500));
|
||||
|
||||
// 将递归调用的timeout ID保存到数组中
|
||||
this.rippleTimeouts.push(timeoutId);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user