using System; using System.Collections.Generic; 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> /// 地板所占的地板格子, 单位: 格, 使用时不需要加上 OriginPosition /// </summary> public HashSet<Vector2I> AisleFloorCell; /// <summary> /// 地板所占的矩形, 单位: 格, 使用时不需要加上 OriginPosition /// </summary> public Rect2I AisleFloorRect; /// <summary> /// 与下一道门是否有交叉点 /// </summary> public bool HasCross; /// <summary> /// 与下一道门的交叉点, 单位: 格 /// </summary> public Vector2I Cross; /// <summary> /// 连接过道使用预览纹理, 用于小地图 /// </summary> public ImageTexture AislePreviewTexture; /// <summary> /// 连接过道使用预览图, 用于小地图 /// </summary> public TextureRect AislePreviewSprite; /// <summary> /// 门实例 /// </summary> public RoomDoor Door; /// <summary> /// 过道的迷雾 /// </summary> public FogMask AisleFogMask; /// <summary> /// 过道迷雾区域 /// </summary> public AisleFogArea AisleFogArea; /// <summary> /// 门区域预览房间迷雾 /// </summary> public PreviewFogMask PreviewRoomFogMask; /// <summary> /// 门区域预览过道迷雾 /// </summary> public PreviewFogMask PreviewAisleFogMask; /// <summary> /// 未探索的区域显示的问号 /// </summary> public Sprite2D UnknownSprite; /// <summary> /// 世界坐标下的原点坐标, 单位: 像素 /// </summary> public Vector2I GetWorldOriginPosition() { return new Vector2I( OriginPosition.X * GameConfig.TileCellSize, OriginPosition.Y * GameConfig.TileCellSize ); } /// <summary> /// 终点坐标, 单位: 格 /// </summary> public Vector2I GetEndPosition() { if (Direction == DoorDirection.E || Direction == DoorDirection.W) { return OriginPosition + new Vector2I(0, 4); } else if (Direction == DoorDirection.N || Direction == DoorDirection.S) { return OriginPosition + new Vector2I(4, 0); } return default; } /// <summary> /// 世界坐标下的终点坐标, 单位: 像素 /// </summary> public Vector2I GetWorldEndPosition() { if (Direction == DoorDirection.E || Direction == DoorDirection.W) { return GetWorldOriginPosition() + new Vector2I(0, 4 * GameConfig.TileCellSize); } else if (Direction == DoorDirection.N || Direction == DoorDirection.S) { return GetWorldOriginPosition() + new Vector2I(4 * GameConfig.TileCellSize, 0); } return default; } /// <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 (AisleFogMask != null) { AisleFogMask.Destroy(); } if (AisleFogArea != null) { AisleFogArea.Destroy(); } if (PreviewRoomFogMask != null) { PreviewRoomFogMask.Destroy(); } if (PreviewAisleFogMask != null) { PreviewAisleFogMask.Destroy(); } if (AislePreviewTexture != null) { AislePreviewTexture.Dispose(); } if (AislePreviewSprite != null) { AislePreviewSprite.QueueFree(); } } }