diff --git a/DungeonShooting_Godot/src/framework/Grid.cs b/DungeonShooting_Godot/src/framework/Grid.cs
index f44fa3c..ac48e11 100644
--- a/DungeonShooting_Godot/src/framework/Grid.cs
+++ b/DungeonShooting_Godot/src/framework/Grid.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using Godot;
///
@@ -41,6 +40,7 @@
{
return value[y];
}
+
return default;
}
@@ -66,6 +66,26 @@
}
}
+ public void RemoveRect(Vector2 pos, Vector2 size)
+ {
+ var x = (int)pos.x;
+ var y = (int)pos.y;
+ for (var i = 0; i < size.x; i++)
+ {
+ for (var j = 0; j < size.y; j++)
+ {
+ if (_map.TryGetValue(x + i, out var value))
+ {
+ value.Remove(y + j);
+ if (value.Count == 0)
+ {
+ _map.Remove(x + i);
+ }
+ }
+ }
+ }
+ }
+
public bool RectCollision(Vector2 pos, Vector2 size)
{
var x = (int)pos.x;
@@ -73,10 +93,11 @@
var w = (int)size.x;
var h = (int)size.y;
//先判断四个角
- if (Contains(x, y) || Contains(x + w, y) || Contains(x, y + h) || Contains(x + w, y + h))
+ if (Contains(x, y) || Contains(x + w - 1, y) || Contains(x, y + h - 1) || Contains(x + w - 1, y + h - 1))
{
return true;
}
+
//逐个点判断
for (int i = 1; i < w; i++)
{
@@ -88,6 +109,7 @@
}
}
}
+
return false;
}
diff --git a/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs b/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs
index 19ac224..4bda25a 100644
--- a/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs
+++ b/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs
@@ -17,13 +17,35 @@
private int _count = 0;
- //房间数量
+ ///
+ /// 生成的房间数量
+ ///
private int _maxCount = 15;
///
/// 过道宽度
///
- public const int CorridorWidth = 4;
+ private int _corridorWidth = 4;
+
+ //宽高
+ private int _roomMinWidth = 20;
+ private int _roomMaxWidth = 45;
+ private int _roomMinHeight = 20;
+
+ private int _roomMaxHeight = 35;
+
+ //间隔
+ private int _roomMinInterval = 6;
+ private int _roomMaxInterval = 10;
+
+ //房间横轴分散程度
+ private float _roomHorizontalMinDispersion = 0.7f;
+
+ private float _roomHorizontalMaxDispersion = 1.1f;
+
+ //房间纵轴分散程度
+ private float _roomVerticalMinDispersion = 0.7f;
+ private float _roomVerticalMaxDispersion = 1.1f;
public GenerateDungeon(TileMap tileMap)
{
@@ -43,9 +65,6 @@
if (nextRoom != null)
{
room.Next.Add(nextRoom);
-
- //找门
- FindDoor(room, nextRoom);
}
}
@@ -72,22 +91,25 @@
}
var room = new RoomInfo(_count);
- room.Size = new Vector2(Utils.RandRangeInt(25, 60), Utils.RandRangeInt(25, 45));
- room.Position = Vector2.Zero;
+ //房间大小
+ room.Size = new Vector2(Utils.RandRangeInt(_roomMinWidth, _roomMaxWidth),
+ Utils.RandRangeInt(_roomMinHeight, _roomMaxHeight));
if (prevRoomInfo != null) //表示这不是第一个房间, 就得判断当前位置下的房间是否被遮挡
{
//房间间隔
- var space = Utils.RandRangeInt(6, 12);
+ var space = Utils.RandRangeInt(_roomMinInterval, _roomMaxInterval);
//中心偏移
int offset;
if (direction == 0 || direction == 2)
{
- offset = Utils.RandRangeInt(-(int)(prevRoomInfo.Size.y * 0.7f), (int)(prevRoomInfo.Size.y * 1.5f));
+ offset = Utils.RandRangeInt(-(int)(prevRoomInfo.Size.x * _roomVerticalMinDispersion),
+ (int)(prevRoomInfo.Size.x * _roomVerticalMaxDispersion));
}
else
{
- offset = Utils.RandRangeInt(-(int)(prevRoomInfo.Size.x * 0.7f), (int)(prevRoomInfo.Size.x * 1.5f));
+ offset = Utils.RandRangeInt(-(int)(prevRoomInfo.Size.y * _roomHorizontalMinDispersion),
+ (int)(prevRoomInfo.Size.y * _roomHorizontalMaxDispersion));
}
//计算房间位置
@@ -117,11 +139,23 @@
{
return null;
}
+
+ RoomGrid.AddRect(room.Position, room.Size, true);
+
+ //找门, 与上一个房间是否能连通
+ if (!ConnectDoor(prevRoomInfo, room))
+ {
+ RoomGrid.RemoveRect(room.Position, room.Size);
+ return null;
+ }
}
_count++;
_roomInfos.Add(room);
- RoomGrid.AddRect(room.Position, room.Size, true);
+ if (prevRoomInfo == null)
+ {
+ RoomGrid.AddRect(room.Position, room.Size, true);
+ }
//下一个房间
//0上, 1右, 2下, 3左
@@ -147,9 +181,6 @@
room.Next.Add(nextRoom);
dirList.Remove(randDir);
-
- //找门
- FindDoor(room, nextRoom);
}
}
@@ -159,7 +190,7 @@
///
/// 找两个房间的门
///
- private void FindDoor(RoomInfo room, RoomInfo nextRoom)
+ private bool ConnectDoor(RoomInfo room, RoomInfo nextRoom)
{
//门描述
var roomDoor = new RoomDoor();
@@ -172,12 +203,10 @@
//这种情况下x轴有重叠
if (overlapX >= 6)
{
- GD.Print("----1: " + room.Id + ", " + nextRoom.Id);
-
//找到重叠区域
var range = CalcRange(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, (int)range.y - CorridorWidth);
+ var x = Utils.RandRangeInt((int)range.x + 1, (int)range.y - _corridorWidth - 1);
if (room.Position.y < nextRoom.Position.y) //room在上, nextRoom在下
{
@@ -185,8 +214,6 @@
nextRoomDoor.Direction = DoorDirection.N;
roomDoor.OriginPosition = new Vector2(x, room.Position.y + room.Size.y);
nextRoomDoor.OriginPosition = new Vector2(x, nextRoom.Position.y);
-
- //RoomGrid.AddRect(roomDoor.OriginPosition, new Vector2(4, nextRoomDoor.OriginPosition.y - roomDoor.OriginPosition.y), true);
}
else //room在下, nextRoom在上
{
@@ -194,19 +221,19 @@
nextRoomDoor.Direction = DoorDirection.S;
roomDoor.OriginPosition = new Vector2(x, room.Position.y);
nextRoomDoor.OriginPosition = new Vector2(x, nextRoom.Position.y + nextRoom.Size.y);
-
- //RoomGrid.AddRect(nextRoomDoor.OriginPosition, new Vector2(4, roomDoor.OriginPosition.y - nextRoomDoor.OriginPosition.y), true);
}
//判断门之间的通道是否有物体碰到
-
+ if (!AddCorridorToGridRange(roomDoor.OriginPosition, nextRoomDoor.OriginPosition))
+ {
+ //此门不能连通
+ return false;
+ }
//没有撞到物体
room.Doors.Add(roomDoor);
nextRoom.Doors.Add(nextRoomDoor);
- AddToGridRange(roomDoor.OriginPosition, nextRoomDoor.OriginPosition);
-
- return;
+ return true;
}
var overlapY = Mathf.Min(room.Position.y + room.Size.y, nextRoom.Position.y + nextRoom.Size.y) -
@@ -214,12 +241,10 @@
//这种情况下y轴有重叠
if (overlapY >= 6)
{
- GD.Print("----2: " + room.Id + ", " + nextRoom.Id);
-
//找到重叠区域
var range = CalcRange(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, (int)range.y - CorridorWidth);
+ var y = Utils.RandRangeInt((int)range.x + 1, (int)range.y - _corridorWidth - 1);
if (room.Position.x < nextRoom.Position.x) //room在左, nextRoom在右
{
@@ -227,8 +252,6 @@
nextRoomDoor.Direction = DoorDirection.W;
roomDoor.OriginPosition = new Vector2(room.Position.x + room.Size.x, y);
nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x, y);
-
- //RoomGrid.AddRect(roomDoor.OriginPosition, new Vector2(nextRoomDoor.OriginPosition.x - roomDoor.OriginPosition.x, 4), true);
}
else //room在右, nextRoom在左
{
@@ -236,29 +259,27 @@
nextRoomDoor.Direction = DoorDirection.E;
roomDoor.OriginPosition = new Vector2(room.Position.x, y);
nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x + nextRoom.Size.x, y);
-
- //RoomGrid.AddRect(nextRoomDoor.OriginPosition, new Vector2(roomDoor.OriginPosition.x - nextRoomDoor.OriginPosition.x, 4), true);
}
//判断门之间的通道是否有物体碰到
-
+ if (!AddCorridorToGridRange(roomDoor.OriginPosition, nextRoomDoor.OriginPosition))
+ {
+ //此门不能连通
+ return false;
+ }
//没有撞到物体
room.Doors.Add(roomDoor);
nextRoom.Doors.Add(nextRoomDoor);
- AddToGridRange(roomDoor.OriginPosition, nextRoomDoor.OriginPosition);
-
- return;
+ return true;
}
var offset1 = Mathf.Max((int)overlapX + 2, 2);
var offset2 = Mathf.Max((int)overlapY + 2, 2);
- GD.Print("----3: " + room.Id + ", " + nextRoom.Id + " --- tempX: " + overlapX + ", tempY: " + overlapY +
- ", offset1: " + offset1 + ", offset2: " + offset2);
//焦点
- Vector2 focus;
+ Vector2 cross;
//这种情况下x和y轴都没有重叠, 那么就只能生成拐角通道了
if (room.Position.x > nextRoom.Position.x)
@@ -273,7 +294,7 @@
roomDoor.OriginPosition = new Vector2(room.Position.x + offset1, room.Position.y);
nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x + nextRoom.Size.x,
nextRoom.Position.y + nextRoom.Size.y - offset2 - 6);
- focus = new Vector2(roomDoor.OriginPosition.x, nextRoomDoor.OriginPosition.y);
+ cross = new Vector2(roomDoor.OriginPosition.x, nextRoomDoor.OriginPosition.y);
}
else
{
@@ -283,7 +304,7 @@
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);
- focus = new Vector2(nextRoomDoor.OriginPosition.x, roomDoor.OriginPosition.y);
+ cross = new Vector2(nextRoomDoor.OriginPosition.x, roomDoor.OriginPosition.y);
}
}
else
@@ -296,7 +317,7 @@
roomDoor.OriginPosition = new Vector2(room.Position.x + offset1, room.Position.y + room.Size.y);
nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x + nextRoom.Size.x,
nextRoom.Position.y + offset2);
- focus = new Vector2(roomDoor.OriginPosition.x, nextRoomDoor.OriginPosition.y);
+ cross = new Vector2(roomDoor.OriginPosition.x, nextRoomDoor.OriginPosition.y);
}
else
{
@@ -307,7 +328,7 @@
new Vector2(room.Position.x, room.Position.y + room.Size.y - offset2 - 6); //
nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x + nextRoom.Size.x - offset2 - 6,
nextRoom.Position.y);
- focus = new Vector2(nextRoomDoor.OriginPosition.x, roomDoor.OriginPosition.y);
+ cross = new Vector2(nextRoomDoor.OriginPosition.x, roomDoor.OriginPosition.y);
}
}
}
@@ -323,7 +344,7 @@
roomDoor.OriginPosition = new Vector2(room.Position.x + room.Size.x, room.Position.y + offset2);
nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x + offset1,
nextRoom.Position.y + nextRoom.Size.y);
- focus = new Vector2(nextRoomDoor.OriginPosition.x, roomDoor.OriginPosition.y);
+ cross = new Vector2(nextRoomDoor.OriginPosition.x, roomDoor.OriginPosition.y);
}
else
{
@@ -333,7 +354,7 @@
roomDoor.OriginPosition = new Vector2(room.Position.x + room.Size.x - offset1 - 6, room.Position.y);
nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x,
nextRoom.Position.y + nextRoom.Size.y - offset2 - 6);
- focus = new Vector2(roomDoor.OriginPosition.x, nextRoomDoor.OriginPosition.y);
+ cross = new Vector2(roomDoor.OriginPosition.x, nextRoomDoor.OriginPosition.y);
}
}
else
@@ -346,7 +367,7 @@
roomDoor.OriginPosition = new Vector2(room.Position.x + room.Size.x,
room.Position.y + room.Size.y - offset2 - 6);
nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x + offset1, nextRoom.Position.y);
- focus = new Vector2(nextRoomDoor.OriginPosition.x, roomDoor.OriginPosition.y);
+ cross = new Vector2(nextRoomDoor.OriginPosition.x, roomDoor.OriginPosition.y);
}
else
{
@@ -356,16 +377,24 @@
roomDoor.OriginPosition = new Vector2(room.Position.x + room.Size.x - offset1 - 6,
room.Position.y + room.Size.y);
nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x, nextRoom.Position.y + offset2);
- focus = new Vector2(roomDoor.OriginPosition.x, nextRoomDoor.OriginPosition.y);
+ cross = new Vector2(roomDoor.OriginPosition.x, nextRoomDoor.OriginPosition.y);
}
}
}
- roomDoor.HasFocus = true;
- roomDoor.Focus = focus;
+ //判断门之间的通道是否有物体碰到
+ if (!AddCorridorToGridRange(roomDoor.OriginPosition, nextRoomDoor.OriginPosition, cross))
+ {
+ //此门不能连通
+ return false;
+ }
+
+ roomDoor.HasCross = true;
+ roomDoor.Cross = cross;
room.Doors.Add(roomDoor);
nextRoom.Doors.Add(nextRoomDoor);
+ return true;
}
private Vector2 CalcRange(float start1, float end1, float start2, float end2)
@@ -386,15 +415,41 @@
return 2;
}
- private void AddToGridRange(Vector2 point1, Vector2 point2)
+ private bool AddCorridorToGridRange(Vector2 point1, Vector2 point2)
{
- RoomGrid.AddRect(
- new Vector2(Mathf.Min(point1.x, point2.x), Mathf.Min(point1.y, point2.y)),
- new Vector2(
- point1.x == point2.x ? CorridorWidth : Mathf.Abs(point1.x - point2.x),
- point1.y == point2.y ? CorridorWidth : Mathf.Abs(point1.y - point2.y)
- ),
- true
+ 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)
);
+ if (RoomGrid.RectCollision(pos, size))
+ {
+ return false;
+ }
+
+ RoomGrid.AddRect(pos, size, true);
+ return true;
+ }
+
+ private bool AddCorridorToGridRange(Vector2 point1, Vector2 point2, Vector2 cross)
+ {
+ 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)
+ );
+ 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)
+ );
+ if (RoomGrid.RectCollision(pos1, size1) || RoomGrid.RectCollision(pos2, size2))
+ {
+ 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/generate/RoomDoor.cs b/DungeonShooting_Godot/src/framework/generate/RoomDoor.cs
index 8c94894..e4ee6ce 100644
--- a/DungeonShooting_Godot/src/framework/generate/RoomDoor.cs
+++ b/DungeonShooting_Godot/src/framework/generate/RoomDoor.cs
@@ -21,7 +21,13 @@
///
public Vector2 OriginPosition;
- public bool HasFocus;
-
- public Vector2 Focus;
+ ///
+ /// 与下一道门是否有交叉点
+ ///
+ public bool HasCross;
+
+ ///
+ /// 与下一道门的交叉点
+ ///
+ public Vector2 Cross;
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs b/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs
index 47ff98f..e637924 100644
--- a/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs
+++ b/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs
@@ -83,16 +83,16 @@
break;
}
- if (roomDoor.HasFocus)
+ if (roomDoor.HasCross)
{
- DrawRect(new Rect2(roomDoor.Focus * cellSize, cellSize * 4), Colors.Yellow);
+ 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.White);
+ // DrawRect(new Rect2(new Vector2(x, y) * cellSize + new Vector2(6, 6), new Vector2(4, 4)), Colors.Green);
// });
}
}
\ No newline at end of file