Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / effects / Trail.cs
@小李xl 小李xl on 29 Jan 2024 2 KB 制作0010武器完成
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;
    }
}