Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / generate / GenerateDungeon.cs
  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 info = Utils.RandChoose(_roomInfos);
  31. var nextInfo = GenerateRoom(info, Utils.RandRangeInt(0, 3));
  32. if (nextInfo != null)
  33. {
  34. info.Next.Add(nextInfo);
  35. }
  36. }
  37.  
  38. foreach (var info in _roomInfos)
  39. {
  40. //临时铺上地砖
  41. var id = (int)TileMap.TileSet.GetTilesIds()[0];
  42. for (int i = 0; i < info.Size.x; i++)
  43. {
  44. for (int j = 0; j < info.Size.y; j++)
  45. {
  46. TileMap.SetCell(i + (int)info.Position.x, j + (int)info.Position.y, id);
  47. }
  48. }
  49. }
  50. }
  51.  
  52. private RoomInfo GenerateRoom(RoomInfo prevRoomInfo, int direction)
  53. {
  54. if (_count >= _maxCount)
  55. {
  56. return null;
  57. }
  58. var info = new RoomInfo(_count);
  59. info.Size = new Vector2(Utils.RandRangeInt(10, 30), Utils.RandRangeInt(10, 30));
  60. info.Position = Vector2.Zero;
  61. info.Direction = direction;
  62.  
  63. if (prevRoomInfo != null) //表示这不是第一个房间, 就得判断当前位置下的房间是否被遮挡
  64. {
  65. //房间间隔
  66. var space = Utils.RandRangeInt(3, 4);
  67. //中心偏移
  68. int offset;
  69. if (direction == 0 || direction == 2)
  70. {
  71. offset = Utils.RandRangeInt(-(int)prevRoomInfo.Size.y, (int)prevRoomInfo.Size.y);
  72. }
  73. else
  74. {
  75. offset = Utils.RandRangeInt(-(int)prevRoomInfo.Size.x, (int)prevRoomInfo.Size.x);
  76. }
  77. //计算房间位置
  78. if (direction == 0) //上
  79. {
  80. info.Position = new Vector2(prevRoomInfo.Position.x + offset,
  81. prevRoomInfo.Position.y - info.Size.y - space);
  82. }
  83. else if (direction == 1) //右
  84. {
  85. info.Position = new Vector2(prevRoomInfo.Position.x + prevRoomInfo.Size.y + space, prevRoomInfo.Position.y + offset);
  86. }
  87. else if (direction == 2) //下
  88. {
  89. info.Position = new Vector2(prevRoomInfo.Position.x + offset, prevRoomInfo.Position.y + prevRoomInfo.Size.y + space);
  90. }
  91. else if (direction == 3) //左
  92. {
  93. info.Position = new Vector2(prevRoomInfo.Position.x - info.Size.x - space,
  94. prevRoomInfo.Position.y + offset);
  95. }
  96. //是否碰到其他房间
  97. if (_roomGrid.RectCollision(info.Position - new Vector2(1, 1), info.Size + new Vector2(2, 2)))
  98. {
  99. return null;
  100. }
  101. }
  102.  
  103. _count++;
  104. _roomInfos.Add(info);
  105. _roomGrid.AddRect(info.Position, info.Size, true);
  106. //下一个房间
  107. //0上, 1右, 2下, 3左
  108. var dirList = new List<int>(new []{ 0, 1, 2, 3 });
  109. if (prevRoomInfo != null)
  110. {
  111. dirList.Remove(GetReverseDirection(direction));
  112. }
  113.  
  114. if (Utils.RandRangeInt(0, 2) != 0)
  115. {
  116. while (dirList.Count > 0)
  117. {
  118. var randDir = Utils.RandChoose(dirList);
  119. var generateRoom = GenerateRoom(info, randDir);
  120. if (generateRoom == null)
  121. {
  122. break;
  123. }
  124.  
  125. generateRoom.Prev = info;
  126. info.Next.Add(generateRoom);
  127.  
  128. dirList.Remove(randDir);
  129. }
  130. }
  131.  
  132. return info;
  133. }
  134.  
  135. private int GetReverseDirection(int direction)
  136. {
  137. switch (direction)
  138. {
  139. case 0: return 2;
  140. case 1: return 3;
  141. case 2: return 0;
  142. case 3: return 1;
  143. }
  144.  
  145. return 2;
  146. }
  147. }