267 lines
9.0 KiB
C#
267 lines
9.0 KiB
C#
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using Shapes;
|
|
|
|
namespace AibisDream.MiniGame.Language
|
|
{
|
|
/// <summary>
|
|
/// 波形渲染器:使用Shapes绘制波形和交互效果
|
|
/// </summary>
|
|
[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<WaveformPoint> waveformPoints;
|
|
private CompletionPhase completionPhase;
|
|
private float calmProgress;
|
|
private Vector2 mouseWorldPos;
|
|
private bool mousePressed;
|
|
private float mouseDragSpeed;
|
|
private List<WaveformParticleEffect> waveParticles = new List<WaveformParticleEffect>();
|
|
|
|
public void SetData(
|
|
List<WaveformPoint> 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.Revealing && completionPhase != CompletionPhase.Completed)
|
|
return;
|
|
|
|
using (Draw.Command(cam))
|
|
{
|
|
Draw.BlendMode = ShapesBlendMode.Transparent;
|
|
Draw.ZTest = UnityEngine.Rendering.CompareFunction.Always;
|
|
|
|
// 绘制粒子效果
|
|
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<Vector3>();
|
|
var colors = new List<Color>();
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|