157 lines
5.5 KiB
C#
157 lines
5.5 KiB
C#
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
|
|
namespace AibisDream.MiniGame.Language
|
|
{
|
|
/// <summary>
|
|
/// 效果传播信息
|
|
/// </summary>
|
|
public class PropagationInfo
|
|
{
|
|
public CandidateParticle particle;
|
|
public CandidateParticle source;
|
|
public int step;
|
|
public float pulseProgress;
|
|
|
|
public PropagationInfo(CandidateParticle particle, CandidateParticle source, int step)
|
|
{
|
|
this.particle = particle;
|
|
this.source = source;
|
|
this.step = step;
|
|
this.pulseProgress = 0f;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 效果传播系统:管理从红色粒子到蓝色粒子的效果传递(使用BFS算法)
|
|
/// </summary>
|
|
public class EffectPropagation
|
|
{
|
|
private CandidateParticle redParticle;
|
|
private List<PropagationInfo> propagatedParticles = new List<PropagationInfo>();
|
|
private Queue<CandidateParticle> propagationQueue = new Queue<CandidateParticle>();
|
|
|
|
private float lifeTimer;
|
|
private float propagationDelay;
|
|
private float propagationCounter = 0f;
|
|
private int maxPropagationNodes;
|
|
private int currentNodeCount = 0;
|
|
private int currentStep = 0;
|
|
|
|
public bool IsActive => lifeTimer > 0;
|
|
public List<PropagationInfo> PropagatedParticles => propagatedParticles;
|
|
|
|
public EffectPropagation(CandidateParticle redParticle, float duration, float delay, int maxNodes)
|
|
{
|
|
this.redParticle = redParticle;
|
|
this.lifeTimer = duration;
|
|
this.propagationDelay = delay;
|
|
this.maxPropagationNodes = maxNodes;
|
|
|
|
// 从红色粒子开始传播(第0步)
|
|
var connectedBlues = FindConnectedBlues(redParticle);
|
|
if (connectedBlues.Count > 0 && currentNodeCount < maxPropagationNodes)
|
|
{
|
|
// 第一步:处理所有直接连接的蓝色粒子(BFS第一层)
|
|
foreach (var targetParticle in connectedBlues)
|
|
{
|
|
if (currentNodeCount >= maxPropagationNodes) break;
|
|
|
|
ApplyEffectToParticle(targetParticle);
|
|
propagatedParticles.Add(new PropagationInfo(targetParticle, redParticle, 1));
|
|
propagationQueue.Enqueue(targetParticle);
|
|
currentNodeCount++;
|
|
}
|
|
currentStep = 1;
|
|
}
|
|
}
|
|
|
|
public void Update(float deltaTime)
|
|
{
|
|
lifeTimer -= deltaTime;
|
|
propagationCounter += deltaTime;
|
|
|
|
// BFS逐层传播
|
|
if (propagationCounter >= propagationDelay && propagationQueue.Count > 0 && currentNodeCount < maxPropagationNodes)
|
|
{
|
|
propagationCounter = 0f;
|
|
currentStep++;
|
|
|
|
// 处理当前层的所有节点
|
|
int currentLevelSize = propagationQueue.Count;
|
|
|
|
for (int i = 0; i < currentLevelSize; i++)
|
|
{
|
|
if (currentNodeCount >= maxPropagationNodes) break;
|
|
|
|
var sourceParticle = propagationQueue.Dequeue();
|
|
var connectedBlues = FindConnectedBlues(sourceParticle);
|
|
|
|
// 将所有连接的蓝色粒子加入下一层
|
|
foreach (var targetParticle in connectedBlues)
|
|
{
|
|
if (currentNodeCount >= maxPropagationNodes) break;
|
|
|
|
ApplyEffectToParticle(targetParticle);
|
|
propagatedParticles.Add(new PropagationInfo(targetParticle, sourceParticle, currentStep + 1));
|
|
propagationQueue.Enqueue(targetParticle);
|
|
currentNodeCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 更新所有传播粒子的脉冲动画
|
|
foreach (var info in propagatedParticles)
|
|
{
|
|
info.pulseProgress += deltaTime * 5f;
|
|
if (info.pulseProgress > 1f)
|
|
info.pulseProgress = 1f;
|
|
}
|
|
}
|
|
|
|
private List<CandidateParticle> FindConnectedBlues(CandidateParticle particle)
|
|
{
|
|
List<CandidateParticle> connected = new List<CandidateParticle>();
|
|
HashSet<CandidateParticle> usedParticles = new HashSet<CandidateParticle>();
|
|
|
|
// 记录已使用的粒子
|
|
usedParticles.Add(redParticle);
|
|
foreach (var prop in propagatedParticles)
|
|
{
|
|
usedParticles.Add(prop.particle);
|
|
}
|
|
|
|
// 只检查真正连接的粒子
|
|
foreach (var connectedParticle in particle.connections)
|
|
{
|
|
if (!connectedParticle.hasEffect &&
|
|
!usedParticles.Contains(connectedParticle) &&
|
|
!connectedParticle.isRed &&
|
|
!connectedParticle.isOrange)
|
|
{
|
|
connected.Add(connectedParticle);
|
|
}
|
|
}
|
|
|
|
return connected;
|
|
}
|
|
|
|
private void ApplyEffectToParticle(CandidateParticle particle)
|
|
{
|
|
if (particle.hasEffect) return;
|
|
if (particle.isRed && particle.originalIsRed) return;
|
|
|
|
particle.ApplyEffect(lifeTimer);
|
|
}
|
|
|
|
public void Cleanup()
|
|
{
|
|
foreach (var info in propagatedParticles)
|
|
{
|
|
info.particle.RemoveEffect();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|