using UnityEngine;
namespace AibisDream.MiniGame.Language
{
///
/// 波形点:管理单个波形点的状态和动画
///
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;
}
///
/// 生成多层Perlin噪声
///
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);
}
///
/// 更新波形点(动态噪波、交互、抚平)
///
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);
}
}
}
}
}
}