diff --git a/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs b/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs
index a34f740..dd6f6df 100644
--- a/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs
+++ b/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs
@@ -8,6 +8,11 @@
public class GenerateDungeon
{
///
+ /// 过道宽度
+ ///
+ public const int CorridorWidth = 4;
+
+ ///
/// 所有生成的房间, 调用过 Generate() 函数才能获取到值
///
public List RoomInfos { get; } = new List();
@@ -22,11 +27,6 @@
///
private int _maxCount = 15;
- ///
- /// 过道宽度
- ///
- private int _corridorWidth = 4;
-
//用于标记地图上的坐标是否被占用
private Grid _roomGrid { get; } = new Grid();
@@ -36,8 +36,8 @@
//宽高
private int _roomMinWidth = 15;
private int _roomMaxWidth = 35;
- private int _roomMinHeight = 10;
- private int _roomMaxHeight = 25;
+ private int _roomMinHeight = 15;
+ private int _roomMaxHeight = 30;
//间隔
private int _roomMinInterval = 6;
@@ -51,6 +51,28 @@
private float _roomVerticalMinDispersion = 0.7f;
private float _roomVerticalMaxDispersion = 1.1f;
+ //区域限制
+ private bool _enableLimitRange = true;
+ private int _rangeX = 110;
+ private int _rangeY = 110;
+
+ //找房间失败次数, 过大则会关闭区域限制
+ private int _maxFailCount = 10;
+ private int _failCount = 0;
+
+ private enum GenerateRoomErrorCode
+ {
+ NoError,
+ //房间已满
+ RoomFull,
+ //超出区域
+ OutArea,
+ //碰到其他房间或过道
+ HasCollision,
+ //没有合适的门
+ NoProperDoor,
+ }
+
///
/// 生成房间
///
@@ -59,28 +81,45 @@
if (StartRoom != null) return;
//第一个房间
- StartRoom = GenerateRoom(null, 0);
-
+ GenerateRoom(null, 0, out var startRoom);
+ StartRoom = startRoom;
+
//如果房间数量不够, 就一直生成
while (_count < _maxCount)
{
var room = Utils.RandChoose(RoomInfos);
- var nextRoom = GenerateRoom(room, Utils.RandRangeInt(0, 3));
- if (nextRoom != null)
+ var errorCode = GenerateRoom(room, Utils.RandRangeInt(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 RoomInfo GenerateRoom(RoomInfo prevRoomInfo, int direction)
+ private GenerateRoomErrorCode GenerateRoom(RoomInfo prevRoomInfo, int direction, out RoomInfo resultRoom)
{
if (_count >= _maxCount)
{
- return null;
+ resultRoom = null;
+ return GenerateRoomErrorCode.RoomFull;
}
var room = new RoomInfo(_count);
@@ -126,11 +165,22 @@
room.Position = new Vector2(prevRoomInfo.Position.x - room.Size.x - space,
prevRoomInfo.Position.y + offset);
}
+
+ //是否在限制区域内
+ if (_enableLimitRange)
+ {
+ if (room.Position.x < -_rangeX || room.Position.x + room.Size.x > _rangeX || room.Position.y < -_rangeY || room.Position.y + room.Size.y > _rangeY)
+ {
+ resultRoom = null;
+ return GenerateRoomErrorCode.OutArea;
+ }
+ }
//是否碰到其他房间或者过道
if (_roomGrid.RectCollision(room.Position - new Vector2(3, 3), room.Size + new Vector2(6, 6)))
{
- return null;
+ resultRoom = null;
+ return GenerateRoomErrorCode.HasCollision;
}
_roomGrid.AddRect(room.Position, room.Size, true);
@@ -139,7 +189,8 @@
if (!ConnectDoor(prevRoomInfo, room))
{
_roomGrid.RemoveRect(room.Position, room.Size);
- return null;
+ resultRoom = null;
+ return GenerateRoomErrorCode.NoProperDoor;
}
}
@@ -164,7 +215,7 @@
while (dirList.Count > 0)
{
var randDir = Utils.RandChoose(dirList);
- var nextRoom = GenerateRoom(room, randDir);
+ GenerateRoom(room, randDir, out var nextRoom);
if (nextRoom == null)
{
break;
@@ -177,7 +228,8 @@
}
}
- return room;
+ resultRoom = room;
+ return GenerateRoomErrorCode.NoError;
}
///
@@ -203,7 +255,7 @@
//找到重叠区域
var range = CalcOverlapRange(room.Position.x, room.Position.x + room.Size.x,
nextRoom.Position.x, nextRoom.Position.x + nextRoom.Size.x);
- var x = Utils.RandRangeInt((int)range.x + 1, (int)range.y - _corridorWidth - 1);
+ var x = Utils.RandRangeInt((int)range.x + 1, (int)range.y - CorridorWidth - 1);
if (room.Position.y < nextRoom.Position.y) //room在上, nextRoom在下
{
@@ -241,7 +293,7 @@
//找到重叠区域
var range = CalcOverlapRange(room.Position.y, room.Position.y + room.Size.y,
nextRoom.Position.y, nextRoom.Position.y + nextRoom.Size.y);
- var y = Utils.RandRangeInt((int)range.x + 1, (int)range.y - _corridorWidth - 1);
+ var y = Utils.RandRangeInt((int)range.x + 1, (int)range.y - CorridorWidth - 1);
if (room.Position.x < nextRoom.Position.x) //room在左, nextRoom在右
{
@@ -271,9 +323,9 @@
return true;
}
-
- var offset1 = Mathf.Max((int)overlapX + 2, 2);
- var offset2 = Mathf.Max((int)overlapY + 2, 2);
+
+ var offset1 = Mathf.Clamp((int)overlapX + 2, 2, 6);
+ var offset2 = Mathf.Clamp((int)overlapY + 2, 2, 6);
//焦点
Vector2 cross;
@@ -297,7 +349,7 @@
{
roomDoor.Direction = DoorDirection.W; //←
nextRoomDoor.Direction = DoorDirection.S; //↓
-
+
roomDoor.OriginPosition = new Vector2(room.Position.x, room.Position.y + offset2);
nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x + nextRoom.Size.x - offset1 - 6,
nextRoom.Position.y + nextRoom.Size.y);
@@ -423,8 +475,8 @@
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 ? _corridorWidth : Mathf.Abs(point1.x - point2.x),
- point1.y == point2.y ? _corridorWidth : Mathf.Abs(point1.y - point2.y)
+ point1.x == point2.x ? CorridorWidth : Mathf.Abs(point1.x - point2.x),
+ point1.y == point2.y ? CorridorWidth : Mathf.Abs(point1.y - point2.y)
);
Vector2 collPos;
@@ -456,13 +508,13 @@
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 ? _corridorWidth : Mathf.Abs(point1.x - cross.x),
- point1.y == cross.y ? _corridorWidth : Mathf.Abs(point1.y - cross.y)
+ point1.x == cross.x ? CorridorWidth : Mathf.Abs(point1.x - cross.x),
+ point1.y == cross.y ? 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 ? _corridorWidth : Mathf.Abs(point2.x - cross.x),
- point2.y == cross.y ? _corridorWidth : Mathf.Abs(point2.y - cross.y)
+ point2.x == cross.x ? CorridorWidth : Mathf.Abs(point2.x - cross.x),
+ point2.y == cross.y ? CorridorWidth : Mathf.Abs(point2.y - cross.y)
);
Vector2 collPos1;
diff --git a/DungeonShooting_Godot/src/game/role/Player.cs b/DungeonShooting_Godot/src/game/role/Player.cs
index e96e5ec..e0b2826 100644
--- a/DungeonShooting_Godot/src/game/role/Player.cs
+++ b/DungeonShooting_Godot/src/game/role/Player.cs
@@ -48,7 +48,7 @@
MaxShield = 30;
Shield = 30;
- MoveSpeed = 300;
+ //MoveSpeed = 800;
}
protected override void Process(float delta)
diff --git a/DungeonShooting_Godot/src/game/room/DungeonTileManager.cs b/DungeonShooting_Godot/src/game/room/DungeonTileManager.cs
index 2f3d2a4..427f2e6 100644
--- a/DungeonShooting_Godot/src/game/room/DungeonTileManager.cs
+++ b/DungeonShooting_Godot/src/game/room/DungeonTileManager.cs
@@ -1,4 +1,5 @@
+using System;
using Godot;
public static class DungeonTileManager
@@ -9,6 +10,7 @@
{
AutoFillRoomTile(floor, middle, top, info);
}
+
//铺房间
FillRect(floor, 0, roomInfo.Position, roomInfo.Size);
//铺过道
@@ -16,8 +18,11 @@
{
if (doorInfo.ConnectRoom.Id < roomInfo.Id)
{
+ //普通的直线连接
if (!doorInfo.HasCross)
{
+ //方向, 0横向, 1纵向
+ int dir = 0;
var rect = Utils.CalcRect(
doorInfo.OriginPosition.x,
doorInfo.OriginPosition.y,
@@ -26,14 +31,113 @@
);
if (doorInfo.Direction == DoorDirection.N || doorInfo.Direction == DoorDirection.S)
{
- rect.Size = new Vector2(4, rect.Size.y);
+ rect.Size = new Vector2(GenerateDungeon.CorridorWidth, rect.Size.y);
+ dir = 1;
}
else
{
- rect.Size = new Vector2(rect.Size.x, 4);
+ rect.Size = new Vector2(rect.Size.x, GenerateDungeon.CorridorWidth);
}
+
FillRect(floor, 0, rect.Position, rect.Size);
}
+ else //带交叉点
+ {
+ //方向, 0横向, 1纵向
+ int dir1 = 0;
+ int dir2 = 0;
+
+ Rect2 rect;
+ Rect2 rect2;
+
+ switch (doorInfo.Direction)
+ {
+ case DoorDirection.E: //→
+ rect = new Rect2(
+ doorInfo.OriginPosition.x,
+ doorInfo.OriginPosition.y,
+ doorInfo.Cross.x - doorInfo.OriginPosition.x,
+ GenerateDungeon.CorridorWidth
+ );
+ break;
+ case DoorDirection.W: //←
+ rect = new Rect2(
+ doorInfo.Cross.x + GenerateDungeon.CorridorWidth,
+ doorInfo.Cross.y,
+ doorInfo.OriginPosition.x - (doorInfo.Cross.x + GenerateDungeon.CorridorWidth),
+ GenerateDungeon.CorridorWidth
+ );
+ break;
+ case DoorDirection.S: //↓
+ dir1 = 1;
+ rect = new Rect2(
+ doorInfo.OriginPosition.x,
+ doorInfo.OriginPosition.y,
+ GenerateDungeon.CorridorWidth,
+ doorInfo.Cross.y - doorInfo.OriginPosition.y
+ );
+ break;
+ case DoorDirection.N: //↑
+ dir1 = 1;
+ rect = new Rect2(
+ doorInfo.Cross.x,
+ doorInfo.Cross.y + GenerateDungeon.CorridorWidth,
+ GenerateDungeon.CorridorWidth,
+ doorInfo.OriginPosition.y - doorInfo.Cross.y
+ );
+ break;
+ default:
+ rect = new Rect2();
+ break;
+ }
+
+
+ switch (doorInfo.ConnectDoor.Direction)
+ {
+ case DoorDirection.E: //→
+ rect2 = new Rect2(
+ doorInfo.ConnectDoor.OriginPosition.x,
+ doorInfo.ConnectDoor.OriginPosition.y,
+ doorInfo.Cross.x - doorInfo.ConnectDoor.OriginPosition.x,
+ GenerateDungeon.CorridorWidth
+ );
+ break;
+ case DoorDirection.W: //←
+ rect2 = new Rect2(
+ doorInfo.Cross.x + GenerateDungeon.CorridorWidth,
+ doorInfo.Cross.y,
+ doorInfo.ConnectDoor.OriginPosition.x -
+ (doorInfo.Cross.x + GenerateDungeon.CorridorWidth),
+ GenerateDungeon.CorridorWidth
+ );
+ break;
+ case DoorDirection.S: //↓
+ dir2 = 1;
+ rect2 = new Rect2(
+ doorInfo.ConnectDoor.OriginPosition.x,
+ doorInfo.ConnectDoor.OriginPosition.y,
+ GenerateDungeon.CorridorWidth,
+ doorInfo.Cross.y - doorInfo.ConnectDoor.OriginPosition.y
+ );
+ break;
+ case DoorDirection.N: //↑
+ dir2 = 1;
+ rect2 = new Rect2(
+ doorInfo.Cross.x,
+ doorInfo.Cross.y + GenerateDungeon.CorridorWidth,
+ GenerateDungeon.CorridorWidth,
+ doorInfo.ConnectDoor.OriginPosition.y - doorInfo.Cross.y
+ );
+ break;
+ default:
+ rect2 = new Rect2();
+ break;
+ }
+
+ FillRect(floor, 0, rect.Position, rect.Size);
+ FillRect(floor, 0, rect2.Position, rect2.Size);
+ FillRect(floor, 0, doorInfo.Cross, new Vector2(GenerateDungeon.CorridorWidth, GenerateDungeon.CorridorWidth));
+ }
}
}
}