211 lines
8.4 KiB
C#
211 lines
8.4 KiB
C#
using UnityEngine;
|
||
|
||
namespace AibisDream.MiniGame.Language
|
||
{
|
||
/// <summary>
|
||
/// 波形点:管理单个波形点的状态和动画
|
||
/// </summary>
|
||
public class WaveformPoint
|
||
{
|
||
// 位置
|
||
public float x; // X坐标(跟随文字)
|
||
public float y; // 当前Y坐标
|
||
public float targetY; // 目标Y坐标(规律波形)
|
||
public float smoothedY; // 平滑后的Y坐标
|
||
|
||
// 噪声参数
|
||
public float noiseOffset; // 噪声偏移
|
||
public float noiseScale1; // 噪声缩放1(低频)
|
||
public float noiseScale2; // 噪声缩放2(中频)
|
||
public float noiseScale3; // 噪声缩放3(高频)
|
||
public float noiseAmplitude; // 噪声振幅
|
||
public float noiseTime; // 噪声时间偏移
|
||
|
||
// 抚平状态
|
||
public float resistance; // 抵抗力(0-1,越高越难抚平)
|
||
public float calmAmount; // 当前被抚平的程度(0-1)
|
||
public bool isBeingCalmed; // 是否正在被抚平
|
||
public float calmTimer; // 抚平计时器
|
||
|
||
// 关联
|
||
public CandidateParticle particle; // 关联的文字粒子
|
||
public int particleIndex; // 粒子索引
|
||
|
||
// 脉冲动画
|
||
public float pulseProgress; // 脉冲进度(0-1)
|
||
|
||
public WaveformPoint(float x, float baseY, float amplitude, int index, CandidateParticle particle)
|
||
{
|
||
this.x = x;
|
||
this.particle = particle;
|
||
this.particleIndex = index;
|
||
|
||
// 初始化噪声参数
|
||
noiseScale1 = 0.05f;
|
||
noiseScale2 = 0.15f;
|
||
noiseScale3 = 0.4f;
|
||
noiseAmplitude = Random.Range(0.7f, 1f);
|
||
noiseOffset = Random.Range(-0.2f, 0.2f);
|
||
noiseTime = Random.Range(0f, 1000f);
|
||
|
||
// 计算初始Y(噪波)
|
||
float combinedNoise = GenerateNoise(Time.time);
|
||
y = baseY + combinedNoise * amplitude;
|
||
smoothedY = y;
|
||
|
||
// 计算目标Y(规律波形)
|
||
float targetWavePhase = index * 0.3f;
|
||
float targetWaveAmplitude = amplitude * 0.3f;
|
||
targetY = baseY + Mathf.Sin(targetWavePhase) * targetWaveAmplitude;
|
||
|
||
// 计算异常程度和抵抗力
|
||
float anomalyAmount = Mathf.Abs(y - targetY) / amplitude;
|
||
resistance = 0.1f + anomalyAmount * 0.25f;
|
||
|
||
calmAmount = 0f;
|
||
isBeingCalmed = false;
|
||
calmTimer = 0f;
|
||
pulseProgress = 0f;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成多层Perlin噪声
|
||
/// </summary>
|
||
private float GenerateNoise(float time)
|
||
{
|
||
// 使用多层噪声叠加
|
||
float noiseValue1 = Mathf.PerlinNoise(x * noiseScale1, time * 0.01f);
|
||
float noiseValue2 = Mathf.PerlinNoise(x * noiseScale2, time * 0.02f + 100f);
|
||
float noiseValue3 = Mathf.PerlinNoise(x * noiseScale3, time * 0.03f + 200f);
|
||
|
||
// 映射到[-1, 1]范围
|
||
noiseValue1 = (noiseValue1 - 0.5f) * 2f;
|
||
noiseValue2 = (noiseValue2 - 0.5f) * 2f * 0.6f;
|
||
noiseValue3 = (noiseValue3 - 0.5f) * 2f * 0.3f;
|
||
|
||
// 叠加
|
||
float combinedNoise = noiseValue1 + noiseValue2 + noiseValue3 + noiseOffset;
|
||
return Mathf.Clamp(combinedNoise * noiseAmplitude, -1.5f, 1.5f);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新波形点(动态噪波、交互、抚平)
|
||
/// </summary>
|
||
public void Update(float baseY, float amplitude, Vector2 mousePos, bool mousePressed, float mouseDragSpeed, float interactionRadius)
|
||
{
|
||
// 同步X位置(跟随文字)
|
||
if (particle != null)
|
||
{
|
||
x = particle.transform.position.x;
|
||
|
||
// 更新目标位置
|
||
float targetWavePhase = particleIndex * 0.3f;
|
||
float targetWaveAmplitude = amplitude * 0.3f;
|
||
targetY = baseY + Mathf.Sin(targetWavePhase) * targetWaveAmplitude;
|
||
}
|
||
|
||
// 重置状态
|
||
isBeingCalmed = false;
|
||
|
||
// 如果未抚平,添加动态噪波
|
||
if (calmAmount < 0.9f)
|
||
{
|
||
float currentTime = Time.time + noiseTime * 0.001f;
|
||
float dynamicNoise = GenerateNoise(currentTime);
|
||
|
||
// 根据抚平程度减少噪波强度
|
||
float noiseIntensity = (1 - calmAmount) * amplitude;
|
||
smoothedY = y + dynamicNoise * noiseIntensity;
|
||
}
|
||
|
||
// 处理鼠标交互
|
||
if (mousePressed)
|
||
{
|
||
float distToMouse = Vector2.Distance(mousePos, new Vector2(x, smoothedY));
|
||
if (distToMouse < interactionRadius)
|
||
{
|
||
// 计算影响强度
|
||
float distanceInfluence = Mathf.Lerp(1f, 0f, distToMouse / interactionRadius);
|
||
float speedBonus = Mathf.Min(1f, mouseDragSpeed / 0.25f); // 拖动速度加成
|
||
float influence = distanceInfluence * (0.5f + speedBonus * 0.5f);
|
||
|
||
// 标记为正在被抚平
|
||
isBeingCalmed = true;
|
||
calmTimer += Time.deltaTime;
|
||
|
||
// 需要持续按住才能抚平(抵抗机制)
|
||
float requiredTime = 0.5f + resistance * 1f; // 需要0.5-1.5秒
|
||
float calmProgressLocal = Mathf.Min(1f, calmTimer / requiredTime);
|
||
|
||
// 应用抚平效果(考虑抵抗力)
|
||
float calmStrength = influence * (1 - resistance) * 0.15f;
|
||
|
||
// 计算目标位置(从噪波位置向规律波形位置过渡)
|
||
float targetYLerp = Mathf.Lerp(y, targetY, calmProgressLocal);
|
||
smoothedY = Mathf.Lerp(smoothedY, targetYLerp, calmStrength);
|
||
|
||
// 更新抚平程度(一旦抚平,就不会恢复)
|
||
if (calmProgressLocal > calmAmount)
|
||
{
|
||
calmAmount = calmProgressLocal;
|
||
}
|
||
|
||
// 如果完全抚平
|
||
if (calmAmount >= 0.95f)
|
||
{
|
||
calmAmount = 1f;
|
||
smoothedY = targetY;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果calmAmount接近1,强制向目标位置靠拢
|
||
if (calmAmount > 0.8f)
|
||
{
|
||
float forceStrength = Mathf.Lerp(0.1f, 0.5f, (calmAmount - 0.8f) / 0.2f);
|
||
smoothedY = Mathf.Lerp(smoothedY, targetY, forceStrength);
|
||
}
|
||
|
||
// 如果完全抚平,直接设置为目标位置
|
||
if (calmAmount >= 1f)
|
||
{
|
||
smoothedY = targetY;
|
||
}
|
||
|
||
// 限制波形点不会完全超出范围
|
||
float maxDeviation = amplitude * (1 - calmAmount * 0.8f);
|
||
smoothedY = Mathf.Clamp(smoothedY, baseY - maxDeviation, baseY + maxDeviation);
|
||
|
||
// 同步更新对应文字粒子的平静进度
|
||
if (particle != null)
|
||
{
|
||
particle.calmProgress = calmAmount;
|
||
|
||
// 如果完全抚平,标记为已稳定
|
||
if (calmAmount >= 0.95f && !particle.isCalmed)
|
||
{
|
||
particle.isCalmed = true;
|
||
particle.isStatic = true;
|
||
particle.changeSpeedMultiplier = 0;
|
||
particle.dissolveProgress = 0;
|
||
}
|
||
|
||
// 如果已抚平,检查波形是否完全稳定
|
||
if (particle.isCalmed)
|
||
{
|
||
float distanceToTarget = Mathf.Abs(smoothedY - targetY);
|
||
float stabilityThreshold = amplitude * 0.05f;
|
||
|
||
if (distanceToTarget < stabilityThreshold)
|
||
{
|
||
// 波形已稳定,开始消散
|
||
float dissolveSpeed = 0.02f + (calmAmount - 0.95f) * 0.15f;
|
||
particle.dissolveProgress = Mathf.Min(1f, particle.dissolveProgress + dissolveSpeed * Time.deltaTime * 50f);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|