Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / DungeonGenerator.cs
  1.  
  2. using System;
  3. using System.Collections.Generic;
  4. using Godot;
  5.  
  6. /// <summary>
  7. /// 地牢生成器
  8. /// </summary>
  9. public class DungeonGenerator
  10. {
  11. /// <summary>
  12. /// 所有生成的房间, 调用过 Generate() 函数才能获取到值
  13. /// </summary>
  14. public List<RoomInfo> RoomInfos { get; } = new List<RoomInfo>();
  15.  
  16. /// <summary>
  17. /// 起始房间
  18. /// </summary>
  19. public RoomInfo StartRoomInfo { get; private set; }
  20. /// <summary>
  21. /// 结束房间
  22. /// </summary>
  23. public RoomInfo EndRoomInfo { get; private set; }
  24.  
  25. /// <summary>
  26. /// boss房间
  27. /// </summary>
  28. public List<RoomInfo> BossRoom { get; } = new List<RoomInfo>();
  29. /// <summary>
  30. /// 随机数对象
  31. /// </summary>
  32. public SeedRandom Random { get; }
  33.  
  34. //用于标记地图上的坐标是否被占用
  35. private Grid<bool> _roomGrid { get; } = new Grid<bool>();
  36. //当前房间数量
  37. private int _count = 0;
  38. //房间id
  39. private int _id;
  40. //下一个房间类型
  41. private DungeonRoomType _nextRoomType = DungeonRoomType.Battle;
  42. //间隔
  43. private int _roomMinInterval = 5;
  44. private int _roomMaxInterval = 6;
  45.  
  46. //房间横轴分散程度
  47. private float _roomHorizontalMinDispersion = 0f;
  48. private float _roomHorizontalMaxDispersion = 0.5f;
  49.  
  50. //房间纵轴分散程度
  51. private float _roomVerticalMinDispersion = 0f;
  52. private float _roomVerticalMaxDispersion = 0.5f;
  53.  
  54. //区域限制
  55. private bool _enableLimitRange = true;
  56. private int _rangeX = 200;
  57. private int _rangeY = 200;
  58. //找房间失败次数, 过大则会关闭区域限制
  59. private int _maxFailCount = 10;
  60. private int _failCount = 0;
  61.  
  62. //最大尝试次数
  63. private int _maxTryCount = 10;
  64. private int _currMaxLayer = 0;
  65.  
  66. //地牢配置
  67. private DungeonConfig _config;
  68. private DungeonRoomGroup _roomGroup;
  69.  
  70. private enum GenerateRoomErrorCode
  71. {
  72. NoError,
  73. //超出区域
  74. OutArea,
  75. //没有合适的位置
  76. NoSuitableLocation
  77. // //碰到其他房间或过道
  78. // HasCollision,
  79. // //没有合适的门
  80. // NoProperDoor,
  81. }
  82. public DungeonGenerator(DungeonConfig config)
  83. {
  84. _config = config;
  85. _roomGroup = GameApplication.Instance.RoomConfig[config.GroupName];
  86.  
  87. //验证该组是否满足生成地牢的条件
  88. var result = DungeonManager.CheckDungeon(config.GroupName);
  89. if (result.HasError)
  90. {
  91. throw new Exception("当前组'" + config.GroupName + "'" + result.ErrorMessage + ", 不能生成地牢!");
  92. }
  93. Random = new SeedRandom();
  94. GD.Print("创建地牢生成器, 随机种子: " + Random.Seed);
  95. _roomGroup.InitWeight(Random);
  96. }
  97.  
  98. /// <summary>
  99. /// 遍历所有房间
  100. /// </summary>
  101. public void EachRoom(Action<RoomInfo> cb)
  102. {
  103. EachRoom(StartRoomInfo, cb);
  104. }
  105.  
  106. private void EachRoom(RoomInfo roomInfo, Action<RoomInfo> cb)
  107. {
  108. if (roomInfo == null)
  109. {
  110. return;
  111. }
  112.  
  113. cb(roomInfo);
  114. foreach (var next in roomInfo.Next)
  115. {
  116. EachRoom(next, cb);
  117. }
  118. }
  119.  
  120. /// <summary>
  121. /// 生成房间
  122. /// </summary>
  123. public void Generate()
  124. {
  125. if (StartRoomInfo != null) return;
  126. CalcNextRoomType(null);
  127. //用于排除上一级房间
  128. var excludePrevRoom = new List<RoomInfo>();
  129. //上一个房间
  130. RoomInfo prevRoomInfo = null;
  131. var chainTryCount = 0;
  132. var chainMaxTryCount = 3;
  133.  
  134. //如果房间数量不够, 就一直生成
  135. while (_count < _config.RoomCount || EndRoomInfo == null)
  136. {
  137. var nextRoomType = GetNextRoomType();
  138. //上一个房间
  139. RoomInfo tempPrevRoomInfo;
  140. if (nextRoomType == DungeonRoomType.Inlet)
  141. {
  142. tempPrevRoomInfo = null;
  143. }
  144. else if (nextRoomType == DungeonRoomType.Boss)
  145. {
  146. tempPrevRoomInfo = FindMaxLayerRoom(excludePrevRoom);
  147. }
  148. else if (nextRoomType == DungeonRoomType.Outlet)
  149. {
  150. tempPrevRoomInfo = prevRoomInfo;
  151. }
  152. else if (nextRoomType == DungeonRoomType.Battle)
  153. {
  154. if (chainTryCount < chainMaxTryCount)
  155. {
  156. if (prevRoomInfo != null && prevRoomInfo.Layer > 6) //层数太高, 下一个房间生成在低层级
  157. {
  158. tempPrevRoomInfo = RoundRoomLessThanLayer(3);
  159. }
  160. else
  161. {
  162. tempPrevRoomInfo = prevRoomInfo;
  163. }
  164. }
  165. else
  166. {
  167. tempPrevRoomInfo = Random.RandomChoose(RoomInfos);
  168. }
  169. }
  170. else
  171. {
  172. tempPrevRoomInfo = Random.RandomChoose(RoomInfos);
  173. }
  174. //生成下一个房间
  175. var errorCode = GenerateRoom(tempPrevRoomInfo, nextRoomType, out var nextRoom);
  176. if (errorCode == GenerateRoomErrorCode.NoError) //生成成功
  177. {
  178. _failCount = 0;
  179. RoomInfos.Add(nextRoom);
  180. if (nextRoomType == DungeonRoomType.Inlet)
  181. {
  182. StartRoomInfo = nextRoom;
  183. }
  184. else if (nextRoomType == DungeonRoomType.Boss) //boss房间
  185. {
  186. BossRoom.Add(nextRoom);
  187. excludePrevRoom.Clear();
  188. }
  189. else if (nextRoomType == DungeonRoomType.Outlet)
  190. {
  191. EndRoomInfo = nextRoom;
  192. }
  193. else if (nextRoomType == DungeonRoomType.Battle)
  194. {
  195. chainTryCount = 0;
  196. chainMaxTryCount = Random.RandomRangeInt(1, 3);
  197. }
  198. prevRoomInfo = nextRoom;
  199. CalcNextRoomType(prevRoomInfo);
  200. }
  201. else //生成失败
  202. {
  203. if (nextRoomType == DungeonRoomType.Boss)
  204. {
  205. //生成boss房间成功
  206. excludePrevRoom.Add(tempPrevRoomInfo);
  207. if (excludePrevRoom.Count >= RoomInfos.Count)
  208. {
  209. //全都没找到合适的, 那就再来一遍
  210. excludePrevRoom.Clear();
  211. }
  212. }
  213. else if (nextRoomType == DungeonRoomType.Outlet)
  214. {
  215. //生成结束房间失败, 那么只能回滚boss房间
  216. if (prevRoomInfo != null)
  217. {
  218. var bossPrev = prevRoomInfo.Prev;
  219. BossRoom.Remove(prevRoomInfo);
  220. RollbackRoom(prevRoomInfo);
  221. CalcNextRoomType(bossPrev);
  222. prevRoomInfo = null;
  223. }
  224. }
  225. else if (nextRoomType == DungeonRoomType.Battle)
  226. {
  227. chainTryCount++;
  228. }
  229. GD.Print("生成第" + (_count + 1) + "个房间失败! 失败原因: " + errorCode);
  230. if (errorCode == GenerateRoomErrorCode.OutArea)
  231. {
  232. _failCount++;
  233. GD.Print("超出区域失败次数: " + _failCount);
  234. if (_failCount >= _maxFailCount)
  235. {
  236. _enableLimitRange = false;
  237. GD.Print("生成房间失败次数过多, 关闭区域限制!");
  238. }
  239. }
  240. }
  241. }
  242. _roomGrid.Clear();
  243. GD.Print("房间总数: " + RoomInfos.Count);
  244. }
  245.  
  246. //生成房间
  247. private GenerateRoomErrorCode GenerateRoom(RoomInfo prevRoomInfo, DungeonRoomType roomType, out RoomInfo resultRoomInfo)
  248. {
  249. // if (_count >= _config.RoomCount)
  250. // {
  251. // resultRoom = null;
  252. // return GenerateRoomErrorCode.RoomFull;
  253. // }
  254.  
  255. DungeonRoomSplit roomSplit;
  256. if (_config.HasDesignatedRoom && _config.DesignatedType == roomType) //执行指定了房间
  257. {
  258. roomSplit = Random.RandomChoose(_config.DesignatedRoom);
  259. }
  260. else //没有指定房间
  261. {
  262. //随机选择一个房间
  263. var list = _roomGroup.GetRoomList(roomType);
  264. if (list.Count == 0) //如果没有指定类型的房间, 就生成战斗房间
  265. {
  266. roomSplit = _roomGroup.GetRandomRoom(DungeonRoomType.Battle);
  267. }
  268. else
  269. {
  270. roomSplit = _roomGroup.GetRandomRoom(roomType);
  271. }
  272. }
  273. var room = new RoomInfo(_id, roomType, roomSplit);
  274.  
  275. //房间大小
  276. room.Size = new Vector2I((int)roomSplit.RoomInfo.Size.X, (int)roomSplit.RoomInfo.Size.Y);
  277.  
  278. if (prevRoomInfo != null) //表示这不是第一个房间, 就得判断当前位置下的房间是否被遮挡
  279. {
  280. room.Layer = prevRoomInfo.Layer + 1;
  281. if (_currMaxLayer < room.Layer)
  282. {
  283. _currMaxLayer = room.Layer;
  284. }
  285. //生成的位置可能会和上一个房间对不上, 需要多次尝试
  286. var tryCount = 0; //当前尝试次数
  287. var maxTryCount = _maxTryCount; //最大尝试次数
  288. if (roomType == DungeonRoomType.Outlet)
  289. {
  290. maxTryCount *= 3;
  291. }
  292. else if (roomType == DungeonRoomType.Boss)
  293. {
  294. maxTryCount *= 2;
  295. }
  296. for (; tryCount < maxTryCount; tryCount++)
  297. {
  298. var direction = Random.RandomRangeInt(0, 3);
  299. //房间间隔
  300. var space = Random.RandomRangeInt(_roomMinInterval, _roomMaxInterval);
  301. //中心偏移
  302. int offset;
  303. if (direction == 0 || direction == 2)
  304. {
  305. offset = Random.RandomRangeInt(-(int)(prevRoomInfo.Size.X * _roomVerticalMinDispersion),
  306. (int)(prevRoomInfo.Size.X * _roomVerticalMaxDispersion));
  307. }
  308. else
  309. {
  310. offset = Random.RandomRangeInt(-(int)(prevRoomInfo.Size.Y * _roomHorizontalMinDispersion),
  311. (int)(prevRoomInfo.Size.Y * _roomHorizontalMaxDispersion));
  312. }
  313.  
  314. //计算房间位置
  315. if (direction == 0) //上
  316. {
  317. room.Position = new Vector2I(prevRoomInfo.Position.X + offset,
  318. prevRoomInfo.Position.Y - room.Size.Y - space);
  319. }
  320. else if (direction == 1) //右
  321. {
  322. room.Position = new Vector2I(prevRoomInfo.Position.X + prevRoomInfo.Size.Y + space,
  323. prevRoomInfo.Position.Y + offset);
  324. }
  325. else if (direction == 2) //下
  326. {
  327. room.Position = new Vector2I(prevRoomInfo.Position.X + offset,
  328. prevRoomInfo.Position.Y + prevRoomInfo.Size.Y + space);
  329. }
  330. else if (direction == 3) //左
  331. {
  332. room.Position = new Vector2I(prevRoomInfo.Position.X - room.Size.X - space,
  333. prevRoomInfo.Position.Y + offset);
  334. }
  335.  
  336. //是否在限制区域内
  337. if (_enableLimitRange)
  338. {
  339. if (room.GetHorizontalStart() < -_rangeX || room.GetHorizontalEnd() > _rangeX ||
  340. room.GetVerticalStart() < -_rangeY || room.GetVerticalEnd() > _rangeY)
  341. {
  342. //超出区域, 直接跳出尝试的循环, 返回 null
  343. resultRoomInfo = null;
  344. return GenerateRoomErrorCode.OutArea;
  345. }
  346. }
  347.  
  348. //是否碰到其他房间或者过道
  349. if (_roomGrid.RectCollision(room.Position - new Vector2I(GameConfig.RoomSpace, GameConfig.RoomSpace), room.Size + new Vector2I(GameConfig.RoomSpace * 2, GameConfig.RoomSpace * 2)))
  350. {
  351. //碰到其他墙壁, 再一次尝试
  352. continue;
  353. //return GenerateRoomErrorCode.HasCollision;
  354. }
  355.  
  356. _roomGrid.SetRect(room.Position, room.Size, true);
  357.  
  358. //找门, 与上一个房间是否能连通
  359. if (!ConnectDoor(prevRoomInfo, room))
  360. {
  361. _roomGrid.RemoveRect(room.Position, room.Size);
  362. //房间过道没有连接上, 再一次尝试
  363. continue;
  364. //return GenerateRoomErrorCode.NoProperDoor;
  365. }
  366. break;
  367. }
  368.  
  369. //尝试次数用光了, 还没有找到合适的位置
  370. if (tryCount >= maxTryCount)
  371. {
  372. resultRoomInfo = null;
  373. return GenerateRoomErrorCode.NoSuitableLocation;
  374. }
  375. }
  376. else //第一个房间
  377. {
  378. room.Layer = 0;
  379. _roomGrid.SetRect(room.Position, room.Size, true);
  380. }
  381.  
  382. if (IsParticipateCounting(room))
  383. {
  384. _count++;
  385. }
  386. _id++;
  387. room.Prev = prevRoomInfo;
  388. if (prevRoomInfo != null)
  389. {
  390. prevRoomInfo.Next.Add(room);
  391. }
  392. resultRoomInfo = room;
  393. return GenerateRoomErrorCode.NoError;
  394. }
  395.  
  396. //判断房间是否参与计数
  397. private bool IsParticipateCounting(RoomInfo roomInfo)
  398. {
  399. return roomInfo.RoomType == DungeonRoomType.Battle || roomInfo.RoomType == DungeonRoomType.Boss;
  400. }
  401.  
  402. //计算下一个房间类型
  403. private void CalcNextRoomType(RoomInfo prev)
  404. {
  405. if (prev == null) //生成第一个房间
  406. {
  407. _nextRoomType = DungeonRoomType.Inlet;
  408. }
  409. else if (_count == _config.RoomCount - 1) //最后一个房间是boss房间
  410. {
  411. _nextRoomType = DungeonRoomType.Boss;
  412. }
  413. else if (_count >= _config.RoomCount) //结束房间
  414. {
  415. _nextRoomType = DungeonRoomType.Outlet;
  416. }
  417. else if (prev.RoomType == DungeonRoomType.Boss) //生成结束房间
  418. {
  419. _nextRoomType = DungeonRoomType.Outlet;
  420. }
  421. else
  422. {
  423. _nextRoomType = DungeonRoomType.Battle;
  424. }
  425. }
  426. //获取下一个房间类型
  427. private DungeonRoomType GetNextRoomType()
  428. {
  429. return _nextRoomType;
  430. }
  431.  
  432. //回滚一个房间
  433. private bool RollbackRoom(RoomInfo roomInfo)
  434. {
  435. if (roomInfo.Next.Count > 0)
  436. {
  437. GD.PrintErr("当前房间还有连接的子房间, 不能回滚!");
  438. return false;
  439. }
  440. //退掉占用的房间区域和过道占用区域
  441. _roomGrid.RemoveRect(roomInfo.Position, roomInfo.Size);
  442. foreach (var rect2 in roomInfo.AisleArea)
  443. {
  444. _roomGrid.RemoveRect(rect2.Position, rect2.Size);
  445. }
  446. //roomInfo.Doors[0].
  447. if (roomInfo.Prev != null)
  448. {
  449. roomInfo.Prev.Next.Remove(roomInfo);
  450. }
  451.  
  452. roomInfo.Prev = null;
  453. foreach (var roomInfoDoor in roomInfo.Doors)
  454. {
  455. var connectDoor = roomInfoDoor.ConnectDoor;
  456. connectDoor.RoomInfo.Doors.Remove(connectDoor);
  457. }
  458.  
  459. RoomInfos.Remove(roomInfo);
  460. roomInfo.Destroy();
  461.  
  462. if (IsParticipateCounting(roomInfo))
  463. {
  464. _count--;
  465. }
  466.  
  467. _id--;
  468. return true;
  469. }
  470.  
  471. /// <summary>
  472. /// 寻找层级最高的房间
  473. /// </summary>
  474. /// <param name="exclude">排除的房间</param>
  475. private RoomInfo FindMaxLayerRoom(List<RoomInfo> exclude)
  476. {
  477. RoomInfo temp = null;
  478. foreach (var roomInfo in RoomInfos)
  479. {
  480. if (temp == null || roomInfo.Layer > temp.Layer)
  481. {
  482. if (exclude == null || !exclude.Contains(roomInfo))
  483. {
  484. temp = roomInfo;
  485. }
  486. }
  487. }
  488.  
  489. return temp;
  490. }
  491.  
  492. /// <summary>
  493. /// 随机抽取层级小于 layer 的房间
  494. /// </summary>
  495. private RoomInfo RoundRoomLessThanLayer(int layer)
  496. {
  497. var list = new List<RoomInfo>();
  498. foreach (var roomInfo in RoomInfos)
  499. {
  500. if (roomInfo.Layer < layer)
  501. {
  502. list.Add(roomInfo);
  503. }
  504. }
  505.  
  506. return Random.RandomChoose(list);
  507. }
  508. /// <summary>
  509. /// 找两个房间的门
  510. /// </summary>
  511. private bool ConnectDoor(RoomInfo roomInfo, RoomInfo nextRoomInfo)
  512. {
  513. //门描述
  514. var roomDoor = new RoomDoorInfo();
  515. var nextRoomDoor = new RoomDoorInfo();
  516. roomDoor.RoomInfo = roomInfo;
  517. nextRoomDoor.RoomInfo = nextRoomInfo;
  518. roomDoor.ConnectRoom = nextRoomInfo;
  519. roomDoor.ConnectDoor = nextRoomDoor;
  520. nextRoomDoor.ConnectRoom = roomInfo;
  521. nextRoomDoor.ConnectDoor = roomDoor;
  522.  
  523. //先寻找直通门
  524. if (Random.RandomBoolean())
  525. {
  526. //直行通道, 优先横轴
  527. if (TryConnectHorizontalDoor(roomInfo, roomDoor, nextRoomInfo, nextRoomDoor)
  528. || TryConnectVerticalDoor(roomInfo, roomDoor, nextRoomInfo, nextRoomDoor))
  529. {
  530. return true;
  531. }
  532. }
  533. else
  534. {
  535. //直行通道, 优先纵轴
  536. if (TryConnectVerticalDoor(roomInfo, roomDoor, nextRoomInfo, nextRoomDoor)
  537. || TryConnectHorizontalDoor(roomInfo, roomDoor, nextRoomInfo, nextRoomDoor))
  538. {
  539. return true;
  540. }
  541. }
  542. //包含拐角的通道
  543. return TryConnectCrossDoor(roomInfo, roomDoor, nextRoomInfo, nextRoomDoor);
  544. }
  545.  
  546. /// <summary>
  547. /// 尝试寻找横轴方向上两个房间的连通的门, 只查找直线通道, 返回是否找到
  548. /// </summary>
  549. private bool TryConnectHorizontalDoor(RoomInfo roomInfo, RoomDoorInfo roomDoor, RoomInfo nextRoomInfo, RoomDoorInfo nextRoomDoor)
  550. {
  551. var overlapX = Mathf.Min(roomInfo.GetHorizontalEnd(), nextRoomInfo.GetHorizontalEnd()) -
  552. Mathf.Max(roomInfo.GetHorizontalStart(), nextRoomInfo.GetHorizontalStart());
  553. //这种情况下x轴有重叠
  554. if (overlapX >= 6)
  555. {
  556. //找到重叠区域
  557. var rangeList = FindPassage(roomInfo, nextRoomInfo,
  558. roomInfo.GetVerticalStart() < nextRoomInfo.GetVerticalStart() ? DoorDirection.S : DoorDirection.N);
  559. while (rangeList.Count > 0)
  560. {
  561. //找到重叠区域
  562. var range = Random.RandomChooseAndRemove(rangeList);
  563. var x = Random.RandomRangeInt(range.X, range.Y);
  564. if (roomInfo.GetVerticalStart() < nextRoomInfo.GetVerticalStart()) //room在上, nextRoom在下
  565. {
  566. roomDoor.Direction = DoorDirection.S;
  567. nextRoomDoor.Direction = DoorDirection.N;
  568. roomDoor.OriginPosition = new Vector2I(x, roomInfo.GetVerticalEnd());
  569. nextRoomDoor.OriginPosition = new Vector2I(x, nextRoomInfo.GetVerticalStart());
  570. }
  571. else //room在下, nextRoom在上
  572. {
  573. roomDoor.Direction = DoorDirection.N;
  574. nextRoomDoor.Direction = DoorDirection.S;
  575. roomDoor.OriginPosition = new Vector2I(x, roomInfo.GetVerticalStart());
  576. nextRoomDoor.OriginPosition = new Vector2I(x, nextRoomInfo.GetVerticalEnd());
  577. }
  578.  
  579. //判断门之间的通道是否有物体碰到
  580. if (!AddCorridorToGridRange(roomDoor, nextRoomDoor))
  581. {
  582. //此门不能连通
  583. continue;
  584. }
  585.  
  586. //没有撞到物体
  587. roomInfo.Doors.Add(roomDoor);
  588. nextRoomInfo.Doors.Add(nextRoomDoor);
  589. return true;
  590. }
  591. }
  592. return false;
  593. }
  594.  
  595. /// <summary>
  596. /// 尝试寻找纵轴方向上两个房间的连通的门, 只查找直线通道, 返回是否找到
  597. /// </summary>
  598. private bool TryConnectVerticalDoor(RoomInfo roomInfo, RoomDoorInfo roomDoor, RoomInfo nextRoomInfo, RoomDoorInfo nextRoomDoor)
  599. {
  600. var overlapY = Mathf.Min(roomInfo.GetVerticalEnd(), nextRoomInfo.GetVerticalEnd()) -
  601. Mathf.Max(roomInfo.GetVerticalStart(), nextRoomInfo.GetVerticalStart());
  602. //这种情况下y轴有重叠
  603. if (overlapY >= 6)
  604. {
  605. //找到重叠区域
  606. var rangeList = FindPassage(roomInfo, nextRoomInfo,
  607. roomInfo.GetHorizontalStart() < nextRoomInfo.GetHorizontalStart() ? DoorDirection.E : DoorDirection.W);
  608.  
  609. while (rangeList.Count > 0)
  610. {
  611. //找到重叠区域
  612. var range = Random.RandomChooseAndRemove(rangeList);
  613. var y = Random.RandomRangeInt(range.X, range.Y);
  614. if (roomInfo.GetHorizontalStart() < nextRoomInfo.GetHorizontalStart()) //room在左, nextRoom在右
  615. {
  616. roomDoor.Direction = DoorDirection.E;
  617. nextRoomDoor.Direction = DoorDirection.W;
  618. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalEnd(), y);
  619. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart(), y);
  620. }
  621. else //room在右, nextRoom在左
  622. {
  623. roomDoor.Direction = DoorDirection.W;
  624. nextRoomDoor.Direction = DoorDirection.E;
  625. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalStart(), y);
  626. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalEnd(), y);
  627. }
  628.  
  629. //判断门之间的通道是否有物体碰到
  630. if (!AddCorridorToGridRange(roomDoor, nextRoomDoor))
  631. {
  632. //此门不能连通
  633. continue;
  634. }
  635.  
  636. //没有撞到物体
  637. roomInfo.Doors.Add(roomDoor);
  638. nextRoomInfo.Doors.Add(nextRoomDoor);
  639. return true;
  640. }
  641. }
  642.  
  643. return false;
  644. }
  645.  
  646. /// <summary>
  647. /// 尝试寻找包含拐角的两个房间的连通的门, 返回是否找到
  648. /// </summary>
  649. private bool TryConnectCrossDoor(RoomInfo roomInfo, RoomDoorInfo roomDoor, RoomInfo nextRoomInfo, RoomDoorInfo nextRoomDoor)
  650. {
  651. //焦点
  652. Vector2I cross = default;
  653.  
  654. if (roomInfo.GetHorizontalStart() > nextRoomInfo.GetHorizontalStart())
  655. {
  656. if (roomInfo.GetVerticalStart() > nextRoomInfo.GetVerticalStart())
  657. {
  658. if (Random.RandomBoolean()) //↑ //→
  659. {
  660. if (!TryConnect_NE_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  661. !TryConnect_WS_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  662. {
  663. return false;
  664. }
  665. }
  666. else //← //↓
  667. {
  668. if (!TryConnect_WS_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  669. !TryConnect_NE_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  670. {
  671. return false;
  672. }
  673. }
  674. }
  675. else
  676. {
  677. if (Random.RandomBoolean()) //↓ //→
  678. {
  679. if (!TryConnect_SE_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  680. !TryConnect_WN_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  681. {
  682. return false;
  683. }
  684. }
  685. else //← //↑
  686. {
  687. if (!TryConnect_WN_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  688. !TryConnect_SE_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  689. {
  690. return false;
  691. }
  692. }
  693. }
  694. }
  695. else
  696. {
  697. if (roomInfo.GetVerticalStart() > nextRoomInfo.GetVerticalStart()) //→ //↓
  698. {
  699. if (Random.RandomBoolean())
  700. {
  701. if (!TryConnect_ES_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  702. !TryConnect_NW_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  703. {
  704. return false;
  705. }
  706. }
  707. else //↑ //←
  708. {
  709. if (!TryConnect_NW_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  710. !TryConnect_ES_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  711. {
  712. return false;
  713. }
  714. }
  715. }
  716. else
  717. {
  718. if (Random.RandomBoolean()) //→ //↑
  719. {
  720. if (!TryConnect_EN_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  721. !TryConnect_SW_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  722. {
  723. return false;
  724. }
  725. }
  726. else //↓ //←
  727. {
  728. if (!TryConnect_SW_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  729. !TryConnect_EN_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  730. {
  731. return false;
  732. }
  733. }
  734. }
  735. }
  736.  
  737. //判断门之间的通道是否有物体碰到
  738. if (!AddCorridorToGridRange(roomDoor, nextRoomDoor, cross))
  739. {
  740. //此门不能连通
  741. return false;
  742. }
  743.  
  744. roomDoor.HasCross = true;
  745. roomDoor.Cross = cross;
  746. nextRoomDoor.HasCross = true;
  747. nextRoomDoor.Cross = cross;
  748.  
  749. roomInfo.Doors.Add(roomDoor);
  750. nextRoomInfo.Doors.Add(nextRoomDoor);
  751. return true;
  752. }
  753.  
  754. private bool FindCrossPassage(RoomInfo roomInfo, RoomInfo nextRoomInfo, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor,ref int offset1, ref int offset2)
  755. {
  756. var room1 = roomInfo.RoomSplit.RoomInfo;
  757. var room2 = nextRoomInfo.RoomSplit.RoomInfo;
  758. int? temp1 = null;
  759. int? temp2 = null;
  760.  
  761. foreach (var areaInfo1 in room1.GetCompletionDoorArea())
  762. {
  763. if (areaInfo1.Direction == roomDoor.Direction)
  764. {
  765. FindCrossPassage_Area(areaInfo1, roomInfo, nextRoomInfo, ref temp1);
  766. }
  767. }
  768. if (temp1 == null)
  769. {
  770. return false;
  771. }
  772.  
  773. foreach (var areaInfo2 in room2.GetCompletionDoorArea())
  774. {
  775. if (areaInfo2.Direction == nextRoomDoor.Direction)
  776. {
  777. FindCrossPassage_Area(areaInfo2, nextRoomInfo, roomInfo, ref temp2);
  778. }
  779. }
  780.  
  781. if (temp2 == null)
  782. {
  783. return false;
  784. }
  785. offset1 = temp1.Value;
  786. offset2 = temp2.Value;
  787. return true;
  788. }
  789.  
  790. private void FindCrossPassage_Area(DoorAreaInfo areaInfo, RoomInfo room1, RoomInfo room2, ref int? areaRange)
  791. {
  792. if (areaInfo.Direction == DoorDirection.N || areaInfo.Direction == DoorDirection.S) //纵向门
  793. {
  794. var num = room1.GetHorizontalStart();
  795. var p1 = num + areaInfo.Start / GameConfig.TileCellSize;
  796. var p2 = num + areaInfo.End / GameConfig.TileCellSize;
  797.  
  798. if (room1.Position.X > room2.Position.X)
  799. {
  800. var range = CalcOverlapRange(room2.GetHorizontalEnd() + GameConfig.RoomSpace,
  801. room1.GetHorizontalEnd(), p1, p2);
  802. //交集范围够生成门
  803. if (range.Y - range.X >= GameConfig.CorridorWidth)
  804. {
  805. // var tempRange = new Vector2I(Mathf.Abs(room1.Position.X - (int)range.X),
  806. // Mathf.Abs(room1.Position.X - (int)range.Y) - GameConfig.CorridorWidth);
  807. var rangeValue = Mathf.Abs(room1.Position.X - (int)range.X);
  808.  
  809. if (areaRange == null || rangeValue < areaRange)
  810. {
  811. areaRange = rangeValue;
  812. }
  813. }
  814. }
  815. else
  816. {
  817. var range = CalcOverlapRange(room1.GetHorizontalStart(),
  818. room2.GetHorizontalStart() - + GameConfig.RoomSpace, p1, p2);
  819. //交集范围够生成门
  820. if (range.Y - range.X >= GameConfig.CorridorWidth)
  821. {
  822. // var tempRange = new Vector2I(Mathf.Abs(room1.Position.X - (int)range.X),
  823. // Mathf.Abs(room1.Position.X - (int)range.Y) - GameConfig.CorridorWidth);
  824.  
  825. var rangeValue = Mathf.Abs(room1.Position.X - (int)range.Y) - GameConfig.CorridorWidth;
  826.  
  827. if (areaRange == null || rangeValue > areaRange)
  828. {
  829. areaRange = rangeValue;
  830. }
  831. }
  832. }
  833. }
  834. else //横向门
  835. {
  836. var num = room1.GetVerticalStart();
  837. var p1 = num + areaInfo.Start / GameConfig.TileCellSize;
  838. var p2 = num + areaInfo.End / GameConfig.TileCellSize;
  839.  
  840. if (room1.Position.Y > room2.Position.Y)
  841. {
  842. var range = CalcOverlapRange(room2.GetVerticalEnd() + GameConfig.RoomSpace,
  843. room1.GetVerticalEnd(), p1, p2);
  844. //交集范围够生成门
  845. if (range.Y - range.X >= GameConfig.CorridorWidth)
  846. {
  847. // var tempRange = new Vector2I(Mathf.Abs(room1.Position.Y - (int)range.X),
  848. // Mathf.Abs(room1.Position.Y - (int)range.Y) - GameConfig.CorridorWidth);
  849.  
  850. var rangeValue = Mathf.Abs(room1.Position.Y - (int)range.X);
  851.  
  852. if (areaRange == null || rangeValue < areaRange)
  853. {
  854. areaRange = rangeValue;
  855. }
  856. }
  857. }
  858. else
  859. {
  860. var range = CalcOverlapRange(room1.GetVerticalStart(),
  861. room2.GetVerticalStart() - GameConfig.RoomSpace, p1, p2);
  862. //交集范围够生成门
  863. if (range.Y - range.X >= GameConfig.CorridorWidth)
  864. {
  865. // var tempRange = new Vector2I(Mathf.Abs(room1.Position.Y - (int)range.X),
  866. // Mathf.Abs(room1.Position.Y - (int)range.Y) - GameConfig.CorridorWidth);
  867. var rangeValue = Mathf.Abs(room1.Position.Y - (int)range.Y) - GameConfig.CorridorWidth;
  868.  
  869. if (areaRange == null || rangeValue > areaRange)
  870. {
  871. areaRange = rangeValue;
  872. }
  873. }
  874. }
  875. }
  876. }
  877.  
  878. private bool TryConnect_NE_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2I cross)
  879. {
  880. var offset1 = 0;
  881. var offset2 = 0;
  882. roomDoor.Direction = DoorDirection.N; //↑
  883. nextRoomDoor.Direction = DoorDirection.E; //→
  884.  
  885. if (!FindCrossPassage(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  886. {
  887. return false;
  888. }
  889. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalStart() + offset1, roomInfo.GetVerticalStart());
  890. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalEnd(),
  891. nextRoomInfo.GetVerticalStart() + offset2);
  892. cross = new Vector2I(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y);
  893. return true;
  894. }
  895.  
  896. private bool TryConnect_WS_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2I cross)
  897. {
  898. //ok
  899. var offset1 = 0;
  900. var offset2 = 0;
  901. roomDoor.Direction = DoorDirection.W; //←
  902. nextRoomDoor.Direction = DoorDirection.S; //↓
  903. if (!FindCrossPassage(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  904. {
  905. return false;
  906. }
  907. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalStart(), roomInfo.GetVerticalStart() + offset1);
  908. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart() + offset2, nextRoomInfo.GetVerticalEnd());
  909. cross = new Vector2I(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y);
  910. return true;
  911. }
  912.  
  913. private bool TryConnect_SE_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2I cross)
  914. {
  915. var offset1 = 0;
  916. var offset2 = 0;
  917. roomDoor.Direction = DoorDirection.S; //↓
  918. nextRoomDoor.Direction = DoorDirection.E; //→
  919. if (!FindCrossPassage(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  920. {
  921. return false;
  922. }
  923.  
  924. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalStart() + offset1, roomInfo.GetVerticalEnd());
  925. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalEnd(),
  926. nextRoomInfo.GetVerticalStart() + offset2);
  927. cross = new Vector2I(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y);
  928. return true;
  929. }
  930.  
  931. private bool TryConnect_WN_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2I cross)
  932. {
  933. var offset1 = 0;
  934. var offset2 = 0;
  935. roomDoor.Direction = DoorDirection.W; //←
  936. nextRoomDoor.Direction = DoorDirection.N; //↑
  937. if (!FindCrossPassage(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  938. {
  939. return false;
  940. }
  941.  
  942. roomDoor.OriginPosition =
  943. new Vector2I(roomInfo.GetHorizontalStart(), roomInfo.GetVerticalStart() + offset1); //
  944. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart() + offset2,
  945. nextRoomInfo.GetVerticalStart());
  946. cross = new Vector2I(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y);
  947. return true;
  948. }
  949. private bool TryConnect_ES_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2I cross)
  950. {
  951. var offset1 = 0;
  952. var offset2 = 0;
  953. roomDoor.Direction = DoorDirection.E; //→
  954. nextRoomDoor.Direction = DoorDirection.S; //↓
  955.  
  956. if (!FindCrossPassage(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  957. {
  958. return false;
  959. }
  960. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalEnd(), roomInfo.GetVerticalStart() + offset1);
  961. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart() + offset2,
  962. nextRoomInfo.GetVerticalEnd());
  963. cross = new Vector2I(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y);
  964. return true;
  965. }
  966. private bool TryConnect_NW_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2I cross)
  967. {
  968. var offset1 = 0;
  969. var offset2 = 0;
  970. roomDoor.Direction = DoorDirection.N; //↑
  971. nextRoomDoor.Direction = DoorDirection.W; //←
  972.  
  973. if (!FindCrossPassage(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  974. {
  975. return false;
  976. }
  977. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalStart() + offset1, roomInfo.GetVerticalStart());
  978. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart(),
  979. nextRoomInfo.GetVerticalStart() + offset2);
  980. cross = new Vector2I(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y);
  981. return true;
  982. }
  983. private bool TryConnect_EN_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2I cross)
  984. {
  985. var offset1 = 0;
  986. var offset2 = 0;
  987. roomDoor.Direction = DoorDirection.E; //→
  988. nextRoomDoor.Direction = DoorDirection.N; //↑
  989.  
  990. if (!FindCrossPassage(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  991. {
  992. return false;
  993. }
  994. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalEnd(),
  995. roomInfo.GetVerticalStart() + offset1);
  996. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart() + offset2, nextRoomInfo.GetVerticalStart());
  997. cross = new Vector2I(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y);
  998. return true;
  999. }
  1000.  
  1001. private bool TryConnect_SW_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor, ref Vector2I cross)
  1002. {
  1003. var offset1 = 0;
  1004. var offset2 = 0;
  1005. roomDoor.Direction = DoorDirection.S; //↓
  1006. nextRoomDoor.Direction = DoorDirection.W; //←
  1007.  
  1008. if (!FindCrossPassage(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  1009. {
  1010. return false;
  1011. }
  1012. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalStart() + offset1,
  1013. roomInfo.GetVerticalEnd());
  1014. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart(), nextRoomInfo.GetVerticalStart() + offset2);
  1015. cross = new Vector2I(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y);
  1016. return true;
  1017. }
  1018.  
  1019. /// <summary>
  1020. /// 查找房间的连接通道, 函数返回是否找到对应的门, 通过 result 返回 x/y 轴坐标
  1021. /// </summary>
  1022. /// <param name="roomInfo">第一个房间</param>
  1023. /// <param name="nextRoomInfo">第二个房间</param>
  1024. /// <param name="direction">第一个房间连接方向</param>
  1025. private List<Vector2I> FindPassage(RoomInfo roomInfo, RoomInfo nextRoomInfo, DoorDirection direction)
  1026. {
  1027. var room1 = roomInfo.RoomSplit.RoomInfo;
  1028. var room2 = nextRoomInfo.RoomSplit.RoomInfo;
  1029. //用于存储符合生成条件的区域
  1030. var rangeList = new List<Vector2I>();
  1031. foreach (var doorAreaInfo1 in room1.GetCompletionDoorArea())
  1032. {
  1033. if (doorAreaInfo1.Direction == direction)
  1034. {
  1035. //第二个门的方向
  1036. var direction2 = GetReverseDirection(direction);
  1037. foreach (var doorAreaInfo2 in room2.GetCompletionDoorArea())
  1038. {
  1039. if (doorAreaInfo2.Direction == direction2)
  1040. {
  1041. Vector2 range;
  1042. if (direction == DoorDirection.E || direction == DoorDirection.W) //第二个门向← 或者 第二个门向→
  1043. {
  1044. range = CalcOverlapRange(
  1045. roomInfo.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo1.Start, roomInfo.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo1.End,
  1046. nextRoomInfo.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo2.Start, nextRoomInfo.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo2.End
  1047. );
  1048. }
  1049. else //第二个门向↑ 或者 第二个门向↓
  1050. {
  1051. range = CalcOverlapRange(
  1052. roomInfo.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo1.Start, roomInfo.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo1.End,
  1053. nextRoomInfo.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo2.Start, nextRoomInfo.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo2.End
  1054. );
  1055. }
  1056. //交集范围够生成门
  1057. if (range.Y - range.X >= GameConfig.CorridorWidth * GameConfig.TileCellSize)
  1058. {
  1059. rangeList.Add(new Vector2I((int)(range.X / GameConfig.TileCellSize), (int)(range.Y / GameConfig.TileCellSize) - GameConfig.CorridorWidth));
  1060. }
  1061. }
  1062. }
  1063. }
  1064. }
  1065. return rangeList;
  1066. }
  1067. /// <summary>
  1068. /// 用于计算重叠区域坐标, 可以理解为一维轴上4个点的中间两个点, 返回的x为起始点, y为结束点
  1069. /// </summary>
  1070. private Vector2 CalcOverlapRange(float start1, float end1, float start2, float end2)
  1071. {
  1072. return new Vector2(Mathf.Max(start1, start2), Mathf.Min(end1, end2));
  1073. }
  1074.  
  1075. /// <summary>
  1076. /// 返回 p1 - p2 是否在 start - end 范围内
  1077. /// </summary>
  1078. private bool IsInRange(float start, float end, float p1, float p2)
  1079. {
  1080. return p1 >= start && p2 <= end;
  1081. }
  1082. //返回指定方向的反方向
  1083. //0上, 1右, 2下, 3左
  1084. private int GetReverseDirection(int direction)
  1085. {
  1086. switch (direction)
  1087. {
  1088. case 0: return 2;
  1089. case 1: return 3;
  1090. case 2: return 0;
  1091. case 3: return 1;
  1092. }
  1093.  
  1094. return 2;
  1095. }
  1096. //返回参数方向的反方向
  1097. private DoorDirection GetReverseDirection(DoorDirection direction)
  1098. {
  1099. switch (direction)
  1100. {
  1101. case DoorDirection.E:
  1102. return DoorDirection.W;
  1103. case DoorDirection.W:
  1104. return DoorDirection.E;
  1105. case DoorDirection.S:
  1106. return DoorDirection.N;
  1107. case DoorDirection.N:
  1108. return DoorDirection.S;
  1109. }
  1110.  
  1111. return DoorDirection.S;
  1112. }
  1113.  
  1114. //将两个门间的过道占用数据存入RoomGrid
  1115. private bool AddCorridorToGridRange(RoomDoorInfo door1, RoomDoorInfo door2)
  1116. {
  1117. var point1 = door1.OriginPosition;
  1118. var point2 = door2.OriginPosition;
  1119. var pos = new Vector2I(Mathf.Min(point1.X, point2.X), Mathf.Min(point1.Y, point2.Y));
  1120. var size = new Vector2I(
  1121. point1.X == point2.X ? GameConfig.CorridorWidth : Mathf.Abs(point1.X - point2.X),
  1122. point1.Y == point2.Y ? GameConfig.CorridorWidth : Mathf.Abs(point1.Y - point2.Y)
  1123. );
  1124.  
  1125. Vector2I collPos;
  1126. Vector2I collSize;
  1127. if (point1.X == point2.X) //纵向加宽, 防止贴到其它墙
  1128. {
  1129. collPos = new Vector2I(pos.X - GameConfig.RoomSpace, pos.Y);
  1130. collSize = new Vector2I(size.X + GameConfig.RoomSpace * 2, size.Y);
  1131. }
  1132. else //横向加宽, 防止贴到其它墙
  1133. {
  1134. collPos = new Vector2I(pos.X, pos.Y - GameConfig.RoomSpace);
  1135. collSize = new Vector2I(size.X, size.Y + GameConfig.RoomSpace * 2);
  1136. }
  1137.  
  1138. if (_roomGrid.RectCollision(collPos, collSize))
  1139. {
  1140. return false;
  1141. }
  1142.  
  1143. door2.RoomInfo.AisleArea.Add(new Rect2I(pos, size));
  1144. _roomGrid.SetRect(pos, size, true);
  1145. return true;
  1146. }
  1147.  
  1148. //将两个门间的过道占用数据存入RoomGrid, 该重载加入拐角点
  1149. private bool AddCorridorToGridRange(RoomDoorInfo door1, RoomDoorInfo door2, Vector2I cross)
  1150. {
  1151. var point1 = door1.OriginPosition;
  1152. var point2 = door2.OriginPosition;
  1153. var pos1 = new Vector2I(Mathf.Min(point1.X, cross.X), Mathf.Min(point1.Y, cross.Y));
  1154. var size1 = new Vector2I(
  1155. point1.X == cross.X ? GameConfig.CorridorWidth : Mathf.Abs(point1.X - cross.X),
  1156. point1.Y == cross.Y ? GameConfig.CorridorWidth : Mathf.Abs(point1.Y - cross.Y)
  1157. );
  1158. var pos2 = new Vector2I(Mathf.Min(point2.X, cross.X), Mathf.Min(point2.Y, cross.Y));
  1159. var size2 = new Vector2I(
  1160. point2.X == cross.X ? GameConfig.CorridorWidth : Mathf.Abs(point2.X - cross.X),
  1161. point2.Y == cross.Y ? GameConfig.CorridorWidth : Mathf.Abs(point2.Y - cross.Y)
  1162. );
  1163.  
  1164. Vector2I collPos1;
  1165. Vector2I collSize1;
  1166. if (point1.X == cross.X) //纵向加宽, 防止贴到其它墙
  1167. {
  1168. collPos1 = new Vector2I(pos1.X - GameConfig.RoomSpace, pos1.Y);
  1169. collSize1 = new Vector2I(size1.X + GameConfig.RoomSpace * 2, size1.Y);
  1170. }
  1171. else //横向加宽, 防止贴到其它墙
  1172. {
  1173. collPos1 = new Vector2I(pos1.X, pos1.Y - GameConfig.RoomSpace);
  1174. collSize1 = new Vector2I(size1.X, size1.Y + GameConfig.RoomSpace * 2);
  1175. }
  1176.  
  1177. if (_roomGrid.RectCollision(collPos1, collSize1))
  1178. {
  1179. return false;
  1180. }
  1181.  
  1182. Vector2I collPos2;
  1183. Vector2I collSize2;
  1184. if (point2.X == cross.X) //纵向加宽, 防止贴到其它墙
  1185. {
  1186. collPos2 = new Vector2I(pos2.X - GameConfig.RoomSpace, pos2.Y);
  1187. collSize2 = new Vector2I(size2.X + GameConfig.RoomSpace * 2, size2.Y);
  1188. }
  1189. else //横向加宽, 防止贴到其它墙
  1190. {
  1191. collPos2 = new Vector2I(pos2.X, pos2.Y - GameConfig.RoomSpace);
  1192. collSize2 = new Vector2I(size2.X, size2.Y + GameConfig.RoomSpace * 2);
  1193. }
  1194.  
  1195. if (_roomGrid.RectCollision(collPos2, collSize2))
  1196. {
  1197. return false;
  1198. }
  1199.  
  1200. door2.RoomInfo.AisleArea.Add(new Rect2I(pos1, size1));
  1201. door2.RoomInfo.AisleArea.Add(new Rect2I(pos2, size2));
  1202. _roomGrid.SetRect(pos1, size1, true);
  1203. _roomGrid.SetRect(pos2, size2, true);
  1204. return true;
  1205. }
  1206. }