using Godot; /// <summary> /// 拖尾效果 /// </summary> public partial class Trail : Line2D, IPoolItem { /// <summary> /// 拖尾效果固定更新帧率 /// </summary> public const int TrailUpdateFrame = 20; /// <summary> /// 拖尾最大点数 /// </summary> public int MaxLength { get; set; } = 20; /// <summary> /// 拖尾绑定的物体 /// </summary> public Node2D Target { get; private set; } public bool IsDestroyed { get; private set; } public bool IsRecycled { get; set; } public string Logotype { get; set; } private double _time = 0; private IPoolItem _targetPoolItem; /// <summary> /// 设置拖尾跟随的物体 /// </summary> public void SetTarget(Node2D target) { Target = target; if (target is IPoolItem poolItem) { _targetPoolItem = poolItem; } else { _targetPoolItem = null; } if (target != null) { ClearPoints(); } _time = 1f / TrailUpdateFrame; } public void SetColor(Color color) { Gradient.SetColor(0, color); color.A = 0; Gradient.SetColor(1, color); } public override void _Process(double delta) { if (_targetPoolItem != null && _targetPoolItem.IsRecycled) //目标物体被回收 { SetTarget(null); } _time += delta; var v = 1f / TrailUpdateFrame; if (_time >= v) //执行更新点 { _time %= v; var pointCount = GetPointCount(); if (Target != null) //没有被回收 { AddPoint(Target.GlobalPosition, 0); if (pointCount > MaxLength) { RemovePoint(pointCount); } } else //被回收了, { if (pointCount > 0) { RemovePoint(pointCount - 1); } if (pointCount <= 1) //没有点了, 执行回收 { ObjectPool.Reclaim(this); } } } else if (Target != null && GetPointCount() >= 2) //没有被回收, 更新第一个点 { SetPointPosition(0, Target.GlobalPosition); } } public void Destroy() { if (IsDestroyed) { return; } IsDestroyed = true; QueueFree(); } public void OnReclaim() { GetParent().CallDeferred(Node.MethodName.RemoveChild, this); Target = null; _targetPoolItem = null; } public void OnLeavePool() { ClearPoints(); _time = 0; ZIndex = 0; } }