Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / generate / GenerateDungeon.cs
@小李xl 小李xl on 3 Jan 2023 7 KB 房间连通功能, 开发中...
  1.  
  2. using System.Collections.Generic;
  3. using Godot;
  4.  
  5. /// <summary>
  6. /// 地牢生成器
  7. /// </summary>
  8. public class GenerateDungeon
  9. {
  10. public readonly TileMap TileMap;
  11.  
  12. public RoomInfo StartRoom;
  13.  
  14. private Grid<bool> _roomGrid = new Grid<bool>();
  15. private List<RoomInfo> _roomInfos = new List<RoomInfo>();
  16. private int _count = 0;
  17. private int _maxCount = 15;
  18.  
  19. public GenerateDungeon(TileMap tileMap)
  20. {
  21. TileMap = tileMap;
  22. }
  23.  
  24. public void Generate()
  25. {
  26. StartRoom = GenerateRoom(null, 0);
  27.  
  28. while (_count < _maxCount)
  29. {
  30. var room = Utils.RandChoose(_roomInfos);
  31. var nextRoom = GenerateRoom(room, Utils.RandRangeInt(0, 3));
  32. if (nextRoom != null)
  33. {
  34. room.Next.Add(nextRoom);
  35. //找门
  36. FindDoor(room, nextRoom);
  37. }
  38. }
  39.  
  40. foreach (var info in _roomInfos)
  41. {
  42. //临时铺上地砖
  43. var id = (int)TileMap.TileSet.GetTilesIds()[0];
  44. for (int i = 0; i < info.Size.x; i++)
  45. {
  46. for (int j = 0; j < info.Size.y; j++)
  47. {
  48. TileMap.SetCell(i + (int)info.Position.x, j + (int)info.Position.y, id);
  49. }
  50. }
  51. }
  52. }
  53.  
  54. private RoomInfo GenerateRoom(RoomInfo prevRoomInfo, int direction)
  55. {
  56. if (_count >= _maxCount)
  57. {
  58. return null;
  59. }
  60. var room = new RoomInfo(_count);
  61. room.Size = new Vector2(Utils.RandRangeInt(25, 60), Utils.RandRangeInt(25, 45));
  62. room.Position = Vector2.Zero;
  63.  
  64. if (prevRoomInfo != null) //表示这不是第一个房间, 就得判断当前位置下的房间是否被遮挡
  65. {
  66. //房间间隔
  67. var space = Utils.RandRangeInt(6, 12);
  68. //中心偏移
  69. int offset;
  70. if (direction == 0 || direction == 2)
  71. {
  72. offset = Utils.RandRangeInt(-(int)(prevRoomInfo.Size.y * 0.7f), (int)(prevRoomInfo.Size.y * 0.7f));
  73. }
  74. else
  75. {
  76. offset = Utils.RandRangeInt(-(int)(prevRoomInfo.Size.x * 0.7f), (int)(prevRoomInfo.Size.x * 0.7f));
  77. }
  78. //计算房间位置
  79. if (direction == 0) //上
  80. {
  81. room.Position = new Vector2(prevRoomInfo.Position.x + offset,
  82. prevRoomInfo.Position.y - room.Size.y - space);
  83. }
  84. else if (direction == 1) //右
  85. {
  86. room.Position = new Vector2(prevRoomInfo.Position.x + prevRoomInfo.Size.y + space, prevRoomInfo.Position.y + offset);
  87. }
  88. else if (direction == 2) //下
  89. {
  90. room.Position = new Vector2(prevRoomInfo.Position.x + offset, prevRoomInfo.Position.y + prevRoomInfo.Size.y + space);
  91. }
  92. else if (direction == 3) //左
  93. {
  94. room.Position = new Vector2(prevRoomInfo.Position.x - room.Size.x - space,
  95. prevRoomInfo.Position.y + offset);
  96. }
  97. //是否碰到其他房间
  98. if (_roomGrid.RectCollision(room.Position - new Vector2(2, 2), room.Size + new Vector2(4, 4)))
  99. {
  100. return null;
  101. }
  102. }
  103.  
  104. _count++;
  105. _roomInfos.Add(room);
  106. _roomGrid.AddRect(room.Position, room.Size, true);
  107. //下一个房间
  108. //0上, 1右, 2下, 3左
  109. var dirList = new List<int>(new []{ 0, 1, 2, 3 });
  110. if (prevRoomInfo != null)
  111. {
  112. dirList.Remove(GetReverseDirection(direction));
  113. }
  114.  
  115. if (Utils.RandRangeInt(0, 2) != 0)
  116. {
  117. while (dirList.Count > 0)
  118. {
  119. var randDir = Utils.RandChoose(dirList);
  120. var nextRoom = GenerateRoom(room, randDir);
  121. if (nextRoom == null)
  122. {
  123. break;
  124. }
  125.  
  126. nextRoom.Prev = room;
  127. room.Next.Add(nextRoom);
  128.  
  129. dirList.Remove(randDir);
  130. //找门
  131. FindDoor(room, nextRoom);
  132. }
  133. }
  134.  
  135. return room;
  136. }
  137.  
  138. /// <summary>
  139. /// 找两个房间的门
  140. /// </summary>
  141. private void FindDoor(RoomInfo room, RoomInfo nextRoom)
  142. {
  143. if (Mathf.Min(room.Position.x + room.Size.x, nextRoom.Position.x + nextRoom.Size.x) -
  144. Mathf.Max(room.Position.x, nextRoom.Position.x) >= 6) //x轴
  145. {
  146. GD.Print("----1: " + room.Id + ", " + nextRoom.Id);
  147. //找到重叠区域
  148. var range = CalcRange(room.Position.x, room.Position.x + room.Size.x,
  149. nextRoom.Position.x, nextRoom.Position.x + nextRoom.Size.x);
  150. var x = Utils.RandRangeInt((int)range.x, (int)range.y - 4);
  151.  
  152. //门描述
  153. var roomDoor = new RoomDoor();
  154. var nextRoomDoor = new RoomDoor();
  155. roomDoor.ConnectRoom = nextRoom;
  156. nextRoomDoor.ConnectRoom = room;
  157.  
  158. if (room.Position.y < nextRoom.Position.y) //room在上, nextRoom在下
  159. {
  160. roomDoor.Direction = DoorDirection.S;
  161. nextRoomDoor.Direction = DoorDirection.N;
  162. roomDoor.OriginPosition = new Vector2(x, room.Position.y + room.Size.y);
  163. nextRoomDoor.OriginPosition = new Vector2(x, nextRoom.Position.y);
  164. }
  165. else //room在下, nextRoom在上
  166. {
  167. roomDoor.Direction = DoorDirection.N;
  168. nextRoomDoor.Direction = DoorDirection.S;
  169. roomDoor.OriginPosition = new Vector2(x, room.Position.y);
  170. nextRoomDoor.OriginPosition = new Vector2(x, nextRoom.Position.y + nextRoom.Size.y);
  171. }
  172. room.Doors.Add(roomDoor);
  173. nextRoom.Doors.Add(nextRoomDoor);
  174. }
  175. else if (Mathf.Min(room.Position.y + room.Size.y, nextRoom.Position.y + nextRoom.Size.y) -
  176. Mathf.Max(room.Position.y, nextRoom.Position.y) >= 6) //y轴
  177. {
  178. GD.Print("----2: " + room.Id + ", " + nextRoom.Id);
  179. //找到重叠区域
  180. var range = CalcRange(room.Position.y, room.Position.y + room.Size.y,
  181. nextRoom.Position.y, nextRoom.Position.y + nextRoom.Size.y);
  182. var y = Utils.RandRangeInt((int)range.x, (int)range.y - 4);
  183.  
  184. //门描述
  185. var roomDoor = new RoomDoor();
  186. var nextRoomDoor = new RoomDoor();
  187. roomDoor.ConnectRoom = nextRoom;
  188. nextRoomDoor.ConnectRoom = room;
  189.  
  190. if (room.Position.x < nextRoom.Position.x) //room在左, nextRoom在右
  191. {
  192. roomDoor.Direction = DoorDirection.E;
  193. nextRoomDoor.Direction = DoorDirection.W;
  194. roomDoor.OriginPosition = new Vector2(room.Position.x + room.Size.x, y);
  195. nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x, y);
  196. }
  197. else //room在右, nextRoom在左
  198. {
  199. roomDoor.Direction = DoorDirection.W;
  200. nextRoomDoor.Direction = DoorDirection.E;
  201. roomDoor.OriginPosition = new Vector2(room.Position.x, y);
  202. nextRoomDoor.OriginPosition = new Vector2(nextRoom.Position.x + nextRoom.Size.x, y);
  203. }
  204. room.Doors.Add(roomDoor);
  205. nextRoom.Doors.Add(nextRoomDoor);
  206. }
  207. else
  208. {
  209. GD.Print("----3: " + room.Id + ", " + nextRoom.Id);
  210. }
  211. }
  212.  
  213. private Vector2 CalcRange(float start1, float end1, float start2, float end2)
  214. {
  215. return new Vector2(Mathf.Max(start1, start2), Mathf.Min(end1, end2));
  216. }
  217. private int GetReverseDirection(int direction)
  218. {
  219. switch (direction)
  220. {
  221. case 0: return 2;
  222. case 1: return 3;
  223. case 2: return 0;
  224. case 3: return 1;
  225. }
  226.  
  227. return 2;
  228. }
  229. }