diff --git a/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs b/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs
index db9bf8f..989983e 100644
--- a/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs
+++ b/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs
@@ -17,6 +17,16 @@
/// 起始房间
///
public RoomInfo StartRoom { get; private set; }
+
+ ///
+ /// 结束房间
+ ///
+ public RoomInfo EndRoom { get; private set; }
+
+ ///
+ /// boss房间
+ ///
+ public List BossRoom { get; } = new List();
//用于标记地图上的坐标是否被占用
private Grid _roomGrid { get; } = new Grid();
@@ -58,7 +68,8 @@
private int _failCount = 0;
//最大尝试次数
- private int _maxTryCount = 15;
+ private int _maxTryCount = 10;
+ private int _currMaxLayer = 0;
//地牢配置
private DungeonConfig _config;
@@ -70,8 +81,6 @@
private enum GenerateRoomErrorCode
{
NoError,
- //房间已满
- RoomFull,
//超出区域
OutArea,
//没有合适的位置
@@ -146,47 +155,114 @@
public void Generate()
{
if (StartRoom != null) return;
-
- //计算下一个房间类型
+
CalcNextRoomType(null);
- //第一个房间
- GenerateRoom(null, GetNextRoomType(), out var startRoom);
- StartRoom = startRoom;
-
//用于排除上一级房间
var excludePrevRoom = new List();
+ //上一个房间
+ RoomInfo prevRoom = null;
+ var chainTryCount = 0;
+ var chainMaxTryCount = 3;
+
//如果房间数量不够, 就一直生成
- while (_count < _config.RoomCount)
+ while (_count < _config.RoomCount || EndRoom == null)
{
var nextRoomType = GetNextRoomType();
- RoomInfo room;
- if (nextRoomType == DungeonRoomType.Boss)
+
+ //上一个房间
+ RoomInfo tempPrevRoom;
+ if (nextRoomType == DungeonRoomType.Inlet)
{
- room = FindMaxLayerRoom(excludePrevRoom);
+ tempPrevRoom = null;
+ }
+ else if (nextRoomType == DungeonRoomType.Boss)
+ {
+ tempPrevRoom = FindMaxLayerRoom(excludePrevRoom);
+ }
+ else if (nextRoomType == DungeonRoomType.Outlet)
+ {
+ tempPrevRoom = prevRoom;
+ }
+ else if (nextRoomType == DungeonRoomType.Battle)
+ {
+ if (chainTryCount < chainMaxTryCount)
+ {
+ if (prevRoom != null && prevRoom.Layer > 6) //层数太高, 下一个房间生成在低层级
+ {
+ tempPrevRoom = RoundRoomLessThanLayer(3);
+ }
+ else
+ {
+ tempPrevRoom = prevRoom;
+ }
+ }
+ else
+ {
+ tempPrevRoom = Utils.RandomChoose(RoomInfos);
+ }
}
else
{
- room = Utils.RandomChoose(RoomInfos);
+ tempPrevRoom = Utils.RandomChoose(RoomInfos);
}
- var errorCode = GenerateRoom(room, nextRoomType, out var nextRoom);
- if (errorCode == GenerateRoomErrorCode.NoError)
+
+ //生成下一个房间
+ var errorCode = GenerateRoom(tempPrevRoom, nextRoomType, out var nextRoom);
+ if (errorCode == GenerateRoomErrorCode.NoError) //生成成功
{
_failCount = 0;
- room.Next.Add(nextRoom);
- excludePrevRoom.Clear();
+ RoomInfos.Add(nextRoom);
+ if (nextRoomType == DungeonRoomType.Inlet)
+ {
+ StartRoom = nextRoom;
+ }
+ else if (nextRoomType == DungeonRoomType.Boss) //boss房间
+ {
+ BossRoom.Add(nextRoom);
+ excludePrevRoom.Clear();
+ }
+ else if (nextRoomType == DungeonRoomType.Outlet)
+ {
+ EndRoom = nextRoom;
+ }
+ else if (nextRoomType == DungeonRoomType.Battle)
+ {
+ chainTryCount = 0;
+ chainMaxTryCount = Utils.RandomRangeInt(1, 3);
+ }
+ prevRoom = nextRoom;
+ CalcNextRoomType(prevRoom);
}
- else
+ else //生成失败
{
if (nextRoomType == DungeonRoomType.Boss)
{
- excludePrevRoom.Add(room);
+ //生成boss房间成功
+ excludePrevRoom.Add(tempPrevRoom);
if (excludePrevRoom.Count >= RoomInfos.Count)
{
//全都没找到合适的, 那就再来一遍
excludePrevRoom.Clear();
}
}
+ else if (nextRoomType == DungeonRoomType.Outlet)
+ {
+ //生成结束房间失败, 那么只能回滚boss房间
+ if (prevRoom != null)
+ {
+ var bossPrev = prevRoom.Prev;
+ BossRoom.Remove(prevRoom);
+ RollbackRoom(prevRoom);
+ CalcNextRoomType(bossPrev);
+ prevRoom = null;
+ }
+ }
+ else if (nextRoomType == DungeonRoomType.Battle)
+ {
+ chainTryCount++;
+ }
+
GD.Print("生成第" + (_count + 1) + "个房间失败! 失败原因: " + errorCode);
if (errorCode == GenerateRoomErrorCode.OutArea)
{
@@ -202,16 +278,17 @@
}
_roomGrid.Clear();
+ GD.Print("房间总数: " + RoomInfos.Count);
}
//生成房间
private GenerateRoomErrorCode GenerateRoom(RoomInfo prevRoomInfo, DungeonRoomType roomType, out RoomInfo resultRoom)
{
- if (_count >= _config.RoomCount)
- {
- resultRoom = null;
- return GenerateRoomErrorCode.RoomFull;
- }
+ // if (_count >= _config.RoomCount)
+ // {
+ // resultRoom = null;
+ // return GenerateRoomErrorCode.RoomFull;
+ // }
DungeonRoomSplit roomSplit;
//没有指定房间
@@ -234,16 +311,29 @@
}
var room = new RoomInfo(_id, roomType, roomSplit);
-
+
//房间大小
room.Size = new Vector2I((int)roomSplit.RoomInfo.Size.X, (int)roomSplit.RoomInfo.Size.Y);
if (prevRoomInfo != null) //表示这不是第一个房间, 就得判断当前位置下的房间是否被遮挡
{
room.Layer = prevRoomInfo.Layer + 1;
+ if (_currMaxLayer < room.Layer)
+ {
+ _currMaxLayer = room.Layer;
+ }
//生成的位置可能会和上一个房间对不上, 需要多次尝试
var tryCount = 0; //当前尝试次数
- for (; tryCount < _maxTryCount; tryCount++)
+ var maxTryCount = _maxTryCount; //最大尝试次数
+ if (roomType == DungeonRoomType.Outlet)
+ {
+ maxTryCount *= 3;
+ }
+ else if (roomType == DungeonRoomType.Boss)
+ {
+ maxTryCount *= 2;
+ }
+ for (; tryCount < maxTryCount; tryCount++)
{
var direction = Utils.RandomRangeInt(0, 3);
//房间间隔
@@ -333,45 +423,13 @@
{
_count++;
}
-
- _id++;
-
- RoomInfos.Add(room);
- //计算下一个房间类型
- CalcNextRoomType(room);
- var nextRoomType = GetNextRoomType();
-
- //这条线有一定概率不生成下一个房间
- if (nextRoomType != DungeonRoomType.Boss && Utils.RandomRangeInt(0, 2) != 0)
+ _id++;
+ room.Prev = prevRoomInfo;
+ if (prevRoomInfo != null)
{
- // //下一个房间
- // //0上, 1右, 2下, 3左
- // var dirList = new List(new[] { 0, 1, 2, 3 });
- // if (prevRoomInfo != null)
- // {
- // dirList.Remove(GetReverseDirection(direction));
- // }
- var num = Utils.RandomRangeInt(1, 4);
- for (var i = 0; i < num; i++)
- {
- nextRoomType = GetNextRoomType();
- if (nextRoomType == DungeonRoomType.Boss) //这里不处理boss房间, 交给外层处理
- {
- break;
- }
-
- GenerateRoom(room, nextRoomType, out var nextRoom);
- if (nextRoom == null)
- {
- break;
- }
-
- nextRoom.Prev = room;
- room.Next.Add(nextRoom);
- }
+ prevRoomInfo.Next.Add(room);
}
-
resultRoom = room;
return GenerateRoomErrorCode.NoError;
}
@@ -393,6 +451,10 @@
{
_nextRoomType = DungeonRoomType.Boss;
}
+ else if (_count >= _config.RoomCount) //结束房间
+ {
+ _nextRoomType = DungeonRoomType.Outlet;
+ }
else if (prev.RoomType == DungeonRoomType.Boss) //生成结束房间
{
_nextRoomType = DungeonRoomType.Outlet;
@@ -436,6 +498,8 @@
var connectDoor = roomInfoDoor.ConnectDoor;
connectDoor.RoomInfo.Doors.Remove(connectDoor);
}
+
+ RoomInfos.Remove(roomInfo);
roomInfo.Destroy();
if (IsParticipateCounting(roomInfo))
@@ -451,7 +515,6 @@
/// 寻找层级最高的房间
///
/// 排除的房间
- ///
private RoomInfo FindMaxLayerRoom(List exclude)
{
RoomInfo temp = null;
@@ -468,6 +531,23 @@
return temp;
}
+
+ ///
+ /// 随机抽取层级小于 layer 的房间
+ ///
+ private RoomInfo RoundRoomLessThanLayer(int layer)
+ {
+ var list = new List();
+ foreach (var roomInfo in RoomInfos)
+ {
+ if (roomInfo.Layer < layer)
+ {
+ list.Add(roomInfo);
+ }
+ }
+
+ return Utils.RandomChoose(list);
+ }
///
/// 找两个房间的门