Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / room / RoomDoorInfo.cs
@小李xl 小李xl on 9 Oct 2023 9 KB 过道迷雾, 开发中...

using System;
using Godot;

/// <summary>
/// 房间的门
/// </summary>
public class RoomDoorInfo : IDestroy
{
    public bool IsDestroyed { get; private set; }

    /// <summary>
    /// 所在墙面方向
    /// </summary>
    public DoorDirection Direction;

    /// <summary>
    /// 是否是正向的门
    /// </summary>
    public bool IsForward;

    /// <summary>
    /// 所在的房间
    /// </summary>
    public RoomInfo RoomInfo;

    /// <summary>
    /// 连接的门
    /// </summary>
    public RoomDoorInfo ConnectDoor;

    /// <summary>
    /// 连接的房间
    /// </summary>
    public RoomInfo ConnectRoom;

    /// <summary>
    /// 原点坐标, 单位: 格
    /// </summary>
    public Vector2I OriginPosition;

    /// <summary>
    /// 与下一道门是否有交叉点
    /// </summary>
    public bool HasCross;

    /// <summary>
    /// 与下一道门的交叉点, 单位: 格
    /// </summary>
    public Vector2I Cross;

    /// <summary>
    /// 占位导航网格
    /// </summary>
    public DoorNavigationInfo Navigation;

    /// <summary>
    /// 门实例
    /// </summary>
    public RoomDoor Door;

    /// <summary>
    /// 过道的迷雾
    /// </summary>
    public FogMask FogMask;

    /// <summary>
    /// 过道迷雾区域
    /// </summary>
    public AisleFogArea AisleFogArea;

    /// <summary>
    /// 门区域预览迷雾
    /// </summary>
    public PreviewFogMask PreviewFogMask;

    /// <summary>
    /// 当前门连接的过道是否探索过
    /// </summary>
    public bool IsExplored { get; private set; } = false;

    /// <summary>
    /// 世界坐标下的原点坐标, 单位: 像素
    /// </summary>
    public Vector2I GetWorldOriginPosition()
    {
        return new Vector2I(
            OriginPosition.X * GameConfig.TileCellSize,
            OriginPosition.Y * GameConfig.TileCellSize
        );
    }

    /// <summary>
    /// 获取直连门过道区域数据, 单位: 格, 如果当前门连接区域带交叉点, 则报错
    /// </summary>
    public Rect2I GetAisleRect()
    {
        if (HasCross)
        {
            throw new Exception("当前门连接的过道包含交叉点, 请改用 GetCrossAisleRect() 函数!");
        }
        
        var rect = Utils.CalcRect(
            OriginPosition.X,
            OriginPosition.Y,
            ConnectDoor.OriginPosition.X,
            ConnectDoor.OriginPosition.Y
        );
    
        switch (Direction)
        {
            case DoorDirection.E:
                rect.Size = new Vector2I(rect.Size.X, GameConfig.CorridorWidth);
                break;
            case DoorDirection.W:
                rect.Size = new Vector2I(rect.Size.X, GameConfig.CorridorWidth);
                break;
                    
            case DoorDirection.S:
                rect.Size = new Vector2I(GameConfig.CorridorWidth, rect.Size.Y);
                break;
            case DoorDirection.N:
                rect.Size = new Vector2I(GameConfig.CorridorWidth, rect.Size.Y);
                break;
        }

        return rect;
    }

    /// <summary>
    /// 获取交叉门过道区域数据, 单位: 格, 如果当前门连接区域不带交叉点, 则报错
    /// </summary>
    public CrossAisleRectData GetCrossAisleRect()
    {
        if (!HasCross)
        {
            throw new Exception("当前门连接的过道不包含交叉点, 请改用 GetAisleRect() 函数!");
        }

        Rect2I rect;
        Rect2I rect2;

        //计算范围
        switch (Direction)
        {
            case DoorDirection.E: //→
                rect = new Rect2I(
                    OriginPosition.X,
                    OriginPosition.Y,
                    Cross.X - OriginPosition.X,
                    GameConfig.CorridorWidth
                );
                break;
            case DoorDirection.W: //←
                rect = new Rect2I(
                    Cross.X + GameConfig.CorridorWidth,
                    Cross.Y,
                    OriginPosition.X - (Cross.X + GameConfig.CorridorWidth),
                    GameConfig.CorridorWidth
                );
                break;
            case DoorDirection.S: //↓
                rect = new Rect2I(
                    OriginPosition.X,
                    OriginPosition.Y,
                    GameConfig.CorridorWidth,
                    Cross.Y - OriginPosition.Y
                );
                break;
            case DoorDirection.N: //↑
                rect = new Rect2I(
                    Cross.X,
                    Cross.Y + GameConfig.CorridorWidth,
                    GameConfig.CorridorWidth,
                    OriginPosition.Y - (Cross.Y + GameConfig.CorridorWidth)
                );
                break;
            default:
                rect = new Rect2I();
                break;
        }

        switch (ConnectDoor.Direction)
        {
            case DoorDirection.E: //→
                rect2 = new Rect2I(
                    ConnectDoor.OriginPosition.X,
                    ConnectDoor.OriginPosition.Y,
                    Cross.X - ConnectDoor.OriginPosition.X,
                    GameConfig.CorridorWidth
                );
                break;
            case DoorDirection.W: //←
                rect2 = new Rect2I(
                    Cross.X + GameConfig.CorridorWidth,
                    Cross.Y,
                    ConnectDoor.OriginPosition.X -
                    (Cross.X + GameConfig.CorridorWidth),
                    GameConfig.CorridorWidth
                );
                break;
            case DoorDirection.S: //↓
                rect2 = new Rect2I(
                    ConnectDoor.OriginPosition.X,
                    ConnectDoor.OriginPosition.Y,
                    GameConfig.CorridorWidth,
                    Cross.Y - ConnectDoor.OriginPosition.Y
                );
                break;
            case DoorDirection.N: //↑
                rect2 = new Rect2I(
                    Cross.X,
                    Cross.Y + GameConfig.CorridorWidth,
                    GameConfig.CorridorWidth,
                    ConnectDoor.OriginPosition.Y -
                    (Cross.Y + GameConfig.CorridorWidth)
                );
                break;
            default:
                rect2 = new Rect2I();
                break;
        }

        return new CrossAisleRectData()
        {
            Rect1 = rect,
            Rect2 = rect2,
            Cross = new Rect2I(Cross + Vector2I.One, new Vector2I(GameConfig.CorridorWidth - 2, GameConfig.CorridorWidth - 2))
        };
    }
    
    public void Destroy()
    {
        if (IsDestroyed)
        {
            return;
        }

        IsDestroyed = true;
        if (FogMask != null)
        {
            FogMask.Destroy();
        }

        if (AisleFogArea != null)
        {
            AisleFogArea.Destroy();
        }
    }

    /// <summary>
    /// 清除过道迷雾
    /// </summary>
    public void ClearFog()
    {
        IsExplored = true;
        ConnectDoor.IsExplored = true;
        if (FogMask != null && Math.Abs(FogMask.Color.A - 1f) > 0.001f)
        {
            FogMask.TransitionAlpha(1, GameConfig.FogTransitionTime);
            RefreshPreviewFog(1);
        }
    }

    /// <summary>
    /// 将过道迷雾变暗
    /// </summary>
    public void DarkFog()
    {
        IsExplored = true;
        ConnectDoor.IsExplored = true;
        if (FogMask != null && Math.Abs(FogMask.Color.A - GameConfig.DarkFogAlpha) > 0.001f)
        {
            FogMask.TransitionAlpha(GameConfig.DarkFogAlpha, GameConfig.FogTransitionTime);
            RefreshPreviewFog(GameConfig.DarkFogAlpha);
        }
    }

    /// <summary>
    /// 刷新房间中的预览迷雾
    /// </summary>
    /// <param name="aisleFogAlpha">过道迷雾透明度</param>
    public void RefreshPreviewFog(float aisleFogAlpha)
    {
        var room1Alpha = RoomInfo.FogMask.TargetAlpha;
        var room2Alpha = ConnectDoor.RoomInfo.FogMask.TargetAlpha;
        //GD.Print($"aisleFogAlpha: {aisleFogAlpha}, room1Alpha: {room1Alpha}, room2Alpha{room2Alpha}");

        if ((aisleFogAlpha < 1 && room1Alpha < 1) || Math.Abs(aisleFogAlpha - room1Alpha) < 0.001f) //隐藏预览
        {
            PreviewFogMask.TransitionToHide(GameConfig.FogTransitionTime);
        }
        else if (aisleFogAlpha >= 1) //预览房间
        {
            PreviewFogMask.SetActive(true);
            PreviewFogMask.SetPreviewFogType(PreviewFogMask.PreviewFogType.Room);

            //播放过渡动画
            var targetAlpha = 1 - room1Alpha;
            PreviewFogMask.Color = new Color(1, 1, 1, 0);
            PreviewFogMask.TransitionAlpha(targetAlpha, GameConfig.FogTransitionTime);
        }
        else if (room1Alpha >= 1) //预览过道
        {
            PreviewFogMask.SetActive(true);
            PreviewFogMask.SetPreviewFogType(PreviewFogMask.PreviewFogType.Aisle);
        }

        if ((aisleFogAlpha < 1 && room2Alpha < 1) || Math.Abs(aisleFogAlpha - room2Alpha) < 0.001f) //隐藏预览
        {
            ConnectDoor.PreviewFogMask.TransitionToHide(GameConfig.FogTransitionTime);
        }
        else if (aisleFogAlpha >= 1) //预览房间
        {
            ConnectDoor.PreviewFogMask.SetActive(true);
            ConnectDoor.PreviewFogMask.SetPreviewFogType(PreviewFogMask.PreviewFogType.Room);
            
            //播放过渡动画, 这里有问题
            var targetAlpha = 1 - room2Alpha;
            ConnectDoor.PreviewFogMask.Color = new Color(1, 1, 1, 0);
            ConnectDoor.PreviewFogMask.TransitionAlpha(targetAlpha, GameConfig.FogTransitionTime);
        }
        else if (room2Alpha >= 1) //预览过道
        {
            ConnectDoor.PreviewFogMask.SetActive(true);
            ConnectDoor.PreviewFogMask.SetPreviewFogType(PreviewFogMask.PreviewFogType.Aisle);
        }
    }
}