Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / mark / ActivityMark.cs

using System.Collections;
using System.Threading.Tasks;
using Godot;

/// <summary>
/// 物体生成标记
/// </summary>
[Tool]
public partial class ActivityMark : Node2D
{
    /// <summary>
    /// 物体类型
    /// </summary>
    [Export]
    public ActivityIdPrefix.ActivityPrefixType Type = ActivityIdPrefix.ActivityPrefixType.NonePrefix;

    /// <summary>
    /// 物体id
    /// </summary>
    [Export]
    public string ItemId;

    /// <summary>
    /// 所在层级
    /// </summary>
    [Export]
    public RoomLayerEnum Layer = RoomLayerEnum.NormalLayer;

    /// <summary>
    /// 该标记在第几波调用 BeReady,
    /// 一个房间内所以敌人清完即可进入下一波
    /// </summary>
    [Export]
    public int WaveNumber = 1;

    /// <summary>
    /// 延时执行时间,单位:秒
    /// </summary>
    [Export]
    public float DelayTime = 0;

    /// <summary>
    /// 物体会在该矩形区域内随机位置生成
    /// </summary>
    [Export]
    public Vector2I BirthRect = Vector2I.Zero;
    
    /// <summary>
    /// 绘制的颜色
    /// </summary>
    [Export]
    public Color DrawColor = new Color(1, 1, 1, 1);

    /// <summary>
    /// 物体初始海拔高度
    /// </summary>
    [ExportGroup("Vertical")]
    [Export(PropertyHint.Range, "0, 36")]
    public int Altitude = 0;

    /// <summary>
    /// 物体初始纵轴速度
    /// </summary>
    [Export(PropertyHint.Range, "-1000,1000,0.1")]
    public float VerticalSpeed = 0;

    /// <summary>
    /// 当前标记所在Tile节点
    /// </summary>
    public TileMap TileRoot;

    //是否已经结束
    private bool _isOver = true;
    private float _overTimer = 0;
    private float _timer = 0;
    private RoomInfo _tempRoom;

    //绘制的字体
    private static Font _drawFont;
    
    /// <summary>
    /// 获取物体Id
    /// </summary>
    public string GetItemId()
    {
        return ActivityIdPrefix.GetNameByPrefixType(Type) + ItemId;
    }

    public override void _Process(double delta)
    {
#if TOOLS
        if (Engine.IsEditorHint())
        {
            QueueRedraw();
            return;
        }
#endif
        if (_isOver)
        {
            _overTimer += (float)delta;
            if (_overTimer >= 1)
            {
                SetActive(false);
            }
        }
        else
        {
            if (DelayTime > 0)
            {
                _timer += (float)delta;
                if (_timer >= DelayTime)
                {
                    Doing(_tempRoom);
                    _tempRoom = null;
                    _isOver = true;
                }
            }
        }
    }

    /// <summary>
    /// 标记准备好了
    /// </summary>
    public void BeReady(RoomInfo roomInfo)
    {
        _isOver = false;
        _overTimer = 0;
        SetActive(true);
        if (DelayTime <= 0)
        {
            Doing(roomInfo);
            _isOver = true;
        }
        else
        {
            _timer = 0;
            _tempRoom = roomInfo;
        }
    }

    /// <summary>
    /// 是否已经结束
    /// </summary>
    public bool IsOver()
    {
        return _isOver && _overTimer >= 1;
    }

    /// <summary>
    /// 调用该函数表示该标记可以生成物体了
    /// </summary>
    public virtual void Doing(RoomInfo roomInfo)
    {
        CreateActivityObject().PutDown(Layer);
    }

    /// <summary>
    /// 实例化ItemId指定的物体, 并返回对象实例, 函数会自动设置位置
    /// </summary>
    protected ActivityObject CreateActivityObject()
    {
        var instance = ActivityObject.Create(GetItemId());
        var pos = Position;
        if (BirthRect != Vector2I.Zero)
        {
            instance.Position = new Vector2(
                Utils.RandomRangeInt((int)pos.X - BirthRect.X / 2, (int)pos.X + BirthRect.X / 2),
                Utils.RandomRangeInt((int)pos.Y - BirthRect.Y / 2, (int)pos.Y + BirthRect.Y / 2)
            );
        }
        else
        {
            instance.Position = pos;
        }
        
        instance.VerticalSpeed = VerticalSpeed;
        instance.Altitude = Altitude;
        instance.StartCoroutine(PlayBirthAnimation(instance));
        return instance;
    }

    private IEnumerator PlayBirthAnimation(ActivityObject instance)
    {
        var a = 1.0f;
        instance.SetBlendColor(Colors.White);

        for (var i = 0; i < 10; i++)
        {
            instance.SetBlendSchedule(a);
            yield return 0;
        }
        
        while (a > 0)
        {
            instance.SetBlendSchedule(a);
            a -= 0.03f;
            yield return 0;
        }
    }

#if TOOLS
    public override void _Draw()
    {
        if (Engine.IsEditorHint() || GameApplication.Instance.Debug)
        {
            DrawLine(new Vector2(-2, -2), new Vector2(2, 2), DrawColor, 1f);
            DrawLine(new Vector2(-2, 2), new Vector2(2, -2), DrawColor, 1f);

            if (BirthRect != Vector2.Zero)
            {
                var c = DrawColor;
                c.A = 0.5f;
                DrawRect(new Rect2(-BirthRect / 2, BirthRect), c, false, 0.5f);
            }

            if (_drawFont == null)
            {
                _drawFont = ResourceManager.Load<Font>(ResourcePath.Silver_ttf);
            }
            DrawString(_drawFont, new Vector2(-14, 12), WaveNumber.ToString(), HorizontalAlignment.Center, 28, 14);
        }
    }
#endif

    /// <summary>
    /// 设置当前节点是否是活动状态
    /// </summary>
    public void SetActive(bool flag)
    {
        // SetProcess(flag);
        // SetPhysicsProcess(flag);
        // SetProcessInput(flag);
        // Visible = flag;
        
        var parent = GetParent();
        if (flag)
        {
            if (parent == null)
            {
                TileRoot.AddChild(this);
            }
            else if (parent != TileRoot)
            {
                parent.RemoveChild(this);
                TileRoot.AddChild(this);
            }
            Owner = TileRoot;
        }
        else
        {
            if (parent != null)
            {
                parent.RemoveChild(this);
                Owner = null;
            }
        }
    }
}