Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / image / FreezeSprite.cs
@小李xl 小李xl on 3 Nov 2023 2 KB 优化可互动物体

using Godot;

/// <summary>
/// 用于绘制静止不动的 ActivityObject,从而优化性能
/// </summary>
public class FreezeSprite : IDestroy
{
    public bool IsDestroyed { get; private set; }
    
    /// <summary>
    /// 所在位置
    /// </summary>
    public Vector2 Position { get; private set; }
    
    /// <summary>
    /// 所属对象
    /// </summary>
    public ActivityObject ActivityObject { get; }
    
    /// <summary>
    /// 是否已经被冻结
    /// </summary>
    public bool IsFrozen { get; private set; }

    private Node _spriteParent;
    private int _spriteIndex;
    private Node _shadowParent;
    private int _shadowIndex;
    private Node _parent;
    
    public FreezeSprite(ActivityObject ao)
    {
        ActivityObject = ao;
        _spriteParent = ao.AnimatedSprite.GetParent();
        _shadowParent = ao.ShadowSprite.GetParent();
    }

    /// <summary>
    /// 冻结精灵,这样 ActivityObject 多余的节点就会被移出场景树,逻辑也会被暂停,从而优化性能
    /// </summary>
    public void Freeze()
    {
        if (IsFrozen)
        {
            return;
        }

        var affiliationArea = ActivityObject.AffiliationArea;
        if (affiliationArea == null)
        {
            Debug.LogError("物体的 AffiliationArea 属性为空,不能调用 Freeze() 函数!");
            return;
        }

        IsFrozen = true;

        Position = ActivityObject.Position;
        affiliationArea.SpriteRoot.AddFreezeSprite(this);
        _spriteIndex = ActivityObject.AnimatedSprite.GetIndex();
        _shadowIndex = ActivityObject.ShadowSprite.GetIndex();
        ActivityObject.ShadowSprite.Reparent(affiliationArea.SpriteRoot);
        ActivityObject.AnimatedSprite.Reparent(affiliationArea.SpriteRoot);
        _parent = ActivityObject.GetParent();
        _parent.RemoveChild(ActivityObject);
    }

    /// <summary>
    /// 解冻精灵,让 ActivityObject 恢复正常功能
    /// </summary>
    public void Unfreeze()
    {
        if (!IsFrozen)
        {
            return;
        }

        IsFrozen = false;

        ActivityObject.AffiliationArea.SpriteRoot.AddFreezeSprite(this);

        _parent.AddChild(ActivityObject);
        ActivityObject.ShadowSprite.Reparent(_shadowParent);
        ActivityObject.AnimatedSprite.Reparent(_spriteParent);

        if (_spriteIndex > _shadowIndex)
        {
            _shadowParent.MoveChild(ActivityObject.ShadowSprite, _shadowIndex);
            _spriteParent.MoveChild(ActivityObject.AnimatedSprite, _spriteIndex);
        }
        else
        {
            _spriteParent.MoveChild(ActivityObject.AnimatedSprite, _spriteIndex);
            _shadowParent.MoveChild(ActivityObject.ShadowSprite, _shadowIndex);
        }
    }


    public void Destroy()
    {
        if (IsDestroyed)
        {
            return;
        }

        IsDestroyed = true;
        if (IsFrozen)
        {
            ActivityObject.Destroy();
        }
    }
}