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