Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / SubLine.cs

using System.Collections;
using Godot;

/// <summary>
/// 瞄准辅助线
/// </summary>
public class SubLine : Component<Role>
{
    /// <summary>
    /// 是否正在播放警告闪烁动画
    /// </summary>
    public bool IsPlayWarnAnimation => _cid > 0;
    
    private Line2D _line2D;
    private RayCast2D _rayCast2D;

    private bool _enableSubLine;
    private float _range;
    private long _cid;
    private Color _color = Colors.Orange;
    
    public override void Ready()
    {
        //初始化瞄准辅助线
        _line2D = new Line2D();
        _line2D.Width = 1;
        AddChild(_line2D);

        _rayCast2D = new RayCast2D();
        _rayCast2D.CollisionMask = PhysicsLayer.Wall | PhysicsLayer.Obstacle;
        AddChild(_rayCast2D);
        
        Master.WeaponPack.ChangeActiveItemEvent += OnChangeWeapon;
    }

    public override void OnEnable()
    {
        OnChangeWeapon(Master.WeaponPack.ActiveItem);
    }
    
    public override void OnDisable()
    {
        _enableSubLine = false;
        _line2D.Visible = false;
        _rayCast2D.Enabled = false;
        if (_cid > 0)
        {
            StopCoroutine(_cid);
        }
    }

    /// <summary>
    /// 设置线条颜色
    /// </summary>
    public void SetColor(Color color)
    {
        _color = color;
        _line2D.DefaultColor = color;
    }

    /// <summary>
    /// 播放闪烁警告动画
    /// </summary>
    /// <param name="time">持续时间</param>
    public void PlayWarnAnimation(float time)
    {
        if (_cid > 0)
        {
            StopCoroutine(_cid);
        }
        
        _cid = StartCoroutine(RunWarnAnimation(time));
    }

    private IEnumerator RunWarnAnimation(float time)
    {
        var now = 0f;
        var t = 0f;
        var b = false;
        while (now < time)
        {
            var delta = GetProcessDeltaTime();
            now += delta;
            t += delta;
            if (t >= 0.08f)
            {
                t %= 0.08f;
                _line2D.DefaultColor = b ? Colors.Orange : Colors.Red;
                b = !b;
            }
            yield return null;
        }

        _line2D.DefaultColor = _color;
        _cid = 0;
    }

    //切换武器
    private void OnChangeWeapon(Weapon weapon)
    {
        if (!Enable)
        {
            return;
        }
        if (weapon == null)
        {
            _enableSubLine = false;
        }
        else
        {
            _enableSubLine = true;
            if (_cid > 0)
            {
                StopCoroutine(_cid);
                _cid = 0;
            }
            _range = Utils.GetConfigRangeEnd(weapon.Attribute.Bullet.DistanceRange);
            _line2D.DefaultColor = _color;
        }
    }

    public override void PhysicsProcess(float delta)
    {
        if (_enableSubLine)
        {
            _line2D.Visible = true;
            _rayCast2D.Enabled = true;
            UpdateSubLine();
        }
        else
        {
            _line2D.Visible = false;
            _rayCast2D.Enabled = false;
        }
    }

    public override void OnDestroy()
    {
        _line2D.QueueFree();
        _rayCast2D.QueueFree();
        Master.WeaponPack.ChangeActiveItemEvent -= OnChangeWeapon;
    }

    private void UpdateSubLine()
    {
        var master = Master;
        var weapon = master.WeaponPack.ActiveItem;
        float length;
        var firePointGlobalPosition = weapon.FirePoint.GlobalPosition;
        if (_rayCast2D.IsColliding())
        {
            length = firePointGlobalPosition.DistanceTo(_rayCast2D.GetCollisionPoint());
        }
        else
        {
            length = _range;
        }

        var r = master.ConvertRotation(master.MountPoint.RealRotation);
        //更新 Ray 的位置角度
        _rayCast2D.GlobalPosition = firePointGlobalPosition;
        _rayCast2D.TargetPosition = new Vector2(_range, 0);
        _rayCast2D.Rotation = r;

        //计算 line2D 的点
        var position = _line2D.ToLocal(firePointGlobalPosition);
        Vector2 position2 = Vector2.FromAngle(r) * length;

        _line2D.Points = new Vector2[]
        {
            position,
            position + position2
        };
    }
}