-
- using System;
- using System.Collections.Generic;
- using Godot;
-
- /// <summary>
- /// 房间的数据描述
- /// </summary>
- public class RoomInfo : IDestroy
- {
- public RoomInfo(int id, DungeonRoomType type, DungeonRoomSplit roomSplit)
- {
- Id = id;
- RoomType = type;
- RoomSplit = roomSplit;
- }
-
- /// <summary>
- /// 房间 id
- /// </summary>
- public int Id;
-
- /// <summary>
- /// 房间类型
- /// </summary>
- public DungeonRoomType RoomType;
-
- /// <summary>
- /// 层级, 也就是离初始房间间隔多少个房间
- /// </summary>
- public int Layer;
-
- /// <summary>
- /// 生成该房间使用的配置数据
- /// </summary>
- public DungeonRoomSplit RoomSplit;
-
- /// <summary>
- /// 房间大小, 单位: 格
- /// </summary>
- public Vector2I Size;
-
- /// <summary>
- /// 房间位置, 单位: 格
- /// </summary>
- public Vector2I Position;
-
- /// <summary>
- /// 门
- /// </summary>
- public List<RoomDoorInfo> Doors = new List<RoomDoorInfo>();
-
- /// <summary>
- /// 连接该房间的过道占用区域信息
- /// </summary>
- public List<Rect2I> AisleArea = new List<Rect2I>();
-
- /// <summary>
- /// 下一个房间
- /// </summary>
- public List<RoomInfo> Next = new List<RoomInfo>();
-
- /// <summary>
- /// 上一个房间
- /// </summary>
- public RoomInfo Prev;
-
- /// <summary>
- /// 当前房间使用的预设
- /// </summary>
- public RoomPreinstall RoomPreinstall;
-
- /// <summary>
- /// 当前房间归属区域
- /// </summary>
- public AffiliationArea AffiliationArea;
-
- /// <summary>
- /// 静态渲染精灵根节点, 用于放置sprite
- /// </summary>
- public RoomStaticSprite StaticSprite;
-
- /// <summary>
- /// 静态精灵绘制画布
- /// </summary>
- public ImageCanvas StaticImageCanvas;
-
- /// <summary>
- /// 液体画布
- /// </summary>
- public LiquidCanvas LiquidCanvas;
-
- /// <summary>
- /// 房间迷雾
- /// </summary>
- public FogMask RoomFogMask;
-
- /// <summary>
- /// 房间坐标相对于画布坐标偏移量, 单位: 像素
- /// </summary>
- public Vector2I RoomOffset { get; private set; }
-
- /// <summary>
- /// 房间算上连接通道所占用的区域
- /// </summary>
- public Rect2I OuterRect { get; private set; }
-
- /// <summary>
- /// 画布占用区域
- /// </summary>
- public Rect2I CanvasRect { get; private set; }
-
- /// <summary>
- /// 是否处于闭关状态, 也就是房间门没有主动打开
- /// </summary>
- public bool IsSeclusion { get; private set; } = false;
-
- /// <summary>
- /// 用于标记攻击目标位置
- /// </summary>
- public Dictionary<long, Vector2> MarkTargetPosition { get; private set; } = new Dictionary<long, Vector2>();
-
- /// <summary>
- /// 房间预览纹理, 用于小地图
- /// </summary>
- public ImageTexture PreviewTexture { get; set; }
-
- /// <summary>
- /// 房间预览图, 用于小地图
- /// </summary>
- public TextureRect PreviewSprite { get; set; }
-
- /// <summary>
- /// 房间内的传送点, 单位: 格
- /// </summary>
- public Vector2I Waypoints { get; set; }
-
- public bool IsDestroyed { get; private set; }
-
- private bool _openDoorFlag = true;
-
- // private bool _beReady = false;
- // private bool _waveStart = false;
- // private int _currWaveIndex = 0;
- // private int _currWaveNumber = 0;
- //private List<ActivityMark> _currActivityMarks = new List<ActivityMark>();
-
- /// <summary>
- /// 重新计算占用的区域
- /// </summary>
- public void CalcRange()
- {
- var worldPos = GetWorldPosition();
- var pos = new Vector2I(worldPos.X, worldPos.Y);
- var minX = pos.X;
- var minY = pos.Y;
- var maxX = minX + GetWidth();
- var maxY = minY + GetHeight();
-
- //遍历每一个连接的门, 计算计算canvas覆盖范围
- foreach (var doorInfo in Doors)
- {
- var connectDoor = doorInfo.ConnectDoor;
- switch (connectDoor.Direction)
- {
- case DoorDirection.E:
- case DoorDirection.W:
- {
- var (px1, py1) = connectDoor.GetWorldOriginPosition();
- var py2 = py1 + 4 * GameConfig.TileCellSize;
- if (px1 < minX)
- {
- minX = px1;
- }
- else if (px1 > maxX)
- {
- maxX = px1;
- }
-
- if (py1 < minY)
- {
- minY = py1;
- }
- else if (py1 > maxY)
- {
- maxY = py1;
- }
-
- if (py2 < minY)
- {
- minY = py2;
- }
- else if (py2 > maxY)
- {
- maxY = py2;
- }
- }
- break;
- case DoorDirection.S:
- case DoorDirection.N:
- {
- var (px1, py1) = connectDoor.GetWorldOriginPosition();
- var px2 = px1 + 4 * GameConfig.TileCellSize;
- if (px1 < minX)
- {
- minX = px1;
- }
- else if (px1 > maxX)
- {
- maxX = px1;
- }
-
- if (py1 < minY)
- {
- minY = py1;
- }
- else if (py1 > maxY)
- {
- maxY = py1;
- }
-
- if (px2 < minX)
- {
- minX = px2;
- }
- else if (px2 > maxX)
- {
- maxX = px2;
- }
- }
- break;
- }
- }
-
- OuterRect = new Rect2I(minX, minY, maxX - minX, maxY - minY);
-
- var cMinX = minX - GameConfig.TileCellSize;
- var cMinY = minY - GameConfig.TileCellSize;
- var cMaxX = maxX + GameConfig.TileCellSize;
- var cMaxY = maxY + GameConfig.TileCellSize;
- CanvasRect = new Rect2I(cMinX, cMinY, cMaxX - cMinX, cMaxY - cMinY);
-
- RoomOffset = new Vector2I(worldPos.X - cMinX, worldPos.Y - cMinY);
- }
-
- /// <summary>
- /// 获取房间的全局坐标, 单位: 像素
- /// </summary>
- public Vector2I GetWorldPosition()
- {
- return new Vector2I(
- Position.X * GameConfig.TileCellSize,
- Position.Y * GameConfig.TileCellSize
- );
- }
-
- /// <summary>
- /// 获取房间左上角的 Tile 距离全局坐标原点的偏移, 单位: 像素
- /// </summary>
- /// <returns></returns>
- public Vector2I GetOffsetPosition()
- {
- return RoomSplit.RoomInfo.Position.AsVector2I() * GameConfig.TileCellSize;
- }
-
- /// <summary>
- /// 将房间配置中的坐标转为全局坐标, 单位: 像素
- /// </summary>
- public Vector2 ToGlobalPosition(Vector2 pos)
- {
- return GetWorldPosition() + pos - GetOffsetPosition();
- }
-
- /// <summary>
- /// 获取房间横轴结束位置, 单位: 格
- /// </summary>
- public int GetHorizontalEnd()
- {
- return Position.X + Size.X;
- }
-
- /// <summary>
- /// 获取房间纵轴结束位置, 单位: 格
- /// </summary>
- public int GetVerticalEnd()
- {
- return Position.Y + Size.Y;
- }
-
- /// <summary>
- /// 获取房间横轴开始位置, 单位: 格
- /// </summary>
- public int GetHorizontalStart()
- {
- return Position.X;
- }
-
- /// <summary>
- /// 获取房间纵轴开始位置, 单位: 格
- /// </summary>
- public int GetVerticalStart()
- {
- return Position.Y;
- }
-
- /// <summary>
- /// 获取房间门横轴结束位置, 单位: 格
- /// </summary>
- public int GetHorizontalDoorEnd()
- {
- return Position.X + Size.X - 1;
- }
-
- /// <summary>
- /// 获取房间门纵轴结束位置, 单位: 格
- /// </summary>
- public int GetVerticalDoorEnd()
- {
- return Position.Y + Size.Y - 1;
- }
-
- /// <summary>
- /// 获取房间门横轴开始位置, 单位: 格
- /// </summary>
- public int GetHorizontalDoorStart()
- {
- return Position.X + 1;
- }
-
- /// <summary>
- /// 获取房间门纵轴开始位置, 单位: 格
- /// </summary>
- public int GetVerticalDoorStart()
- {
- return Position.Y + 2;
- }
-
- /// <summary>
- /// 获取房间宽度, 单位: 像素
- /// </summary>
- public int GetWidth()
- {
- return Size.X * GameConfig.TileCellSize;
- }
-
-
- /// <summary>
- /// 获取房间高度, 单位: 像素
- /// </summary>
- public int GetHeight()
- {
- return Size.Y * GameConfig.TileCellSize;
- }
-
- /// <summary>
- /// 将世界坐标转为画布下的坐标
- /// </summary>
- public Vector2 ToCanvasPosition(Vector2 pos)
- {
- return pos - CanvasRect.Position;
- }
-
- public void Destroy()
- {
- if (IsDestroyed)
- {
- return;
- }
-
- IsDestroyed = true;
- //递归销毁下一个房间
- foreach (var nextRoom in Next)
- {
- nextRoom.Destroy();
- }
- Next.Clear();
-
- //销毁连接的门
- foreach (var roomDoorInfo in Doors)
- {
- roomDoorInfo.Destroy();
- }
-
- //销毁预设
- if (RoomPreinstall != null)
- {
- RoomPreinstall.Destroy();
- RoomPreinstall = null;
- }
-
- //销毁画布
- if (StaticImageCanvas != null)
- {
- StaticImageCanvas.Destroy();
- }
-
- //销毁液体画布
- if (LiquidCanvas != null)
- {
- LiquidCanvas.Destroy();
- }
-
- //销毁静态精灵节点
- if (StaticSprite != null)
- {
- StaticSprite.Destroy();
- }
-
- //销毁迷雾
- if (RoomFogMask != null)
- {
- RoomFogMask.Destroy();
- }
-
- //销毁所属区域对象
- if (AffiliationArea != null)
- {
- AffiliationArea.Destroy();
- }
-
- //销毁预览图
- if (PreviewTexture != null)
- {
- PreviewTexture.Dispose();
- }
-
- if (PreviewSprite != null)
- {
- PreviewSprite.QueueFree();
- }
-
- MarkTargetPosition.Clear();
- }
-
- /// <summary>
- /// 加载地牢完成
- /// </summary>
- public void OnReady()
- {
- //提前加载波
- RoomPreinstall.OnReady();
- }
-
- /// <summary>
- /// 玩家第一次进入房间, 房间准备好了, 准备刷敌人, 并且关闭所有<br/>
- /// 当清完每一波刷新的敌人后即可开门
- /// </summary>
- public void OnFirstEnter()
- {
- if (RoomPreinstall.IsRunWave)
- {
- return;
- }
-
- //房间内有敌人, 或者会刷新敌人才会关门
- var hasEnemy = false;
- if (AffiliationArea.ExistEnterItem(activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy))) //先判断房间里面是否有敌人
- {
- hasEnemy = true;
- }
- else if (RoomPreinstall.HasEnemy()) //在判断是否会刷出敌人
- {
- hasEnemy = true;
- }
-
- if (!hasEnemy) //没有敌人, 不关门
- {
- IsSeclusion = false;
- //执行第一波生成
- RoomPreinstall.StartWave();
- return;
- }
-
- //关门
- CloseDoor();
- IsSeclusion = true;
-
- //执行第一波生成
- RoomPreinstall.StartWave();
- }
-
- /// <summary>
- /// 当前房间所有敌人都被清除了
- /// </summary>
- public void OnClearRoom()
- {
- if (RoomPreinstall.IsLastWave) //所有 mark 都走完了
- {
- IsSeclusion = false;
- if (RoomPreinstall.HasEnemy())
- {
- //开门
- OpenDoor();
- }
- //所有标记执行完成
- RoomPreinstall.OverWave();
- }
- else //执行下一波
- {
- RoomPreinstall.NextWave();
- }
- }
-
- /// <summary>
- /// 打开所有门
- /// </summary>
- public void OpenDoor()
- {
- if (!_openDoorFlag)
- {
- _openDoorFlag = true;
- AffiliationArea.RestoreRegion();
- }
-
- foreach (var doorInfo in Doors)
- {
- doorInfo.Door.OpenDoor();
-
- //过道迷雾
- doorInfo.AisleFogArea.Monitoring = true;
- if (doorInfo.AisleFogMask.IsExplored)
- {
- //doorInfo.ClearFog();
- FogMaskHandler.RefreshAisleFog(doorInfo);
- }
- }
- }
-
- /// <summary>
- /// 关闭所有门
- /// </summary>
- public void CloseDoor()
- {
- if (_openDoorFlag)
- {
- _openDoorFlag = false;
- AffiliationArea.ExtendedRegion(new Vector2(GameConfig.TileCellSize * 4, GameConfig.TileCellSize * 4));
- }
-
- foreach (var doorInfo in Doors)
- {
- doorInfo.Door.CloseDoor();
-
- //过道迷雾
- doorInfo.AisleFogArea.Monitoring = false;
- if (doorInfo.AisleFogMask.IsExplored)
- {
- //doorInfo.DarkFog();
- FogMaskHandler.RefreshAisleFog(doorInfo);
- }
- }
- }
-
- /// <summary>
- /// 遍历房间以及后面的房间
- /// </summary>
- public void EachRoom(Action<RoomInfo> callback)
- {
- callback(this);
- if (Next != null)
- {
- foreach (var room in Next)
- {
- room.EachRoom(callback);
- }
- }
- }
- }