using UnityEngine;
using System.Collections.Generic;
using Shapes;
namespace AibisDream.MiniGame.Language
{
///
/// 波形渲染器:使用Shapes绘制波形和交互效果
/// 注意:渲染在底层,确保低于文字(文字 sortingOrder = 10)
///
[ExecuteAlways]
public class WaveformRenderer : ImmediateModeShapeDrawer
{
[Header("波形设置")]
public Color normalWaveColor = new Color(0.59f, 0.78f, 1f, 0.8f);
public Color anxiousWaveColor = new Color(1f, 0.39f, 0.39f, 0.8f);
public float waveLineThickness = 0.04f;
public float baseY = 0f;
[Header("交互设置")]
public Color interactionColor = new Color(0.59f, 0.78f, 1f, 0.3f);
public Color interactionRingColor = new Color(0.59f, 0.78f, 1f, 0.6f);
public float interactionRadius = 0.5f;
[Header("粒子效果")]
public Color particleColor = new Color(0.59f, 0.78f, 1f, 0.8f);
private List waveformPoints;
private CompletionPhase completionPhase;
private float calmProgress;
private Vector2 mouseWorldPos;
private bool mousePressed;
private float mouseDragSpeed;
private List waveParticles = new List();
public void SetData(
List points,
CompletionPhase phase,
float calm,
Vector2 mousePos,
bool mouseDown,
float dragSpeed)
{
waveformPoints = points;
completionPhase = phase;
calmProgress = calm;
mouseWorldPos = mousePos;
mousePressed = mouseDown;
mouseDragSpeed = dragSpeed;
}
private void Update()
{
// 更新粒子效果
for (int i = waveParticles.Count - 1; i >= 0; i--)
{
waveParticles[i].Update(Time.deltaTime);
if (waveParticles[i].alpha <= 0 || waveParticles[i].size < 0.01f)
{
waveParticles.RemoveAt(i);
}
}
// 生成新粒子(如果正在交互)
if (mousePressed && waveformPoints != null && Random.value > 0.7f)
{
foreach (var point in waveformPoints)
{
if (point.isBeingCalmed && Random.value > 0.5f)
{
waveParticles.Add(new WaveformParticleEffect(
new Vector3(point.x, point.smoothedY, 0),
Random.Range(-0.1f, 0.1f),
Random.Range(-0.2f, -0.05f),
Random.Range(0.02f, 0.04f)
));
}
}
}
}
public override void DrawShapes(Camera cam)
{
if (waveformPoints == null || waveformPoints.Count == 0)
return;
if (completionPhase != CompletionPhase.Focusing)
return;
using (Draw.Command(cam))
{
Draw.BlendMode = ShapesBlendMode.Transparent;
Draw.ZTest = UnityEngine.Rendering.CompareFunction.Always;
// 注意:波形默认在底层,文字的 sortingOrder = 10 会显示在上层
// 绘制粒子效果
DrawWaveformParticles();
// 绘制波形线
DrawWaveformLine();
// 绘制波形点
DrawWaveformPoints();
// 绘制交互反馈
if (mousePressed)
{
DrawInteractionFeedback();
}
// 绘制基准线
if (calmProgress < 0.9f)
{
DrawBaseline();
}
}
}
private void DrawWaveformParticles()
{
foreach (var particle in waveParticles)
{
Color color = particleColor;
color.a = particle.alpha;
Draw.Disc(particle.position, particle.size, color);
// 光晕
color.a = particle.alpha * 0.3f;
Draw.Disc(particle.position, particle.size * 2f, color);
}
}
private void DrawWaveformLine()
{
Draw.LineGeometry = LineGeometry.Flat2D;
Draw.Thickness = waveLineThickness;
// 使用Polyline绘制波形
var points = new List();
var colors = new List();
foreach (var point in waveformPoints)
{
// 跳过完全消散的点
float dissolveProgress = point.particle != null ? point.particle.dissolveProgress : 0f;
if (dissolveProgress >= 1f) continue;
points.Add(new Vector3(point.x, point.smoothedY, 0));
// 根据抚平程度混合颜色
Color waveColor = Color.Lerp(anxiousWaveColor, normalWaveColor, point.calmAmount);
waveColor.a *= (1 - dissolveProgress);
colors.Add(waveColor);
}
if (points.Count >= 2)
{
for (int i = 0; i < points.Count - 1; i++)
{
Draw.Line(points[i], points[i + 1], colors[i], colors[i + 1]);
}
}
}
private void DrawWaveformPoints()
{
for (int i = 0; i < waveformPoints.Count; i += 3)
{
var point = waveformPoints[i];
// 跳过完全消散的点
float dissolveProgress = point.particle != null ? point.particle.dissolveProgress : 0f;
if (dissolveProgress >= 1f) continue;
Vector3 pos = new Vector3(point.x, point.smoothedY, 0);
// 如果正在被抚平,显示进度环
if (point.isBeingCalmed && point.calmTimer > 0)
{
float requiredTime = 0.5f + point.resistance * 1f;
float progress = Mathf.Min(1f, point.calmTimer / requiredTime);
Color ringColor = interactionRingColor;
ringColor.a *= (1 - dissolveProgress);
Draw.Ring(pos, 0.08f, 0.06f, ringColor);
Draw.Arc(pos, 0.08f, 0.02f, -Mathf.PI / 2f, progress * Mathf.PI * 2f, ringColor);
}
// 绘制波形点
float pointAlpha = (1 - point.calmAmount) * (1 - calmProgress * 0.5f) * (1 - dissolveProgress) * 0.6f;
if (pointAlpha > 0.05f)
{
Color pointColor = Color.Lerp(anxiousWaveColor, normalWaveColor, point.calmAmount);
pointColor.a = pointAlpha;
Draw.Disc(pos, 0.03f, pointColor);
}
}
}
private void DrawInteractionFeedback()
{
Vector3 mousePos3D = new Vector3(mouseWorldPos.x, mouseWorldPos.y, 0);
// 内圈(交互范围)
Color innerColor = interactionColor;
Draw.Disc(mousePos3D, interactionRadius, innerColor);
// 外圈(视觉反馈)
Color outerColor = interactionRingColor;
Draw.Ring(mousePos3D, interactionRadius, interactionRadius * 0.95f, outerColor);
// 根据拖动速度显示额外反馈
if (mouseDragSpeed > 0.1f)
{
Color speedColor = interactionRingColor;
speedColor.a = 0.4f;
Draw.Ring(mousePos3D, interactionRadius * 1.25f, interactionRadius * 1.2f, speedColor);
}
}
private void DrawBaseline()
{
float alpha = 0.2f * (1 - calmProgress);
Color baselineColor = normalWaveColor;
baselineColor.a = alpha;
Draw.LineGeometry = LineGeometry.Flat2D;
Draw.Thickness = 0.015f;
// 计算波形范围
if (waveformPoints.Count > 0)
{
float minX = waveformPoints[0].x;
float maxX = waveformPoints[waveformPoints.Count - 1].x;
Draw.Line(new Vector3(minX - 0.5f, baseY, 0), new Vector3(maxX + 0.5f, baseY, 0), baselineColor);
}
}
private class WaveformParticleEffect
{
public Vector3 position;
public float vx;
public float vy;
public float alpha;
public float size;
public WaveformParticleEffect(Vector3 pos, float velocityX, float velocityY, float initialSize)
{
position = pos;
vx = velocityX;
vy = velocityY;
alpha = 0.8f;
size = initialSize;
}
public void Update(float deltaTime)
{
position.x += vx * deltaTime;
position.y += vy * deltaTime;
vy += 0.1f * deltaTime; // 重力
alpha -= 0.015f;
size *= 0.98f;
}
}
}
}