diff --git a/DungeonShooting_Godot/src/framework/Grid.cs b/DungeonShooting_Godot/src/framework/Grid.cs index 7971d73..f44fa3c 100644 --- a/DungeonShooting_Godot/src/framework/Grid.cs +++ b/DungeonShooting_Godot/src/framework/Grid.cs @@ -1,4 +1,5 @@  +using System; using System.Collections.Generic; using System.Linq; using Godot; @@ -8,7 +9,7 @@ /// public class Grid { - private Dictionary> _map = new Dictionary>(); + private readonly Dictionary> _map = new Dictionary>(); public bool Contains(int x, int y) { @@ -89,4 +90,15 @@ } return false; } + + public void ForEach(Action cb) + { + foreach (var pair1 in _map) + { + foreach (var pair2 in pair1.Value) + { + cb(pair1.Key, pair2.Key, pair2.Value); + } + } + } } diff --git a/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs b/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs index b541bb3..19ac224 100644 --- a/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs +++ b/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs @@ -11,11 +11,20 @@ public RoomInfo StartRoom; - private Grid _roomGrid = new Grid(); + public readonly Grid RoomGrid = new Grid(); + private List _roomInfos = new List(); + private int _count = 0; + + //房间数量 private int _maxCount = 15; + /// + /// 过道宽度 + /// + public const int CorridorWidth = 4; + public GenerateDungeon(TileMap tileMap) { TileMap = tileMap; @@ -23,8 +32,10 @@ public void Generate() { + //第一个房间 StartRoom = GenerateRoom(null, 0); + //如果房间数量不够, 就一直生成 while (_count < _maxCount) { var room = Utils.RandChoose(_roomInfos); @@ -32,7 +43,7 @@ if (nextRoom != null) { room.Next.Add(nextRoom); - + //找门 FindDoor(room, nextRoom); } @@ -52,12 +63,14 @@ } } + //生成房间 private RoomInfo GenerateRoom(RoomInfo prevRoomInfo, int direction) { if (_count >= _maxCount) { return null; } + var room = new RoomInfo(_count); room.Size = new Vector2(Utils.RandRangeInt(25, 60), Utils.RandRangeInt(25, 45)); room.Position = Vector2.Zero; @@ -76,6 +89,7 @@ { offset = Utils.RandRangeInt(-(int)(prevRoomInfo.Size.x * 0.7f), (int)(prevRoomInfo.Size.x * 1.5f)); } + //计算房间位置 if (direction == 0) //上 { @@ -84,20 +98,22 @@ } else if (direction == 1) //右 { - room.Position = new Vector2(prevRoomInfo.Position.x + prevRoomInfo.Size.y + space, prevRoomInfo.Position.y + offset); + room.Position = new Vector2(prevRoomInfo.Position.x + prevRoomInfo.Size.y + space, + prevRoomInfo.Position.y + offset); } else if (direction == 2) //下 { - room.Position = new Vector2(prevRoomInfo.Position.x + offset, prevRoomInfo.Position.y + prevRoomInfo.Size.y + space); + room.Position = new Vector2(prevRoomInfo.Position.x + offset, + prevRoomInfo.Position.y + prevRoomInfo.Size.y + space); } else if (direction == 3) //左 { room.Position = new Vector2(prevRoomInfo.Position.x - room.Size.x - space, prevRoomInfo.Position.y + offset); } - - //是否碰到其他房间 - if (_roomGrid.RectCollision(room.Position - new Vector2(3, 3), room.Size + new Vector2(6, 6))) + + //是否碰到其他房间或者过道 + if (RoomGrid.RectCollision(room.Position - new Vector2(3, 3), room.Size + new Vector2(6, 6))) { return null; } @@ -105,16 +121,17 @@ _count++; _roomInfos.Add(room); - _roomGrid.AddRect(room.Position, room.Size, true); - + RoomGrid.AddRect(room.Position, room.Size, true); + //下一个房间 //0上, 1右, 2下, 3左 - var dirList = new List(new []{ 0, 1, 2, 3 }); + var dirList = new List(new[] { 0, 1, 2, 3 }); if (prevRoomInfo != null) { dirList.Remove(GetReverseDirection(direction)); } + //这条线有一定概率不生成下一个房间 if (Utils.RandRangeInt(0, 2) != 0) { while (dirList.Count > 0) @@ -130,7 +147,7 @@ room.Next.Add(nextRoom); dirList.Remove(randDir); - + //找门 FindDoor(room, nextRoom); } @@ -149,17 +166,18 @@ var nextRoomDoor = new RoomDoor(); roomDoor.ConnectRoom = nextRoom; nextRoomDoor.ConnectRoom = room; - + var overlapX = Mathf.Min(room.Position.x + room.Size.x, nextRoom.Position.x + nextRoom.Size.x) - - Mathf.Max(room.Position.x, nextRoom.Position.x); - if (overlapX >= 6) //x轴 + Mathf.Max(room.Position.x, nextRoom.Position.x); + //这种情况下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 - 4); + var x = Utils.RandRangeInt((int)range.x, (int)range.y - CorridorWidth); if (room.Position.y < nextRoom.Position.y) //room在上, nextRoom在下 { @@ -167,6 +185,8 @@ 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在上 { @@ -174,24 +194,32 @@ 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); } + //判断门之间的通道是否有物体碰到 + + + //没有撞到物体 room.Doors.Add(roomDoor); nextRoom.Doors.Add(nextRoomDoor); + AddToGridRange(roomDoor.OriginPosition, nextRoomDoor.OriginPosition); return; } var overlapY = Mathf.Min(room.Position.y + room.Size.y, nextRoom.Position.y + nextRoom.Size.y) - - Mathf.Max(room.Position.y, nextRoom.Position.y); - if (overlapY >= 6) //y轴 + Mathf.Max(room.Position.y, nextRoom.Position.y); + //这种情况下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 - 4); + var y = Utils.RandRangeInt((int)range.x, (int)range.y - CorridorWidth); if (room.Position.x < nextRoom.Position.x) //room在左, nextRoom在右 { @@ -199,6 +227,8 @@ 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在左 { @@ -206,10 +236,17 @@ 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); } + //判断门之间的通道是否有物体碰到 + + + //没有撞到物体 room.Doors.Add(roomDoor); nextRoom.Doors.Add(nextRoomDoor); + AddToGridRange(roomDoor.OriginPosition, nextRoomDoor.OriginPosition); return; } @@ -217,11 +254,13 @@ 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); - + GD.Print("----3: " + room.Id + ", " + nextRoom.Id + " --- tempX: " + overlapX + ", tempY: " + overlapY + + ", offset1: " + offset1 + ", offset2: " + offset2); + //焦点 Vector2 focus; + //这种情况下x和y轴都没有重叠, 那么就只能生成拐角通道了 if (room.Position.x > nextRoom.Position.x) { if (room.Position.y > nextRoom.Position.y) @@ -264,7 +303,8 @@ roomDoor.Direction = DoorDirection.W; //← nextRoomDoor.Direction = DoorDirection.N; //↑ - roomDoor.OriginPosition = new Vector2(room.Position.x, room.Position.y + room.Size.y - offset2 - 6);// + roomDoor.OriginPosition = + 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); @@ -324,7 +364,6 @@ roomDoor.HasFocus = true; roomDoor.Focus = focus; - //var temp = room.Position - nextRoom.Position; room.Doors.Add(roomDoor); nextRoom.Doors.Add(nextRoomDoor); } @@ -333,7 +372,7 @@ { return new Vector2(Mathf.Max(start1, start2), Mathf.Min(end1, end2)); } - + private int GetReverseDirection(int direction) { switch (direction) @@ -346,4 +385,16 @@ return 2; } + + private void AddToGridRange(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 + ); + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/common/Utils.cs b/DungeonShooting_Godot/src/game/common/Utils.cs index b78bb23..fe899dc 100644 --- a/DungeonShooting_Godot/src/game/common/Utils.cs +++ b/DungeonShooting_Godot/src/game/common/Utils.cs @@ -37,6 +37,9 @@ return Mathf.FloorToInt(GD.Randf() * (max - min + 1) + min); } + /// + /// 随机返回其中一个参数 + /// public static T RandChoose(params T[] list) { if (list.Length == 0) @@ -47,6 +50,9 @@ return list[RandRangeInt(0, list.Length - 1)]; } + /// + /// 随机返回集合中的一个元素 + /// public static T RandChoose(List list) { if (list.Count == 0) diff --git a/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs b/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs index f18cfb3..47ff98f 100644 --- a/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs +++ b/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs @@ -3,12 +3,10 @@ public class TestGenerateDungeon : Node2D { - [Export] - public NodePath TileMapPath; + [Export] public NodePath TileMapPath; - [Export] - public NodePath Camera; - + [Export] public NodePath Camera; + private TileMap _tileMap; private Camera2D _camera; @@ -22,12 +20,12 @@ _camera = GetNode(Camera); _font = ResourceManager.Load(ResourcePath.resource_font_cn_font_36_tres); - + _generateDungeon = new GenerateDungeon(_tileMap); var nowTicks = DateTime.Now.Ticks; _generateDungeon.Generate(); GD.Print("useTime: " + (DateTime.Now.Ticks - nowTicks) / 10000 + "毫秒"); - + } public override void _Process(float delta) @@ -35,13 +33,12 @@ //移动相机位置 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); } @@ -56,8 +53,9 @@ 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; @@ -65,19 +63,23 @@ { 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); + 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); + 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); + 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); + DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos - new Vector2(-4, 3) * cellSize, + Colors.Yellow); break; } @@ -86,5 +88,11 @@ DrawRect(new Rect2(roomDoor.Focus * 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); + // }); } } \ No newline at end of file