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