diff --git a/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs b/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs new file mode 100644 index 0000000..befdbf9 --- /dev/null +++ b/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs @@ -0,0 +1,994 @@ + +using System; +using System.Collections.Generic; +using Godot; + +/// +/// 地牢生成器 +/// +public class DungeonGenerator +{ + /// + /// 所有生成的房间, 调用过 Generate() 函数才能获取到值 + /// + public List RoomInfos { get; } = new List(); + + /// + /// 起始房间 + /// + public RoomInfo StartRoom { get; private set; } + + /// + /// 生成的房间数量 + /// + private int _maxCount = 15; + + //用于标记地图上的坐标是否被占用 + private Grid _roomGrid { get; } = new Grid(); + + //当前房间数量 + private int _count = 0; + + //宽高 + private int _roomMinWidth = 15; + private int _roomMaxWidth = 35; + private int _roomMinHeight = 15; + private int _roomMaxHeight = 30; + + //间隔 + private int _roomMinInterval = 6; + private int _roomMaxInterval = 10; + + //房间横轴分散程度 + + private float _roomHorizontalMinDispersion = 0.3f; + private float _roomHorizontalMaxDispersion = 1.2f; + + //房间纵轴分散程度 + private float _roomVerticalMinDispersion = 0.3f; + private float _roomVerticalMaxDispersion = 1.2f; + + //区域限制 + private bool _enableLimitRange = true; + private int _rangeX = 110; + private int _rangeY = 110; + + //找房间失败次数, 过大则会关闭区域限制 + private int _maxFailCount = 10; + private int _failCount = 0; + + //最大尝试次数 + private int _maxTryCount = 10; + + private enum GenerateRoomErrorCode + { + NoError, + //房间已满 + RoomFull, + //超出区域 + OutArea, + //没有合适的位置 + NoSuitableLocation + // //碰到其他房间或过道 + // HasCollision, + // //没有合适的门 + // NoProperDoor, + } + + /// + /// 遍历所有房间 + /// + public void EachRoom(Action cb) + { + EachRoom(StartRoom, cb); + } + + private void EachRoom(RoomInfo roomInfo, Action cb) + { + if (roomInfo == null) + { + return; + } + + cb(roomInfo); + foreach (var next in roomInfo.Next) + { + EachRoom(next, cb); + } + } + + /// + /// 生成房间 + /// + public void Generate() + { + if (StartRoom != null) return; + + //第一个房间 + GenerateRoom(null, 0, out var startRoom); + StartRoom = startRoom; + + //如果房间数量不够, 就一直生成 + while (_count < _maxCount) + { + var room = Utils.RandomChoose(RoomInfos); + var errorCode = GenerateRoom(room, Utils.RandomRangeInt(0, 3), out var nextRoom); + if (errorCode == GenerateRoomErrorCode.NoError) + { + _failCount = 0; + room.Next.Add(nextRoom); + } + else + { + GD.Print("生成第" + (_count + 1) + "个房间失败! 失败原因: " + errorCode); + if (errorCode == GenerateRoomErrorCode.OutArea) + { + _failCount++; + GD.Print("超出区域失败次数: " + _failCount); + if (_failCount >= _maxFailCount) + { + _enableLimitRange = false; + GD.Print("生成房间失败次数过多, 关闭区域限制!"); + } + } + } + } + + _roomGrid.Clear(); + } + + //生成房间 + private GenerateRoomErrorCode GenerateRoom(RoomInfo prevRoomInfo, int direction, out RoomInfo resultRoom) + { + if (_count >= _maxCount) + { + resultRoom = null; + return GenerateRoomErrorCode.RoomFull; + } + + //随机选择一个房间 + var roomSplit = Utils.RandomChoose(GameApplication.Instance.RoomConfig); + //var roomSplit = GameApplication.Instance.RoomConfig[0]; + var room = new RoomInfo(_count, roomSplit); + + //房间大小 + room.Size = new Vector2I((int)roomSplit.RoomInfo.Size.X, (int)roomSplit.RoomInfo.Size.Y); + + if (prevRoomInfo != null) //表示这不是第一个房间, 就得判断当前位置下的房间是否被遮挡 + { + //生成的位置可能会和上一个房间对不上, 需要多次尝试 + var tryCount = 0; //当前尝试次数 + for (; tryCount < _maxTryCount; tryCount++) + { + //房间间隔 + var space = Utils.RandomRangeInt(_roomMinInterval, _roomMaxInterval); + //中心偏移 + int offset; + if (direction == 0 || direction == 2) + { + offset = Utils.RandomRangeInt(-(int)(prevRoomInfo.Size.X * _roomVerticalMinDispersion), + (int)(prevRoomInfo.Size.X * _roomVerticalMaxDispersion)); + } + else + { + offset = Utils.RandomRangeInt(-(int)(prevRoomInfo.Size.Y * _roomHorizontalMinDispersion), + (int)(prevRoomInfo.Size.Y * _roomHorizontalMaxDispersion)); + } + + //计算房间位置 + if (direction == 0) //上 + { + room.Position = new Vector2I(prevRoomInfo.Position.X + offset, + prevRoomInfo.Position.Y - room.Size.Y - space); + } + else if (direction == 1) //右 + { + room.Position = new Vector2I(prevRoomInfo.Position.X + prevRoomInfo.Size.Y + space, + prevRoomInfo.Position.Y + offset); + } + else if (direction == 2) //下 + { + room.Position = new Vector2I(prevRoomInfo.Position.X + offset, + prevRoomInfo.Position.Y + prevRoomInfo.Size.Y + space); + } + else if (direction == 3) //左 + { + room.Position = new Vector2I(prevRoomInfo.Position.X - room.Size.X - space, + prevRoomInfo.Position.Y + offset); + } + + //是否在限制区域内 + if (_enableLimitRange) + { + if (room.GetHorizontalStart() < -_rangeX || room.GetHorizontalEnd() > _rangeX || + room.GetVerticalStart() < -_rangeY || room.GetVerticalEnd() > _rangeY) + { + //超出区域, 直接跳出尝试的循环, 返回 null + resultRoom = null; + return GenerateRoomErrorCode.OutArea; + } + } + + //是否碰到其他房间或者过道 + if (_roomGrid.RectCollision(room.Position - new Vector2(GameConfig.RoomSpace, GameConfig.RoomSpace), room.Size + new Vector2(GameConfig.RoomSpace * 2, GameConfig.RoomSpace * 2))) + { + //碰到其他墙壁, 再一次尝试 + continue; + //return GenerateRoomErrorCode.HasCollision; + } + + _roomGrid.AddRect(room.Position, room.Size, true); + + //找门, 与上一个房间是否能连通 + if (!ConnectDoor(prevRoomInfo, room)) + { + _roomGrid.RemoveRect(room.Position, room.Size); + //房间过道没有连接上, 再一次尝试 + continue; + //return GenerateRoomErrorCode.NoProperDoor; + } + break; + } + + //尝试次数用光了, 还没有找到合适的位置 + if (tryCount >= _maxTryCount) + { + resultRoom = null; + return GenerateRoomErrorCode.NoSuitableLocation; + } + } + + _count++; + RoomInfos.Add(room); + if (prevRoomInfo == null) + { + _roomGrid.AddRect(room.Position, room.Size, true); + } + + //下一个房间 + //0上, 1右, 2下, 3左 + var dirList = new List(new[] { 0, 1, 2, 3 }); + if (prevRoomInfo != null) + { + dirList.Remove(GetReverseDirection(direction)); + } + + //这条线有一定概率不生成下一个房间 + if (Utils.RandomRangeInt(0, 2) != 0) + { + while (dirList.Count > 0) + { + var randDir = Utils.RandomChoose(dirList); + GenerateRoom(room, randDir, out var nextRoom); + if (nextRoom == null) + { + break; + } + + nextRoom.Prev = room; + room.Next.Add(nextRoom); + + dirList.Remove(randDir); + } + } + + resultRoom = room; + return GenerateRoomErrorCode.NoError; + } + + /// + /// 找两个房间的门 + /// + private bool ConnectDoor(RoomInfo room, RoomInfo nextRoom) + { + //门描述 + var roomDoor = new RoomDoorInfo(); + var nextRoomDoor = new RoomDoorInfo(); + roomDoor.RoomInfo = room; + nextRoomDoor.RoomInfo = nextRoom; + roomDoor.ConnectRoom = nextRoom; + roomDoor.ConnectDoor = nextRoomDoor; + nextRoomDoor.ConnectRoom = room; + nextRoomDoor.ConnectDoor = roomDoor; + + //先寻找直通门 + if (Utils.RandomBoolean()) + { + //直行通道, 优先横轴 + if (TryConnectHorizontalDoor(room, roomDoor, nextRoom, nextRoomDoor) + || TryConnectVerticalDoor(room, roomDoor, nextRoom, nextRoomDoor)) + { + return true; + } + } + else + { + //直行通道, 优先纵轴 + if (TryConnectVerticalDoor(room, roomDoor, nextRoom, nextRoomDoor) + || TryConnectHorizontalDoor(room, roomDoor, nextRoom, nextRoomDoor)) + { + return true; + } + } + + //包含拐角的通道 + return TryConnectCrossDoor(room, roomDoor, nextRoom, nextRoomDoor); + } + + /// + /// 尝试寻找横轴方向上两个房间的连通的门, 只查找直线通道, 返回是否找到 + /// + private bool TryConnectHorizontalDoor(RoomInfo room, RoomDoorInfo roomDoor, RoomInfo nextRoom, RoomDoorInfo nextRoomDoor) + { + var overlapX = Mathf.Min(room.GetHorizontalEnd(), nextRoom.GetHorizontalEnd()) - + Mathf.Max(room.GetHorizontalStart(), nextRoom.GetHorizontalStart()); + //这种情况下x轴有重叠 + if (overlapX >= 6) + { + //找到重叠区域 + var rangeList = FindPassage(room, nextRoom, + room.GetVerticalStart() < nextRoom.GetVerticalStart() ? DoorDirection.S : DoorDirection.N); + + while (rangeList.Count > 0) + { + //找到重叠区域 + var range = Utils.RandomChooseAndRemove(rangeList); + var x = Utils.RandomRangeInt(range.X, range.Y); + + if (room.GetVerticalStart() < nextRoom.GetVerticalStart()) //room在上, nextRoom在下 + { + roomDoor.Direction = DoorDirection.S; + nextRoomDoor.Direction = DoorDirection.N; + roomDoor.OriginPosition = new Vector2(x, room.GetVerticalEnd()); + nextRoomDoor.OriginPosition = new Vector2(x, nextRoom.GetVerticalStart()); + } + else //room在下, nextRoom在上 + { + roomDoor.Direction = DoorDirection.N; + nextRoomDoor.Direction = DoorDirection.S; + roomDoor.OriginPosition = new Vector2(x, room.GetVerticalStart()); + nextRoomDoor.OriginPosition = new Vector2(x, nextRoom.GetVerticalEnd()); + } + + //判断门之间的通道是否有物体碰到 + if (!AddCorridorToGridRange(roomDoor, nextRoomDoor)) + { + //此门不能连通 + continue; + } + + //没有撞到物体 + room.Doors.Add(roomDoor); + nextRoom.Doors.Add(nextRoomDoor); + return true; + } + } + + return false; + } + + /// + /// 尝试寻找纵轴方向上两个房间的连通的门, 只查找直线通道, 返回是否找到 + /// + private bool TryConnectVerticalDoor(RoomInfo room, RoomDoorInfo roomDoor, RoomInfo nextRoom, RoomDoorInfo nextRoomDoor) + { + var overlapY = Mathf.Min(room.GetVerticalEnd(), nextRoom.GetVerticalEnd()) - + Mathf.Max(room.GetVerticalStart(), nextRoom.GetVerticalStart()); + //这种情况下y轴有重叠 + if (overlapY >= 6) + { + //找到重叠区域 + var rangeList = FindPassage(room, nextRoom, + room.GetHorizontalStart() < nextRoom.GetHorizontalStart() ? DoorDirection.E : DoorDirection.W); + + while (rangeList.Count > 0) + { + //找到重叠区域 + var range = Utils.RandomChooseAndRemove(rangeList); + var y = Utils.RandomRangeInt(range.X, range.Y); + + if (room.GetHorizontalStart() < nextRoom.GetHorizontalStart()) //room在左, nextRoom在右 + { + roomDoor.Direction = DoorDirection.E; + nextRoomDoor.Direction = DoorDirection.W; + roomDoor.OriginPosition = new Vector2(room.GetHorizontalEnd(), y); + nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart(), y); + } + else //room在右, nextRoom在左 + { + roomDoor.Direction = DoorDirection.W; + nextRoomDoor.Direction = DoorDirection.E; + roomDoor.OriginPosition = new Vector2(room.GetHorizontalStart(), y); + nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalEnd(), y); + } + + //判断门之间的通道是否有物体碰到 + if (!AddCorridorToGridRange(roomDoor, nextRoomDoor)) + { + //此门不能连通 + continue; + } + + //没有撞到物体 + room.Doors.Add(roomDoor); + nextRoom.Doors.Add(nextRoomDoor); + return true; + } + } + + return false; + } + + /// + /// 尝试寻找包含拐角的两个房间的连通的门, 返回是否找到 + /// + private bool TryConnectCrossDoor(RoomInfo room, RoomDoorInfo roomDoor, RoomInfo nextRoom, RoomDoorInfo nextRoomDoor) + { + //焦点 + Vector2 cross = default; + + if (room.GetHorizontalStart() > nextRoom.GetHorizontalStart()) + { + if (room.GetVerticalStart() > nextRoom.GetVerticalStart()) + { + if (Utils.RandomBoolean()) //↑ //→ + { + if (!TryConnect_NE_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && + !TryConnect_WS_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) + { + return false; + } + } + else //← //↓ + { + if (!TryConnect_WS_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && + !TryConnect_NE_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) + { + return false; + } + } + } + else + { + if (Utils.RandomBoolean()) //↓ //→ + { + if (!TryConnect_SE_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && + !TryConnect_WN_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) + { + return false; + } + } + else //← //↑ + { + if (!TryConnect_WN_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && + !TryConnect_SE_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) + { + return false; + } + } + } + } + else + { + if (room.GetVerticalStart() > nextRoom.GetVerticalStart()) //→ //↓ + { + if (Utils.RandomBoolean()) + { + if (!TryConnect_ES_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && + !TryConnect_NW_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) + { + return false; + } + } + else //↑ //← + { + if (!TryConnect_NW_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && + !TryConnect_ES_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) + { + return false; + } + } + } + else + { + if (Utils.RandomBoolean()) //→ //↑ + { + if (!TryConnect_EN_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && + !TryConnect_SW_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) + { + return false; + } + } + else //↓ //← + { + if (!TryConnect_SW_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && + !TryConnect_EN_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) + { + return false; + } + } + } + } + + //判断门之间的通道是否有物体碰到 + if (!AddCorridorToGridRange(roomDoor, nextRoomDoor, cross)) + { + //此门不能连通 + return false; + } + + roomDoor.HasCross = true; + roomDoor.Cross = cross; + nextRoomDoor.HasCross = true; + nextRoomDoor.Cross = cross; + + room.Doors.Add(roomDoor); + nextRoom.Doors.Add(nextRoomDoor); + return true; + } + + private bool FindCrossPassage(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor,ref int offset1, ref int offset2) + { + var room1 = room.RoomSplit.RoomInfo; + var room2 = nextRoom.RoomSplit.RoomInfo; + + Vector2I? temp1 = null; + Vector2I? temp2 = null; + + foreach (var areaInfo1 in room1.DoorAreaInfos) + { + if (areaInfo1.Direction == roomDoor.Direction) + { + FindCrossPassage_Area(areaInfo1, room, nextRoom, ref temp1); + } + } + + foreach (var areaInfo2 in room2.DoorAreaInfos) + { + if (areaInfo2.Direction == nextRoomDoor.Direction) + { + FindCrossPassage_Area(areaInfo2, nextRoom, room, ref temp2); + } + } + + if (temp1 != null && temp2 != null) + { + offset1 = Utils.RandomRangeInt(temp1.Value.X, temp1.Value.Y); + offset2 = Utils.RandomRangeInt(temp2.Value.X, temp2.Value.Y); + return true; + } + + return false; + } + + private void FindCrossPassage_Area(DoorAreaInfo areaInfo, RoomInfo room1, RoomInfo room2, ref Vector2I? areaRange) + { + if (areaInfo.Direction == DoorDirection.N || areaInfo.Direction == DoorDirection.S) //纵向门 + { + var num = room1.GetHorizontalStart(); + var p1 = num + areaInfo.Start / GameConfig.TileCellSize; + var p2 = num + areaInfo.End / GameConfig.TileCellSize; + + if (room1.Position.X > room2.Position.X) + { + var range = CalcOverlapRange(room2.GetHorizontalEnd(), + room1.GetHorizontalEnd(), p1, p2); + //交集范围够生成门 + if (range.Y - range.X >= GameConfig.CorridorWidth) + { + // var tempRange = new Vector2I(Mathf.Abs(room1.Position.X - (int)range.X), + // Mathf.Abs(room1.Position.X - (int)range.Y) - GameConfig.CorridorWidth); + + var rangeValue = Mathf.Abs(room1.Position.X - (int)range.Y) - GameConfig.CorridorWidth; + if (areaRange == null || rangeValue < areaRange.Value.X) + { + areaRange = new Vector2I(rangeValue, rangeValue); + } + } + } + else + { + var range = CalcOverlapRange(room1.GetHorizontalStart(), + room2.GetHorizontalStart(), p1, p2); + //交集范围够生成门 + if (range.Y - range.X >= GameConfig.CorridorWidth) + { + // var tempRange = new Vector2I(Mathf.Abs(room1.Position.X - (int)range.X), + // Mathf.Abs(room1.Position.X - (int)range.Y) - GameConfig.CorridorWidth); + + var rangeValue = Mathf.Abs(room1.Position.X - (int)range.Y) - GameConfig.CorridorWidth; + if (areaRange == null || rangeValue > areaRange.Value.Y) + { + areaRange = new Vector2I(rangeValue, rangeValue); + } + } + } + } + else //横向门 + { + var num = room1.GetVerticalStart(); + var p1 = num + areaInfo.Start / GameConfig.TileCellSize; + var p2 = num + areaInfo.End / GameConfig.TileCellSize; + + if (room1.Position.Y > room2.Position.Y) + { + var range = CalcOverlapRange(room2.GetVerticalEnd(), + room1.GetVerticalEnd(), p1, p2); + //交集范围够生成门 + if (range.Y - range.X >= GameConfig.CorridorWidth) + { + // var tempRange = new Vector2I(Mathf.Abs(room1.Position.Y - (int)range.X), + // Mathf.Abs(room1.Position.Y - (int)range.Y) - GameConfig.CorridorWidth); + + var rangeValue = Mathf.Abs(room1.Position.Y - (int)range.X); + if (areaRange == null || rangeValue < areaRange.Value.X) + { + areaRange = new Vector2I(rangeValue, rangeValue); + } + } + } + else + { + var range = CalcOverlapRange(room1.GetVerticalStart(), + room2.GetVerticalStart(), p1, p2); + //交集范围够生成门 + if (range.Y - range.X >= GameConfig.CorridorWidth) + { + // var tempRange = new Vector2I(Mathf.Abs(room1.Position.Y - (int)range.X), + // Mathf.Abs(room1.Position.Y - (int)range.Y) - GameConfig.CorridorWidth); + + var rangeValue = Mathf.Abs(room1.Position.Y - (int)range.Y) - GameConfig.CorridorWidth; + if (areaRange == null || rangeValue > areaRange.Value.Y) + { + areaRange = new Vector2I(rangeValue, rangeValue); + } + } + } + } + } + + private bool TryConnect_NE_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) + { + var offset1 = 0; + var offset2 = 0; + roomDoor.Direction = DoorDirection.N; //↑ + nextRoomDoor.Direction = DoorDirection.E; //→ + + if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) + { + return false; + } + + roomDoor.OriginPosition = new Vector2(room.GetHorizontalStart() + offset1, room.GetVerticalStart()); + nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalEnd(), + nextRoom.GetVerticalStart() + offset2); + cross = new Vector2(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y); + return true; + } + + private bool TryConnect_WS_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) + { + //ok + var offset1 = 0; + var offset2 = 0; + roomDoor.Direction = DoorDirection.W; //← + nextRoomDoor.Direction = DoorDirection.S; //↓ + + if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) + { + return false; + } + + roomDoor.OriginPosition = new Vector2(room.GetHorizontalStart(), room.GetVerticalStart() + offset1); + nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart() + offset2, nextRoom.GetVerticalEnd()); + cross = new Vector2(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y); + return true; + } + + private bool TryConnect_SE_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) + { + var offset1 = 0; + var offset2 = 0; + roomDoor.Direction = DoorDirection.S; //↓ + nextRoomDoor.Direction = DoorDirection.E; //→ + + if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) + { + return false; + } + + roomDoor.OriginPosition = new Vector2(room.GetHorizontalStart() + offset1, room.GetVerticalEnd()); + nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalEnd(), + nextRoom.GetVerticalStart() + offset2); + cross = new Vector2(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y); + return true; + } + + private bool TryConnect_WN_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) + { + var offset1 = 0; + var offset2 = 0; + roomDoor.Direction = DoorDirection.W; //← + nextRoomDoor.Direction = DoorDirection.N; //↑ + + if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) + { + return false; + } + + roomDoor.OriginPosition = + new Vector2(room.GetHorizontalStart(), room.GetVerticalStart() + offset1); // + nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart() + offset2, + nextRoom.GetVerticalStart()); + cross = new Vector2(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y); + return true; + } + + private bool TryConnect_ES_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) + { + var offset1 = 0; + var offset2 = 0; + roomDoor.Direction = DoorDirection.E; //→ + nextRoomDoor.Direction = DoorDirection.S; //↓ + + if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) + { + return false; + } + + roomDoor.OriginPosition = new Vector2(room.GetHorizontalEnd(), room.GetVerticalStart() + offset1); + nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart() + offset2, + nextRoom.GetVerticalEnd()); + cross = new Vector2(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y); + return true; + } + + private bool TryConnect_NW_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) + { + var offset1 = 0; + var offset2 = 0; + roomDoor.Direction = DoorDirection.N; //↑ + nextRoomDoor.Direction = DoorDirection.W; //← + + if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) + { + return false; + } + + roomDoor.OriginPosition = new Vector2(room.GetHorizontalStart() + offset1, room.GetVerticalStart()); + nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart(), + nextRoom.GetVerticalStart() + offset2); + cross = new Vector2(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y); + return true; + } + + private bool TryConnect_EN_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) + { + var offset1 = 0; + var offset2 = 0; + roomDoor.Direction = DoorDirection.E; //→ + nextRoomDoor.Direction = DoorDirection.N; //↑ + + if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) + { + return false; + } + + roomDoor.OriginPosition = new Vector2(room.GetHorizontalEnd(), + room.GetVerticalStart() + offset1); + nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart() + offset2, nextRoom.GetVerticalStart()); + cross = new Vector2(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y); + return true; + } + + private bool TryConnect_SW_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) + { + var offset1 = 0; + var offset2 = 0; + roomDoor.Direction = DoorDirection.S; //↓ + nextRoomDoor.Direction = DoorDirection.W; //← + + if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) + { + return false; + } + + roomDoor.OriginPosition = new Vector2(room.GetHorizontalStart() + offset1, + room.GetVerticalEnd()); + nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart(), nextRoom.GetVerticalStart() + offset2); + cross = new Vector2(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y); + return true; + } + + /// + /// 查找房间的连接通道, 函数返回是否找到对应的门, 通过 result 返回 x/y 轴坐标 + /// + /// 第一个房间 + /// 第二个房间 + /// 第一个房间连接方向 + private List FindPassage(RoomInfo room, RoomInfo nextRoom, DoorDirection direction) + { + var room1 = room.RoomSplit.RoomInfo; + var room2 = nextRoom.RoomSplit.RoomInfo; + + //用于存储符合生成条件的区域 + var rangeList = new List(); + + foreach (var doorAreaInfo1 in room1.DoorAreaInfos) + { + if (doorAreaInfo1.Direction == direction) + { + //第二个门的方向 + var direction2 = GetReverseDirection(direction); + + foreach (var doorAreaInfo2 in room2.DoorAreaInfos) + { + if (doorAreaInfo2.Direction == direction2) + { + Vector2 range; + if (direction == DoorDirection.E || direction == DoorDirection.W) //第二个门向← 或者 第二个门向→ + { + range = CalcOverlapRange( + room.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo1.Start, room.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo1.End, + nextRoom.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo2.Start, nextRoom.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo2.End + ); + } + else //第二个门向↑ 或者 第二个门向↓ + { + range = CalcOverlapRange( + room.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo1.Start, room.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo1.End, + nextRoom.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo2.Start, nextRoom.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo2.End + ); + } + //交集范围够生成门 + if (range.Y - range.X >= GameConfig.CorridorWidth * GameConfig.TileCellSize) + { + rangeList.Add(new Vector2I((int)(range.X / 16), (int)(range.Y / 16) - GameConfig.CorridorWidth)); + } + } + } + } + } + + return rangeList; + } + + /// + /// 用于计算重叠区域坐标, 可以理解为一维轴上4个点的中间两个点, 返回的x为起始点, y为结束点 + /// + private Vector2 CalcOverlapRange(float start1, float end1, float start2, float end2) + { + return new Vector2(Mathf.Max(start1, start2), Mathf.Min(end1, end2)); + } + + /// + /// 返回 p1 - p2 是否在 start - end 范围内 + /// + private bool IsInRange(float start, float end, float p1, float p2) + { + return p1 >= start && p2 <= end; + } + + //返回指定方向的反方向 + //0上, 1右, 2下, 3左 + private int GetReverseDirection(int direction) + { + switch (direction) + { + case 0: return 2; + case 1: return 3; + case 2: return 0; + case 3: return 1; + } + + return 2; + } + + //返回参数方向的反方向 + private DoorDirection GetReverseDirection(DoorDirection direction) + { + switch (direction) + { + case DoorDirection.E: + return DoorDirection.W; + case DoorDirection.W: + return DoorDirection.E; + case DoorDirection.S: + return DoorDirection.N; + case DoorDirection.N: + return DoorDirection.S; + } + + return DoorDirection.S; + } + + //将两个门间的过道占用数据存入RoomGrid + private bool AddCorridorToGridRange(RoomDoorInfo door1, RoomDoorInfo door2) + { + var point1 = door1.OriginPosition; + var point2 = door2.OriginPosition; + var pos = new Vector2(Mathf.Min(point1.X, point2.X), Mathf.Min(point1.Y, point2.Y)); + var size = new Vector2( + point1.X == point2.X ? GameConfig.CorridorWidth : Mathf.Abs(point1.X - point2.X), + point1.Y == point2.Y ? GameConfig.CorridorWidth : Mathf.Abs(point1.Y - point2.Y) + ); + + Vector2 collPos; + Vector2 collSize; + if (point1.X == point2.X) //纵向加宽, 防止贴到其它墙 + { + collPos = new Vector2(pos.X - GameConfig.RoomSpace, pos.Y); + collSize = new Vector2(size.X + GameConfig.RoomSpace * 2, size.Y); + } + else //横向加宽, 防止贴到其它墙 + { + collPos = new Vector2(pos.X, pos.Y - GameConfig.RoomSpace); + collSize = new Vector2(size.X, size.Y + GameConfig.RoomSpace * 2); + } + + if (_roomGrid.RectCollision(collPos, collSize)) + { + return false; + } + + _roomGrid.AddRect(pos, size, true); + return true; + } + + //将两个门间的过道占用数据存入RoomGrid, 该重载加入拐角点 + private bool AddCorridorToGridRange(RoomDoorInfo door1, RoomDoorInfo door2, Vector2 cross) + { + var point1 = door1.OriginPosition; + var point2 = door2.OriginPosition; + var pos1 = new Vector2(Mathf.Min(point1.X, cross.X), Mathf.Min(point1.Y, cross.Y)); + var size1 = new Vector2( + point1.X == cross.X ? GameConfig.CorridorWidth : Mathf.Abs(point1.X - cross.X), + point1.Y == cross.Y ? GameConfig.CorridorWidth : Mathf.Abs(point1.Y - cross.Y) + ); + var pos2 = new Vector2(Mathf.Min(point2.X, cross.X), Mathf.Min(point2.Y, cross.Y)); + var size2 = new Vector2( + point2.X == cross.X ? GameConfig.CorridorWidth : Mathf.Abs(point2.X - cross.X), + point2.Y == cross.Y ? GameConfig.CorridorWidth : Mathf.Abs(point2.Y - cross.Y) + ); + + Vector2 collPos1; + Vector2 collSize1; + if (point1.X == cross.X) //纵向加宽, 防止贴到其它墙 + { + collPos1 = new Vector2(pos1.X - GameConfig.RoomSpace, pos1.Y); + collSize1 = new Vector2(size1.X + GameConfig.RoomSpace * 2, size1.Y); + } + else //横向加宽, 防止贴到其它墙 + { + collPos1 = new Vector2(pos1.X, pos1.Y - GameConfig.RoomSpace); + collSize1 = new Vector2(size1.X, size1.Y + GameConfig.RoomSpace * 2); + } + + if (_roomGrid.RectCollision(collPos1, collSize1)) + { + return false; + } + + Vector2 collPos2; + Vector2 collSize2; + if (point2.X == cross.X) //纵向加宽, 防止贴到其它墙 + { + collPos2 = new Vector2(pos2.X - GameConfig.RoomSpace, pos2.Y); + collSize2 = new Vector2(size2.X + GameConfig.RoomSpace * 2, size2.Y); + } + else //横向加宽, 防止贴到其它墙 + { + collPos2 = new Vector2(pos2.X, pos2.Y - GameConfig.RoomSpace); + collSize2 = new Vector2(size2.X, size2.Y + GameConfig.RoomSpace * 2); + } + + if (_roomGrid.RectCollision(collPos2, collSize2)) + { + return false; + } + + _roomGrid.AddRect(pos1, size1, true); + _roomGrid.AddRect(pos2, size2, true); + return true; + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/map/GenerateDungeon.cs b/DungeonShooting_Godot/src/framework/map/GenerateDungeon.cs deleted file mode 100644 index 6e2720b..0000000 --- a/DungeonShooting_Godot/src/framework/map/GenerateDungeon.cs +++ /dev/null @@ -1,994 +0,0 @@ - -using System; -using System.Collections.Generic; -using Godot; - -/// -/// 地牢生成器 -/// -public class GenerateDungeon -{ - /// - /// 所有生成的房间, 调用过 Generate() 函数才能获取到值 - /// - public List RoomInfos { get; } = new List(); - - /// - /// 起始房间 - /// - public RoomInfo StartRoom { get; private set; } - - /// - /// 生成的房间数量 - /// - private int _maxCount = 15; - - //用于标记地图上的坐标是否被占用 - private Grid _roomGrid { get; } = new Grid(); - - //当前房间数量 - private int _count = 0; - - //宽高 - private int _roomMinWidth = 15; - private int _roomMaxWidth = 35; - private int _roomMinHeight = 15; - private int _roomMaxHeight = 30; - - //间隔 - private int _roomMinInterval = 6; - private int _roomMaxInterval = 10; - - //房间横轴分散程度 - - private float _roomHorizontalMinDispersion = 0.3f; - private float _roomHorizontalMaxDispersion = 1.2f; - - //房间纵轴分散程度 - private float _roomVerticalMinDispersion = 0.3f; - private float _roomVerticalMaxDispersion = 1.2f; - - //区域限制 - private bool _enableLimitRange = true; - private int _rangeX = 110; - private int _rangeY = 110; - - //找房间失败次数, 过大则会关闭区域限制 - private int _maxFailCount = 10; - private int _failCount = 0; - - //最大尝试次数 - private int _maxTryCount = 10; - - private enum GenerateRoomErrorCode - { - NoError, - //房间已满 - RoomFull, - //超出区域 - OutArea, - //没有合适的位置 - NoSuitableLocation - // //碰到其他房间或过道 - // HasCollision, - // //没有合适的门 - // NoProperDoor, - } - - /// - /// 遍历所有房间 - /// - public void EachRoom(Action cb) - { - EachRoom(StartRoom, cb); - } - - private void EachRoom(RoomInfo roomInfo, Action cb) - { - if (roomInfo == null) - { - return; - } - - cb(roomInfo); - foreach (var next in roomInfo.Next) - { - EachRoom(next, cb); - } - } - - /// - /// 生成房间 - /// - public void Generate() - { - if (StartRoom != null) return; - - //第一个房间 - GenerateRoom(null, 0, out var startRoom); - StartRoom = startRoom; - - //如果房间数量不够, 就一直生成 - while (_count < _maxCount) - { - var room = Utils.RandomChoose(RoomInfos); - var errorCode = GenerateRoom(room, Utils.RandomRangeInt(0, 3), out var nextRoom); - if (errorCode == GenerateRoomErrorCode.NoError) - { - _failCount = 0; - room.Next.Add(nextRoom); - } - else - { - GD.Print("生成第" + (_count + 1) + "个房间失败! 失败原因: " + errorCode); - if (errorCode == GenerateRoomErrorCode.OutArea) - { - _failCount++; - GD.Print("超出区域失败次数: " + _failCount); - if (_failCount >= _maxFailCount) - { - _enableLimitRange = false; - GD.Print("生成房间失败次数过多, 关闭区域限制!"); - } - } - } - } - - _roomGrid.Clear(); - } - - //生成房间 - private GenerateRoomErrorCode GenerateRoom(RoomInfo prevRoomInfo, int direction, out RoomInfo resultRoom) - { - if (_count >= _maxCount) - { - resultRoom = null; - return GenerateRoomErrorCode.RoomFull; - } - - //随机选择一个房间 - var roomSplit = Utils.RandomChoose(GameApplication.Instance.RoomConfig); - //var roomSplit = GameApplication.Instance.RoomConfig[0]; - var room = new RoomInfo(_count, roomSplit); - - //房间大小 - room.Size = new Vector2I((int)roomSplit.RoomInfo.Size.X, (int)roomSplit.RoomInfo.Size.Y); - - if (prevRoomInfo != null) //表示这不是第一个房间, 就得判断当前位置下的房间是否被遮挡 - { - //生成的位置可能会和上一个房间对不上, 需要多次尝试 - var tryCount = 0; //当前尝试次数 - for (; tryCount < _maxTryCount; tryCount++) - { - //房间间隔 - var space = Utils.RandomRangeInt(_roomMinInterval, _roomMaxInterval); - //中心偏移 - int offset; - if (direction == 0 || direction == 2) - { - offset = Utils.RandomRangeInt(-(int)(prevRoomInfo.Size.X * _roomVerticalMinDispersion), - (int)(prevRoomInfo.Size.X * _roomVerticalMaxDispersion)); - } - else - { - offset = Utils.RandomRangeInt(-(int)(prevRoomInfo.Size.Y * _roomHorizontalMinDispersion), - (int)(prevRoomInfo.Size.Y * _roomHorizontalMaxDispersion)); - } - - //计算房间位置 - if (direction == 0) //上 - { - room.Position = new Vector2I(prevRoomInfo.Position.X + offset, - prevRoomInfo.Position.Y - room.Size.Y - space); - } - else if (direction == 1) //右 - { - room.Position = new Vector2I(prevRoomInfo.Position.X + prevRoomInfo.Size.Y + space, - prevRoomInfo.Position.Y + offset); - } - else if (direction == 2) //下 - { - room.Position = new Vector2I(prevRoomInfo.Position.X + offset, - prevRoomInfo.Position.Y + prevRoomInfo.Size.Y + space); - } - else if (direction == 3) //左 - { - room.Position = new Vector2I(prevRoomInfo.Position.X - room.Size.X - space, - prevRoomInfo.Position.Y + offset); - } - - //是否在限制区域内 - if (_enableLimitRange) - { - if (room.GetHorizontalStart() < -_rangeX || room.GetHorizontalEnd() > _rangeX || - room.GetVerticalStart() < -_rangeY || room.GetVerticalEnd() > _rangeY) - { - //超出区域, 直接跳出尝试的循环, 返回 null - resultRoom = null; - return GenerateRoomErrorCode.OutArea; - } - } - - //是否碰到其他房间或者过道 - if (_roomGrid.RectCollision(room.Position - new Vector2(GameConfig.RoomSpace, GameConfig.RoomSpace), room.Size + new Vector2(GameConfig.RoomSpace * 2, GameConfig.RoomSpace * 2))) - { - //碰到其他墙壁, 再一次尝试 - continue; - //return GenerateRoomErrorCode.HasCollision; - } - - _roomGrid.AddRect(room.Position, room.Size, true); - - //找门, 与上一个房间是否能连通 - if (!ConnectDoor(prevRoomInfo, room)) - { - _roomGrid.RemoveRect(room.Position, room.Size); - //房间过道没有连接上, 再一次尝试 - continue; - //return GenerateRoomErrorCode.NoProperDoor; - } - break; - } - - //尝试次数用光了, 还没有找到合适的位置 - if (tryCount >= _maxTryCount) - { - resultRoom = null; - return GenerateRoomErrorCode.NoSuitableLocation; - } - } - - _count++; - RoomInfos.Add(room); - if (prevRoomInfo == null) - { - _roomGrid.AddRect(room.Position, room.Size, true); - } - - //下一个房间 - //0上, 1右, 2下, 3左 - var dirList = new List(new[] { 0, 1, 2, 3 }); - if (prevRoomInfo != null) - { - dirList.Remove(GetReverseDirection(direction)); - } - - //这条线有一定概率不生成下一个房间 - if (Utils.RandomRangeInt(0, 2) != 0) - { - while (dirList.Count > 0) - { - var randDir = Utils.RandomChoose(dirList); - GenerateRoom(room, randDir, out var nextRoom); - if (nextRoom == null) - { - break; - } - - nextRoom.Prev = room; - room.Next.Add(nextRoom); - - dirList.Remove(randDir); - } - } - - resultRoom = room; - return GenerateRoomErrorCode.NoError; - } - - /// - /// 找两个房间的门 - /// - private bool ConnectDoor(RoomInfo room, RoomInfo nextRoom) - { - //门描述 - var roomDoor = new RoomDoorInfo(); - var nextRoomDoor = new RoomDoorInfo(); - roomDoor.RoomInfo = room; - nextRoomDoor.RoomInfo = nextRoom; - roomDoor.ConnectRoom = nextRoom; - roomDoor.ConnectDoor = nextRoomDoor; - nextRoomDoor.ConnectRoom = room; - nextRoomDoor.ConnectDoor = roomDoor; - - //先寻找直通门 - if (Utils.RandomBoolean()) - { - //直行通道, 优先横轴 - if (TryConnectHorizontalDoor(room, roomDoor, nextRoom, nextRoomDoor) - || TryConnectVerticalDoor(room, roomDoor, nextRoom, nextRoomDoor)) - { - return true; - } - } - else - { - //直行通道, 优先纵轴 - if (TryConnectVerticalDoor(room, roomDoor, nextRoom, nextRoomDoor) - || TryConnectHorizontalDoor(room, roomDoor, nextRoom, nextRoomDoor)) - { - return true; - } - } - - //包含拐角的通道 - return TryConnectCrossDoor(room, roomDoor, nextRoom, nextRoomDoor); - } - - /// - /// 尝试寻找横轴方向上两个房间的连通的门, 只查找直线通道, 返回是否找到 - /// - private bool TryConnectHorizontalDoor(RoomInfo room, RoomDoorInfo roomDoor, RoomInfo nextRoom, RoomDoorInfo nextRoomDoor) - { - var overlapX = Mathf.Min(room.GetHorizontalEnd(), nextRoom.GetHorizontalEnd()) - - Mathf.Max(room.GetHorizontalStart(), nextRoom.GetHorizontalStart()); - //这种情况下x轴有重叠 - if (overlapX >= 6) - { - //找到重叠区域 - var rangeList = FindPassage(room, nextRoom, - room.GetVerticalStart() < nextRoom.GetVerticalStart() ? DoorDirection.S : DoorDirection.N); - - while (rangeList.Count > 0) - { - //找到重叠区域 - var range = Utils.RandomChooseAndRemove(rangeList); - var x = Utils.RandomRangeInt(range.X, range.Y); - - if (room.GetVerticalStart() < nextRoom.GetVerticalStart()) //room在上, nextRoom在下 - { - roomDoor.Direction = DoorDirection.S; - nextRoomDoor.Direction = DoorDirection.N; - roomDoor.OriginPosition = new Vector2(x, room.GetVerticalEnd()); - nextRoomDoor.OriginPosition = new Vector2(x, nextRoom.GetVerticalStart()); - } - else //room在下, nextRoom在上 - { - roomDoor.Direction = DoorDirection.N; - nextRoomDoor.Direction = DoorDirection.S; - roomDoor.OriginPosition = new Vector2(x, room.GetVerticalStart()); - nextRoomDoor.OriginPosition = new Vector2(x, nextRoom.GetVerticalEnd()); - } - - //判断门之间的通道是否有物体碰到 - if (!AddCorridorToGridRange(roomDoor, nextRoomDoor)) - { - //此门不能连通 - continue; - } - - //没有撞到物体 - room.Doors.Add(roomDoor); - nextRoom.Doors.Add(nextRoomDoor); - return true; - } - } - - return false; - } - - /// - /// 尝试寻找纵轴方向上两个房间的连通的门, 只查找直线通道, 返回是否找到 - /// - private bool TryConnectVerticalDoor(RoomInfo room, RoomDoorInfo roomDoor, RoomInfo nextRoom, RoomDoorInfo nextRoomDoor) - { - var overlapY = Mathf.Min(room.GetVerticalEnd(), nextRoom.GetVerticalEnd()) - - Mathf.Max(room.GetVerticalStart(), nextRoom.GetVerticalStart()); - //这种情况下y轴有重叠 - if (overlapY >= 6) - { - //找到重叠区域 - var rangeList = FindPassage(room, nextRoom, - room.GetHorizontalStart() < nextRoom.GetHorizontalStart() ? DoorDirection.E : DoorDirection.W); - - while (rangeList.Count > 0) - { - //找到重叠区域 - var range = Utils.RandomChooseAndRemove(rangeList); - var y = Utils.RandomRangeInt(range.X, range.Y); - - if (room.GetHorizontalStart() < nextRoom.GetHorizontalStart()) //room在左, nextRoom在右 - { - roomDoor.Direction = DoorDirection.E; - nextRoomDoor.Direction = DoorDirection.W; - roomDoor.OriginPosition = new Vector2(room.GetHorizontalEnd(), y); - nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart(), y); - } - else //room在右, nextRoom在左 - { - roomDoor.Direction = DoorDirection.W; - nextRoomDoor.Direction = DoorDirection.E; - roomDoor.OriginPosition = new Vector2(room.GetHorizontalStart(), y); - nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalEnd(), y); - } - - //判断门之间的通道是否有物体碰到 - if (!AddCorridorToGridRange(roomDoor, nextRoomDoor)) - { - //此门不能连通 - continue; - } - - //没有撞到物体 - room.Doors.Add(roomDoor); - nextRoom.Doors.Add(nextRoomDoor); - return true; - } - } - - return false; - } - - /// - /// 尝试寻找包含拐角的两个房间的连通的门, 返回是否找到 - /// - private bool TryConnectCrossDoor(RoomInfo room, RoomDoorInfo roomDoor, RoomInfo nextRoom, RoomDoorInfo nextRoomDoor) - { - //焦点 - Vector2 cross = default; - - if (room.GetHorizontalStart() > nextRoom.GetHorizontalStart()) - { - if (room.GetVerticalStart() > nextRoom.GetVerticalStart()) - { - if (Utils.RandomBoolean()) //↑ //→ - { - if (!TryConnect_NE_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && - !TryConnect_WS_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) - { - return false; - } - } - else //← //↓ - { - if (!TryConnect_WS_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && - !TryConnect_NE_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) - { - return false; - } - } - } - else - { - if (Utils.RandomBoolean()) //↓ //→ - { - if (!TryConnect_SE_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && - !TryConnect_WN_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) - { - return false; - } - } - else //← //↑ - { - if (!TryConnect_WN_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && - !TryConnect_SE_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) - { - return false; - } - } - } - } - else - { - if (room.GetVerticalStart() > nextRoom.GetVerticalStart()) //→ //↓ - { - if (Utils.RandomBoolean()) - { - if (!TryConnect_ES_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && - !TryConnect_NW_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) - { - return false; - } - } - else //↑ //← - { - if (!TryConnect_NW_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && - !TryConnect_ES_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) - { - return false; - } - } - } - else - { - if (Utils.RandomBoolean()) //→ //↑ - { - if (!TryConnect_EN_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && - !TryConnect_SW_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) - { - return false; - } - } - else //↓ //← - { - if (!TryConnect_SW_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross) && - !TryConnect_EN_Door(room, nextRoom, roomDoor, nextRoomDoor, ref cross)) - { - return false; - } - } - } - } - - //判断门之间的通道是否有物体碰到 - if (!AddCorridorToGridRange(roomDoor, nextRoomDoor, cross)) - { - //此门不能连通 - return false; - } - - roomDoor.HasCross = true; - roomDoor.Cross = cross; - nextRoomDoor.HasCross = true; - nextRoomDoor.Cross = cross; - - room.Doors.Add(roomDoor); - nextRoom.Doors.Add(nextRoomDoor); - return true; - } - - private bool FindCrossPassage(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor,ref int offset1, ref int offset2) - { - var room1 = room.RoomSplit.RoomInfo; - var room2 = nextRoom.RoomSplit.RoomInfo; - - Vector2I? temp1 = null; - Vector2I? temp2 = null; - - foreach (var areaInfo1 in room1.DoorAreaInfos) - { - if (areaInfo1.Direction == roomDoor.Direction) - { - FindCrossPassage_Area(areaInfo1, room, nextRoom, ref temp1); - } - } - - foreach (var areaInfo2 in room2.DoorAreaInfos) - { - if (areaInfo2.Direction == nextRoomDoor.Direction) - { - FindCrossPassage_Area(areaInfo2, nextRoom, room, ref temp2); - } - } - - if (temp1 != null && temp2 != null) - { - offset1 = Utils.RandomRangeInt(temp1.Value.X, temp1.Value.Y); - offset2 = Utils.RandomRangeInt(temp2.Value.X, temp2.Value.Y); - return true; - } - - return false; - } - - private void FindCrossPassage_Area(DoorAreaInfo areaInfo, RoomInfo room1, RoomInfo room2, ref Vector2I? areaRange) - { - if (areaInfo.Direction == DoorDirection.N || areaInfo.Direction == DoorDirection.S) //纵向门 - { - var num = room1.GetHorizontalStart(); - var p1 = num + areaInfo.Start / GameConfig.TileCellSize; - var p2 = num + areaInfo.End / GameConfig.TileCellSize; - - if (room1.Position.X > room2.Position.X) - { - var range = CalcOverlapRange(room2.GetHorizontalEnd(), - room1.GetHorizontalEnd(), p1, p2); - //交集范围够生成门 - if (range.Y - range.X >= GameConfig.CorridorWidth) - { - // var tempRange = new Vector2I(Mathf.Abs(room1.Position.X - (int)range.X), - // Mathf.Abs(room1.Position.X - (int)range.Y) - GameConfig.CorridorWidth); - - var rangeValue = Mathf.Abs(room1.Position.X - (int)range.Y) - GameConfig.CorridorWidth; - if (areaRange == null || rangeValue < areaRange.Value.X) - { - areaRange = new Vector2I(rangeValue, rangeValue); - } - } - } - else - { - var range = CalcOverlapRange(room1.GetHorizontalStart(), - room2.GetHorizontalStart(), p1, p2); - //交集范围够生成门 - if (range.Y - range.X >= GameConfig.CorridorWidth) - { - // var tempRange = new Vector2I(Mathf.Abs(room1.Position.X - (int)range.X), - // Mathf.Abs(room1.Position.X - (int)range.Y) - GameConfig.CorridorWidth); - - var rangeValue = Mathf.Abs(room1.Position.X - (int)range.Y) - GameConfig.CorridorWidth; - if (areaRange == null || rangeValue > areaRange.Value.Y) - { - areaRange = new Vector2I(rangeValue, rangeValue); - } - } - } - } - else //横向门 - { - var num = room1.GetVerticalStart(); - var p1 = num + areaInfo.Start / GameConfig.TileCellSize; - var p2 = num + areaInfo.End / GameConfig.TileCellSize; - - if (room1.Position.Y > room2.Position.Y) - { - var range = CalcOverlapRange(room2.GetVerticalEnd(), - room1.GetVerticalEnd(), p1, p2); - //交集范围够生成门 - if (range.Y - range.X >= GameConfig.CorridorWidth) - { - // var tempRange = new Vector2I(Mathf.Abs(room1.Position.Y - (int)range.X), - // Mathf.Abs(room1.Position.Y - (int)range.Y) - GameConfig.CorridorWidth); - - var rangeValue = Mathf.Abs(room1.Position.Y - (int)range.X); - if (areaRange == null || rangeValue < areaRange.Value.X) - { - areaRange = new Vector2I(rangeValue, rangeValue); - } - } - } - else - { - var range = CalcOverlapRange(room1.GetVerticalStart(), - room2.GetVerticalStart(), p1, p2); - //交集范围够生成门 - if (range.Y - range.X >= GameConfig.CorridorWidth) - { - // var tempRange = new Vector2I(Mathf.Abs(room1.Position.Y - (int)range.X), - // Mathf.Abs(room1.Position.Y - (int)range.Y) - GameConfig.CorridorWidth); - - var rangeValue = Mathf.Abs(room1.Position.Y - (int)range.Y) - GameConfig.CorridorWidth; - if (areaRange == null || rangeValue > areaRange.Value.Y) - { - areaRange = new Vector2I(rangeValue, rangeValue); - } - } - } - } - } - - private bool TryConnect_NE_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) - { - var offset1 = 0; - var offset2 = 0; - roomDoor.Direction = DoorDirection.N; //↑ - nextRoomDoor.Direction = DoorDirection.E; //→ - - if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) - { - return false; - } - - roomDoor.OriginPosition = new Vector2(room.GetHorizontalStart() + offset1, room.GetVerticalStart()); - nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalEnd(), - nextRoom.GetVerticalStart() + offset2); - cross = new Vector2(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y); - return true; - } - - private bool TryConnect_WS_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) - { - //ok - var offset1 = 0; - var offset2 = 0; - roomDoor.Direction = DoorDirection.W; //← - nextRoomDoor.Direction = DoorDirection.S; //↓ - - if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) - { - return false; - } - - roomDoor.OriginPosition = new Vector2(room.GetHorizontalStart(), room.GetVerticalStart() + offset1); - nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart() + offset2, nextRoom.GetVerticalEnd()); - cross = new Vector2(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y); - return true; - } - - private bool TryConnect_SE_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) - { - var offset1 = 0; - var offset2 = 0; - roomDoor.Direction = DoorDirection.S; //↓ - nextRoomDoor.Direction = DoorDirection.E; //→ - - if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) - { - return false; - } - - roomDoor.OriginPosition = new Vector2(room.GetHorizontalStart() + offset1, room.GetVerticalEnd()); - nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalEnd(), - nextRoom.GetVerticalStart() + offset2); - cross = new Vector2(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y); - return true; - } - - private bool TryConnect_WN_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) - { - var offset1 = 0; - var offset2 = 0; - roomDoor.Direction = DoorDirection.W; //← - nextRoomDoor.Direction = DoorDirection.N; //↑ - - if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) - { - return false; - } - - roomDoor.OriginPosition = - new Vector2(room.GetHorizontalStart(), room.GetVerticalStart() + offset1); // - nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart() + offset2, - nextRoom.GetVerticalStart()); - cross = new Vector2(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y); - return true; - } - - private bool TryConnect_ES_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) - { - var offset1 = 0; - var offset2 = 0; - roomDoor.Direction = DoorDirection.E; //→ - nextRoomDoor.Direction = DoorDirection.S; //↓ - - if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) - { - return false; - } - - roomDoor.OriginPosition = new Vector2(room.GetHorizontalEnd(), room.GetVerticalStart() + offset1); - nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart() + offset2, - nextRoom.GetVerticalEnd()); - cross = new Vector2(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y); - return true; - } - - private bool TryConnect_NW_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) - { - var offset1 = 0; - var offset2 = 0; - roomDoor.Direction = DoorDirection.N; //↑ - nextRoomDoor.Direction = DoorDirection.W; //← - - if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) - { - return false; - } - - roomDoor.OriginPosition = new Vector2(room.GetHorizontalStart() + offset1, room.GetVerticalStart()); - nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart(), - nextRoom.GetVerticalStart() + offset2); - cross = new Vector2(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y); - return true; - } - - private bool TryConnect_EN_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) - { - var offset1 = 0; - var offset2 = 0; - roomDoor.Direction = DoorDirection.E; //→ - nextRoomDoor.Direction = DoorDirection.N; //↑ - - if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) - { - return false; - } - - roomDoor.OriginPosition = new Vector2(room.GetHorizontalEnd(), - room.GetVerticalStart() + offset1); - nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart() + offset2, nextRoom.GetVerticalStart()); - cross = new Vector2(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y); - return true; - } - - private bool TryConnect_SW_Door(RoomInfo room, RoomInfo nextRoom, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2 cross) - { - var offset1 = 0; - var offset2 = 0; - roomDoor.Direction = DoorDirection.S; //↓ - nextRoomDoor.Direction = DoorDirection.W; //← - - if (!FindCrossPassage(room, nextRoom, roomDoor, nextRoomDoor, ref offset1, ref offset2)) - { - return false; - } - - roomDoor.OriginPosition = new Vector2(room.GetHorizontalStart() + offset1, - room.GetVerticalEnd()); - nextRoomDoor.OriginPosition = new Vector2(nextRoom.GetHorizontalStart(), nextRoom.GetVerticalStart() + offset2); - cross = new Vector2(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y); - return true; - } - - /// - /// 查找房间的连接通道, 函数返回是否找到对应的门, 通过 result 返回 x/y 轴坐标 - /// - /// 第一个房间 - /// 第二个房间 - /// 第一个房间连接方向 - private List FindPassage(RoomInfo room, RoomInfo nextRoom, DoorDirection direction) - { - var room1 = room.RoomSplit.RoomInfo; - var room2 = nextRoom.RoomSplit.RoomInfo; - - //用于存储符合生成条件的区域 - var rangeList = new List(); - - foreach (var doorAreaInfo1 in room1.DoorAreaInfos) - { - if (doorAreaInfo1.Direction == direction) - { - //第二个门的方向 - var direction2 = GetReverseDirection(direction); - - foreach (var doorAreaInfo2 in room2.DoorAreaInfos) - { - if (doorAreaInfo2.Direction == direction2) - { - Vector2 range; - if (direction == DoorDirection.E || direction == DoorDirection.W) //第二个门向← 或者 第二个门向→ - { - range = CalcOverlapRange( - room.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo1.Start, room.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo1.End, - nextRoom.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo2.Start, nextRoom.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo2.End - ); - } - else //第二个门向↑ 或者 第二个门向↓ - { - range = CalcOverlapRange( - room.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo1.Start, room.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo1.End, - nextRoom.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo2.Start, nextRoom.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo2.End - ); - } - //交集范围够生成门 - if (range.Y - range.X >= GameConfig.CorridorWidth * GameConfig.TileCellSize) - { - rangeList.Add(new Vector2I((int)(range.X / 16), (int)(range.Y / 16) - GameConfig.CorridorWidth)); - } - } - } - } - } - - return rangeList; - } - - /// - /// 用于计算重叠区域坐标, 可以理解为一维轴上4个点的中间两个点, 返回的x为起始点, y为结束点 - /// - private Vector2 CalcOverlapRange(float start1, float end1, float start2, float end2) - { - return new Vector2(Mathf.Max(start1, start2), Mathf.Min(end1, end2)); - } - - /// - /// 返回 p1 - p2 是否在 start - end 范围内 - /// - private bool IsInRange(float start, float end, float p1, float p2) - { - return p1 >= start && p2 <= end; - } - - //返回指定方向的反方向 - //0上, 1右, 2下, 3左 - private int GetReverseDirection(int direction) - { - switch (direction) - { - case 0: return 2; - case 1: return 3; - case 2: return 0; - case 3: return 1; - } - - return 2; - } - - //返回参数方向的反方向 - private DoorDirection GetReverseDirection(DoorDirection direction) - { - switch (direction) - { - case DoorDirection.E: - return DoorDirection.W; - case DoorDirection.W: - return DoorDirection.E; - case DoorDirection.S: - return DoorDirection.N; - case DoorDirection.N: - return DoorDirection.S; - } - - return DoorDirection.S; - } - - //将两个门间的过道占用数据存入RoomGrid - private bool AddCorridorToGridRange(RoomDoorInfo door1, RoomDoorInfo door2) - { - var point1 = door1.OriginPosition; - var point2 = door2.OriginPosition; - var pos = new Vector2(Mathf.Min(point1.X, point2.X), Mathf.Min(point1.Y, point2.Y)); - var size = new Vector2( - point1.X == point2.X ? GameConfig.CorridorWidth : Mathf.Abs(point1.X - point2.X), - point1.Y == point2.Y ? GameConfig.CorridorWidth : Mathf.Abs(point1.Y - point2.Y) - ); - - Vector2 collPos; - Vector2 collSize; - if (point1.X == point2.X) //纵向加宽, 防止贴到其它墙 - { - collPos = new Vector2(pos.X - GameConfig.RoomSpace, pos.Y); - collSize = new Vector2(size.X + GameConfig.RoomSpace * 2, size.Y); - } - else //横向加宽, 防止贴到其它墙 - { - collPos = new Vector2(pos.X, pos.Y - GameConfig.RoomSpace); - collSize = new Vector2(size.X, size.Y + GameConfig.RoomSpace * 2); - } - - if (_roomGrid.RectCollision(collPos, collSize)) - { - return false; - } - - _roomGrid.AddRect(pos, size, true); - return true; - } - - //将两个门间的过道占用数据存入RoomGrid, 该重载加入拐角点 - private bool AddCorridorToGridRange(RoomDoorInfo door1, RoomDoorInfo door2, Vector2 cross) - { - var point1 = door1.OriginPosition; - var point2 = door2.OriginPosition; - var pos1 = new Vector2(Mathf.Min(point1.X, cross.X), Mathf.Min(point1.Y, cross.Y)); - var size1 = new Vector2( - point1.X == cross.X ? GameConfig.CorridorWidth : Mathf.Abs(point1.X - cross.X), - point1.Y == cross.Y ? GameConfig.CorridorWidth : Mathf.Abs(point1.Y - cross.Y) - ); - var pos2 = new Vector2(Mathf.Min(point2.X, cross.X), Mathf.Min(point2.Y, cross.Y)); - var size2 = new Vector2( - point2.X == cross.X ? GameConfig.CorridorWidth : Mathf.Abs(point2.X - cross.X), - point2.Y == cross.Y ? GameConfig.CorridorWidth : Mathf.Abs(point2.Y - cross.Y) - ); - - Vector2 collPos1; - Vector2 collSize1; - if (point1.X == cross.X) //纵向加宽, 防止贴到其它墙 - { - collPos1 = new Vector2(pos1.X - GameConfig.RoomSpace, pos1.Y); - collSize1 = new Vector2(size1.X + GameConfig.RoomSpace * 2, size1.Y); - } - else //横向加宽, 防止贴到其它墙 - { - collPos1 = new Vector2(pos1.X, pos1.Y - GameConfig.RoomSpace); - collSize1 = new Vector2(size1.X, size1.Y + GameConfig.RoomSpace * 2); - } - - if (_roomGrid.RectCollision(collPos1, collSize1)) - { - return false; - } - - Vector2 collPos2; - Vector2 collSize2; - if (point2.X == cross.X) //纵向加宽, 防止贴到其它墙 - { - collPos2 = new Vector2(pos2.X - GameConfig.RoomSpace, pos2.Y); - collSize2 = new Vector2(size2.X + GameConfig.RoomSpace * 2, size2.Y); - } - else //横向加宽, 防止贴到其它墙 - { - collPos2 = new Vector2(pos2.X, pos2.Y - GameConfig.RoomSpace); - collSize2 = new Vector2(size2.X, size2.Y + GameConfig.RoomSpace * 2); - } - - if (_roomGrid.RectCollision(collPos2, collSize2)) - { - return false; - } - - _roomGrid.AddRect(pos1, size1, true); - _roomGrid.AddRect(pos2, size2, true); - return true; - } -} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/room/RoomManager.cs b/DungeonShooting_Godot/src/game/room/RoomManager.cs index 02a61d5..f1c4c42 100644 --- a/DungeonShooting_Godot/src/game/room/RoomManager.cs +++ b/DungeonShooting_Godot/src/game/room/RoomManager.cs @@ -41,7 +41,7 @@ private AutoTileConfig _autoTileConfig; private Font _font; - private GenerateDungeon _generateDungeon; + private DungeonGenerator _dungeonGenerator; private int _affiliationIndex = 0; @@ -63,13 +63,13 @@ var nowTicks = DateTime.Now.Ticks; //生成地牢房间 - _generateDungeon = new GenerateDungeon(); - _generateDungeon.Generate(); + _dungeonGenerator = new DungeonGenerator(); + _dungeonGenerator.Generate(); //填充地牢 _autoTileConfig = new AutoTileConfig(); _dungeonTile = new DungeonTile(TileRoot); - _dungeonTile.AutoFillRoomTile(_autoTileConfig, _generateDungeon.StartRoom); + _dungeonTile.AutoFillRoomTile(_autoTileConfig, _dungeonGenerator.StartRoom); //生成寻路网格, 这一步操作只生成过道的导航 _dungeonTile.GenerateNavigationPolygon(DungeonTile.AisleFloorMapLayer); @@ -80,7 +80,7 @@ //门导航区域数据 _roomStaticNavigationList.AddRange(_dungeonTile.GetConnectDoorPolygonData()); //初始化所有房间 - _generateDungeon.EachRoom(InitRoom); + _dungeonGenerator.EachRoom(InitRoom); GD.Print("生成地牢用时: " + (DateTime.Now.Ticks - nowTicks) / 10000 + "毫秒"); diff --git a/DungeonShooting_Godot/src/test/TestDungeonGenerator.cs b/DungeonShooting_Godot/src/test/TestDungeonGenerator.cs new file mode 100644 index 0000000..5fae0a7 --- /dev/null +++ b/DungeonShooting_Godot/src/test/TestDungeonGenerator.cs @@ -0,0 +1,109 @@ + +using Godot; + +/// +/// 测试地牢生成 +/// +public partial class TestDungeonGenerator : Node2D +{ + [Export] public NodePath TileMapPath; + [Export] public NodePath Camera3D; + + private TileMap _tileMap; + private Camera2D _camera; + + private DungeonGenerator _dungeonGenerator; + private Font _font; + + // public override void _Ready() + // { + // _tileMap = GetNode(TileMapPath); + // _camera = GetNode(Camera3D); + // + // _font = ResourceManager.Load(ResourcePath.resource_font_cn_font_36_tres); + // + // _generateDungeon = new GenerateDungeon(); + // _generateDungeon.Generate(); + // + // foreach (var info in _generateDungeon.RoomInfos) + // { + // //临时铺上地砖 + // var id = (int)_tileMap.TileSet.GetTilesIds()[0]; + // for (int i = 0; i < info.Size.X; i++) + // { + // for (int j = 0; j < info.Size.Y; j++) + // { + // _tileMap.SetCell(i + (int)info.Position.X, j + (int)info.Position.Y, id); + // } + // } + // } + // } + // + // public override void _Process(float delta) + // { + // //移动相机位置 + // var dir = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down"); + // _camera.Position += dir * 1000 * delta; + // + // Update(); + // } + // + // public override void _Draw() + // { + // DrawRoomInfo(_generateDungeon.StartRoom); + // + // } + // + // private void DrawRoomInfo(RoomInfo room) + // { + // var cellSize = _tileMap.CellSize; + // var pos1 = (room.Position + room.Size / 2) * cellSize; + // foreach (var nextRoom in room.Next) + // { + // var pos2 = (nextRoom.Position + nextRoom.Size / 2) * cellSize; + // DrawLine(pos1, pos2, Colors.Red); + // DrawRoomInfo(nextRoom); + // } + // + // DrawString(_font, pos1, room.Id.ToString(), Colors.Yellow); + // + // foreach (var roomDoor in room.Doors) + // { + // var originPos = roomDoor.OriginPosition * cellSize; + // switch (roomDoor.Direction) + // { + // case DoorDirection.E: + // DrawLine(originPos, originPos + new Vector2(3, 0) * cellSize, Colors.Yellow); + // DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos + new Vector2(3, 4) * cellSize, + // Colors.Yellow); + // break; + // case DoorDirection.W: + // DrawLine(originPos, originPos - new Vector2(3, 0) * cellSize, Colors.Yellow); + // DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos - new Vector2(3, -4) * cellSize, + // Colors.Yellow); + // break; + // case DoorDirection.S: + // DrawLine(originPos, originPos + new Vector2(0, 3) * cellSize, Colors.Yellow); + // DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos + new Vector2(4, 3) * cellSize, + // Colors.Yellow); + // break; + // case DoorDirection.N: + // DrawLine(originPos, originPos - new Vector2(0, 3) * cellSize, Colors.Yellow); + // DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos - new Vector2(-4, 3) * cellSize, + // Colors.Yellow); + // break; + // } + // + // if (roomDoor.HasCross && roomDoor.RoomInfo.Id < roomDoor.ConnectRoom.Id) + // { + // DrawRect(new Rect2(roomDoor.Cross * cellSize, cellSize * 4), Colors.Yellow); + // } + // } + // + // //绘制地图上被占用的网格 + // // _generateDungeon.RoomGrid.ForEach((x, y, value) => + // // { + // // DrawRect(new Rect2(new Vector2(x, y) * cellSize + new Vector2(6, 6), new Vector2(4, 4)), Colors.Green); + // // }); + // } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs b/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs deleted file mode 100644 index 2412364..0000000 --- a/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs +++ /dev/null @@ -1,109 +0,0 @@ - -using Godot; - -/// -/// 测试地牢生成 -/// -public partial class TestGenerateDungeon : Node2D -{ - [Export] public NodePath TileMapPath; - [Export] public NodePath Camera3D; - - private TileMap _tileMap; - private Camera2D _camera; - - private GenerateDungeon _generateDungeon; - private Font _font; - - // public override void _Ready() - // { - // _tileMap = GetNode(TileMapPath); - // _camera = GetNode(Camera3D); - // - // _font = ResourceManager.Load(ResourcePath.resource_font_cn_font_36_tres); - // - // _generateDungeon = new GenerateDungeon(); - // _generateDungeon.Generate(); - // - // foreach (var info in _generateDungeon.RoomInfos) - // { - // //临时铺上地砖 - // var id = (int)_tileMap.TileSet.GetTilesIds()[0]; - // for (int i = 0; i < info.Size.X; i++) - // { - // for (int j = 0; j < info.Size.Y; j++) - // { - // _tileMap.SetCell(i + (int)info.Position.X, j + (int)info.Position.Y, id); - // } - // } - // } - // } - // - // public override void _Process(float delta) - // { - // //移动相机位置 - // var dir = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down"); - // _camera.Position += dir * 1000 * delta; - // - // Update(); - // } - // - // public override void _Draw() - // { - // DrawRoomInfo(_generateDungeon.StartRoom); - // - // } - // - // private void DrawRoomInfo(RoomInfo room) - // { - // var cellSize = _tileMap.CellSize; - // var pos1 = (room.Position + room.Size / 2) * cellSize; - // foreach (var nextRoom in room.Next) - // { - // var pos2 = (nextRoom.Position + nextRoom.Size / 2) * cellSize; - // DrawLine(pos1, pos2, Colors.Red); - // DrawRoomInfo(nextRoom); - // } - // - // DrawString(_font, pos1, room.Id.ToString(), Colors.Yellow); - // - // foreach (var roomDoor in room.Doors) - // { - // var originPos = roomDoor.OriginPosition * cellSize; - // switch (roomDoor.Direction) - // { - // case DoorDirection.E: - // DrawLine(originPos, originPos + new Vector2(3, 0) * cellSize, Colors.Yellow); - // DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos + new Vector2(3, 4) * cellSize, - // Colors.Yellow); - // break; - // case DoorDirection.W: - // DrawLine(originPos, originPos - new Vector2(3, 0) * cellSize, Colors.Yellow); - // DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos - new Vector2(3, -4) * cellSize, - // Colors.Yellow); - // break; - // case DoorDirection.S: - // DrawLine(originPos, originPos + new Vector2(0, 3) * cellSize, Colors.Yellow); - // DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos + new Vector2(4, 3) * cellSize, - // Colors.Yellow); - // break; - // case DoorDirection.N: - // DrawLine(originPos, originPos - new Vector2(0, 3) * cellSize, Colors.Yellow); - // DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos - new Vector2(-4, 3) * cellSize, - // Colors.Yellow); - // break; - // } - // - // if (roomDoor.HasCross && roomDoor.RoomInfo.Id < roomDoor.ConnectRoom.Id) - // { - // DrawRect(new Rect2(roomDoor.Cross * cellSize, cellSize * 4), Colors.Yellow); - // } - // } - // - // //绘制地图上被占用的网格 - // // _generateDungeon.RoomGrid.ForEach((x, y, value) => - // // { - // // DrawRect(new Rect2(new Vector2(x, y) * cellSize + new Vector2(6, 6), new Vector2(4, 4)), Colors.Green); - // // }); - // } -} \ No newline at end of file