Files
aibis-dream/Assets/Scripts/MiniGame/HuoShan/Language/WaveformPoint.cs
T
2025-11-12 19:46:16 +08:00

211 lines
8.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
}
}
}
}
}
}