Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / DungeonGenerator.cs
@小李xl 小李xl on 11 Oct 2023 46 KB 日志系统
  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. // private float _roomHorizontalMinDispersion = 0f;
  52. // private float _roomHorizontalMaxDispersion = 2f;
  53.  
  54. //房间纵轴分散程度
  55. private float _roomVerticalMinDispersion = 0f;
  56. private float _roomVerticalMaxDispersion = 0.5f;
  57. // private float _roomVerticalMinDispersion = 0f;
  58. // private float _roomVerticalMaxDispersion = 2f;
  59.  
  60. //区域限制
  61. private bool _enableLimitRange = true;
  62. private int _rangeX = 200;
  63. private int _rangeY = 200;
  64. //找房间失败次数, 过大则会关闭区域限制
  65. private int _maxFailCount = 10;
  66. private int _failCount = 0;
  67.  
  68. //最大尝试次数
  69. private int _maxTryCount = 10;
  70. private int _currMaxLayer = 0;
  71.  
  72. //地牢配置
  73. private DungeonConfig _config;
  74. private DungeonRoomGroup _roomGroup;
  75.  
  76. private enum GenerateRoomErrorCode
  77. {
  78. NoError,
  79. //超出区域
  80. OutArea,
  81. //没有合适的位置
  82. NoSuitableLocation
  83. // //碰到其他房间或过道
  84. // HasCollision,
  85. // //没有合适的门
  86. // NoProperDoor,
  87. }
  88. public DungeonGenerator(DungeonConfig config, SeedRandom seedRandom)
  89. {
  90. _config = config;
  91. _random = seedRandom;
  92. _roomGroup = GameApplication.Instance.RoomConfig[config.GroupName];
  93.  
  94. //验证该组是否满足生成地牢的条件
  95. var result = DungeonManager.CheckDungeon(config.GroupName);
  96. if (result.HasError)
  97. {
  98. throw new Exception("当前组'" + config.GroupName + "'" + result.ErrorMessage + ", 不能生成地牢!");
  99. }
  100. Debug.Log("创建地牢生成器, 随机种子: " + _random.Seed);
  101. _roomGroup.InitWeight(_random);
  102. }
  103.  
  104. /// <summary>
  105. /// 遍历所有房间
  106. /// </summary>
  107. public void EachRoom(Action<RoomInfo> cb)
  108. {
  109. EachRoom(StartRoomInfo, cb);
  110. }
  111.  
  112. private void EachRoom(RoomInfo roomInfo, Action<RoomInfo> cb)
  113. {
  114. if (roomInfo == null)
  115. {
  116. return;
  117. }
  118.  
  119. cb(roomInfo);
  120. foreach (var next in roomInfo.Next)
  121. {
  122. EachRoom(next, cb);
  123. }
  124. }
  125. /// <summary>
  126. /// 用于协程中的遍历所有房间
  127. /// </summary>
  128. public IEnumerator EachRoomCoroutine(Action<RoomInfo> cb)
  129. {
  130. return EachRoomCoroutine(StartRoomInfo, cb);
  131. }
  132. private IEnumerator EachRoomCoroutine(RoomInfo roomInfo, Action<RoomInfo> cb)
  133. {
  134. if (roomInfo == null)
  135. {
  136. yield break;
  137. }
  138.  
  139. cb(roomInfo);
  140. foreach (var next in roomInfo.Next)
  141. {
  142. yield return EachRoomCoroutine(next, cb);
  143. }
  144. }
  145.  
  146. /// <summary>
  147. /// 生成房间
  148. /// </summary>
  149. public void Generate()
  150. {
  151. if (StartRoomInfo != null) return;
  152. CalcNextRoomType(null);
  153. //用于排除上一级房间
  154. var excludePrevRoom = new List<RoomInfo>();
  155. //上一个房间
  156. RoomInfo prevRoomInfo = null;
  157. var chainTryCount = 0;
  158. var chainMaxTryCount = 3;
  159.  
  160. //如果房间数量不够, 就一直生成
  161. while (_count < _config.RoomCount || EndRoomInfo == null)
  162. {
  163. var nextRoomType = GetNextRoomType();
  164. //上一个房间
  165. RoomInfo tempPrevRoomInfo;
  166. if (nextRoomType == DungeonRoomType.Inlet)
  167. {
  168. tempPrevRoomInfo = null;
  169. }
  170. else if (nextRoomType == DungeonRoomType.Boss)
  171. {
  172. tempPrevRoomInfo = FindMaxLayerRoom(excludePrevRoom);
  173. }
  174. else if (nextRoomType == DungeonRoomType.Outlet)
  175. {
  176. tempPrevRoomInfo = prevRoomInfo;
  177. }
  178. else if (nextRoomType == DungeonRoomType.Battle)
  179. {
  180. if (chainTryCount < chainMaxTryCount)
  181. {
  182. if (prevRoomInfo != null && prevRoomInfo.Layer > 6) //层数太高, 下一个房间生成在低层级
  183. {
  184. tempPrevRoomInfo = RoundRoomLessThanLayer(3);
  185. }
  186. else
  187. {
  188. tempPrevRoomInfo = prevRoomInfo;
  189. }
  190. }
  191. else
  192. {
  193. tempPrevRoomInfo = _random.RandomChoose(RoomInfos);
  194. }
  195. }
  196. else
  197. {
  198. tempPrevRoomInfo = _random.RandomChoose(RoomInfos);
  199. }
  200. //生成下一个房间
  201. var errorCode = GenerateRoom(tempPrevRoomInfo, nextRoomType, out var nextRoom);
  202. if (errorCode == GenerateRoomErrorCode.NoError) //生成成功
  203. {
  204. _failCount = 0;
  205. RoomInfos.Add(nextRoom);
  206. if (nextRoomType == DungeonRoomType.Inlet)
  207. {
  208. StartRoomInfo = 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. EndRoomInfo = nextRoom;
  218. }
  219. else if (nextRoomType == DungeonRoomType.Battle)
  220. {
  221. chainTryCount = 0;
  222. chainMaxTryCount = _random.RandomRangeInt(1, 3);
  223. }
  224. prevRoomInfo = nextRoom;
  225. CalcNextRoomType(prevRoomInfo);
  226. }
  227. else //生成失败
  228. {
  229. if (nextRoomType == DungeonRoomType.Boss)
  230. {
  231. //生成boss房间成功
  232. excludePrevRoom.Add(tempPrevRoomInfo);
  233. if (excludePrevRoom.Count >= RoomInfos.Count)
  234. {
  235. //全都没找到合适的, 那就再来一遍
  236. excludePrevRoom.Clear();
  237. }
  238. }
  239. else if (nextRoomType == DungeonRoomType.Outlet)
  240. {
  241. //生成结束房间失败, 那么只能回滚boss房间
  242. if (prevRoomInfo != null)
  243. {
  244. var bossPrev = prevRoomInfo.Prev;
  245. BossRoom.Remove(prevRoomInfo);
  246. RollbackRoom(prevRoomInfo);
  247. CalcNextRoomType(bossPrev);
  248. prevRoomInfo = null;
  249. }
  250. }
  251. else if (nextRoomType == DungeonRoomType.Battle)
  252. {
  253. chainTryCount++;
  254. }
  255. Debug.Log("生成第" + (_count + 1) + "个房间失败! 失败原因: " + errorCode);
  256. if (errorCode == GenerateRoomErrorCode.OutArea)
  257. {
  258. _failCount++;
  259. Debug.Log("超出区域失败次数: " + _failCount);
  260. if (_failCount >= _maxFailCount)
  261. {
  262. _enableLimitRange = false;
  263. Debug.Log("生成房间失败次数过多, 关闭区域限制!");
  264. }
  265. }
  266. }
  267. }
  268. _roomGrid.Clear();
  269. Debug.Log("房间总数: " + RoomInfos.Count);
  270. }
  271.  
  272. //生成房间
  273. private GenerateRoomErrorCode GenerateRoom(RoomInfo prevRoomInfo, DungeonRoomType roomType, out RoomInfo resultRoomInfo)
  274. {
  275. // if (_count >= _config.RoomCount)
  276. // {
  277. // resultRoom = null;
  278. // return GenerateRoomErrorCode.RoomFull;
  279. // }
  280.  
  281. DungeonRoomSplit roomSplit;
  282. if (_config.HasDesignatedRoom && _config.DesignatedType == roomType) //执行指定了房间
  283. {
  284. roomSplit = _random.RandomChoose(_config.DesignatedRoom);
  285. }
  286. else //没有指定房间
  287. {
  288. //随机选择一个房间
  289. var list = _roomGroup.GetRoomList(roomType);
  290. if (list.Count == 0) //如果没有指定类型的房间, 就生成战斗房间
  291. {
  292. roomSplit = _roomGroup.GetRandomRoom(DungeonRoomType.Battle);
  293. }
  294. else
  295. {
  296. roomSplit = _roomGroup.GetRandomRoom(roomType);
  297. }
  298. }
  299. var room = new RoomInfo(_id, roomType, roomSplit);
  300.  
  301. //房间大小
  302. room.Size = new Vector2I((int)roomSplit.RoomInfo.Size.X, (int)roomSplit.RoomInfo.Size.Y);
  303.  
  304. if (prevRoomInfo != null) //表示这不是第一个房间, 就得判断当前位置下的房间是否被遮挡
  305. {
  306. room.Layer = prevRoomInfo.Layer + 1;
  307. if (_currMaxLayer < room.Layer)
  308. {
  309. _currMaxLayer = room.Layer;
  310. }
  311. //生成的位置可能会和上一个房间对不上, 需要多次尝试
  312. var tryCount = 0; //当前尝试次数
  313. var maxTryCount = _maxTryCount; //最大尝试次数
  314. if (roomType == DungeonRoomType.Outlet)
  315. {
  316. maxTryCount *= 3;
  317. }
  318. else if (roomType == DungeonRoomType.Boss)
  319. {
  320. maxTryCount *= 2;
  321. }
  322. for (; tryCount < maxTryCount; tryCount++)
  323. {
  324. var direction = _random.RandomRangeInt(0, 3);
  325. //房间间隔
  326. var space = _random.RandomRangeInt(_roomMinInterval, _roomMaxInterval);
  327. //中心偏移
  328. int offset;
  329. if (direction == 0 || direction == 2)
  330. {
  331. offset = _random.RandomRangeInt(-(int)(prevRoomInfo.Size.X * _roomVerticalMinDispersion),
  332. (int)(prevRoomInfo.Size.X * _roomVerticalMaxDispersion));
  333. }
  334. else
  335. {
  336. offset = _random.RandomRangeInt(-(int)(prevRoomInfo.Size.Y * _roomHorizontalMinDispersion),
  337. (int)(prevRoomInfo.Size.Y * _roomHorizontalMaxDispersion));
  338. }
  339.  
  340. //计算房间位置
  341. if (direction == 0) //上
  342. {
  343. room.Position = new Vector2I(prevRoomInfo.Position.X + offset,
  344. prevRoomInfo.Position.Y - room.Size.Y - space);
  345. }
  346. else if (direction == 1) //右
  347. {
  348. room.Position = new Vector2I(prevRoomInfo.Position.X + prevRoomInfo.Size.Y + space,
  349. prevRoomInfo.Position.Y + offset);
  350. }
  351. else if (direction == 2) //下
  352. {
  353. room.Position = new Vector2I(prevRoomInfo.Position.X + offset,
  354. prevRoomInfo.Position.Y + prevRoomInfo.Size.Y + space);
  355. }
  356. else if (direction == 3) //左
  357. {
  358. room.Position = new Vector2I(prevRoomInfo.Position.X - room.Size.X - space,
  359. prevRoomInfo.Position.Y + offset);
  360. }
  361.  
  362. //是否在限制区域内
  363. if (_enableLimitRange)
  364. {
  365. if (room.GetHorizontalStart() < -_rangeX || room.GetHorizontalEnd() > _rangeX ||
  366. room.GetVerticalStart() < -_rangeY || room.GetVerticalEnd() > _rangeY)
  367. {
  368. //超出区域, 直接跳出尝试的循环, 返回 null
  369. resultRoomInfo = null;
  370. return GenerateRoomErrorCode.OutArea;
  371. }
  372. }
  373.  
  374. //是否碰到其他房间或者过道
  375. if (_roomGrid.RectCollision(room.Position - new Vector2I(GameConfig.RoomSpace, GameConfig.RoomSpace), room.Size + new Vector2I(GameConfig.RoomSpace * 2, GameConfig.RoomSpace * 2)))
  376. {
  377. //碰到其他墙壁, 再一次尝试
  378. continue;
  379. //return GenerateRoomErrorCode.HasCollision;
  380. }
  381.  
  382. _roomGrid.SetRect(room.Position, room.Size, true);
  383.  
  384. //找门, 与上一个房间是否能连通
  385. if (!ConnectDoor(prevRoomInfo, room))
  386. {
  387. _roomGrid.RemoveRect(room.Position, room.Size);
  388. //房间过道没有连接上, 再一次尝试
  389. continue;
  390. //return GenerateRoomErrorCode.NoProperDoor;
  391. }
  392. break;
  393. }
  394.  
  395. //尝试次数用光了, 还没有找到合适的位置
  396. if (tryCount >= maxTryCount)
  397. {
  398. resultRoomInfo = null;
  399. return GenerateRoomErrorCode.NoSuitableLocation;
  400. }
  401. }
  402. else //第一个房间
  403. {
  404. room.Layer = 0;
  405. _roomGrid.SetRect(room.Position, room.Size, true);
  406. }
  407.  
  408. if (IsParticipateCounting(room))
  409. {
  410. _count++;
  411. }
  412. _id++;
  413. room.Prev = prevRoomInfo;
  414. if (prevRoomInfo != null)
  415. {
  416. prevRoomInfo.Next.Add(room);
  417. }
  418. resultRoomInfo = room;
  419. return GenerateRoomErrorCode.NoError;
  420. }
  421.  
  422. //判断房间是否参与计数
  423. private bool IsParticipateCounting(RoomInfo roomInfo)
  424. {
  425. return roomInfo.RoomType == DungeonRoomType.Battle || roomInfo.RoomType == DungeonRoomType.Boss;
  426. }
  427.  
  428. //计算下一个房间类型
  429. private void CalcNextRoomType(RoomInfo prev)
  430. {
  431. if (prev == null) //生成第一个房间
  432. {
  433. _nextRoomType = DungeonRoomType.Inlet;
  434. }
  435. else if (_count == _config.RoomCount - 1) //最后一个房间是boss房间
  436. {
  437. _nextRoomType = DungeonRoomType.Boss;
  438. }
  439. else if (_count >= _config.RoomCount) //结束房间
  440. {
  441. _nextRoomType = DungeonRoomType.Outlet;
  442. }
  443. else if (prev.RoomType == DungeonRoomType.Boss) //生成结束房间
  444. {
  445. _nextRoomType = DungeonRoomType.Outlet;
  446. }
  447. else
  448. {
  449. _nextRoomType = DungeonRoomType.Battle;
  450. }
  451. }
  452. //获取下一个房间类型
  453. private DungeonRoomType GetNextRoomType()
  454. {
  455. return _nextRoomType;
  456. }
  457.  
  458. //回滚一个房间
  459. private bool RollbackRoom(RoomInfo roomInfo)
  460. {
  461. if (roomInfo.Next.Count > 0)
  462. {
  463. Debug.LogError("当前房间还有连接的子房间, 不能回滚!");
  464. return false;
  465. }
  466. //退掉占用的房间区域和过道占用区域
  467. _roomGrid.RemoveRect(roomInfo.Position, roomInfo.Size);
  468. foreach (var rect2 in roomInfo.AisleArea)
  469. {
  470. _roomGrid.RemoveRect(rect2.Position, rect2.Size);
  471. }
  472. //roomInfo.Doors[0].
  473. if (roomInfo.Prev != null)
  474. {
  475. roomInfo.Prev.Next.Remove(roomInfo);
  476. }
  477.  
  478. roomInfo.Prev = null;
  479. foreach (var roomInfoDoor in roomInfo.Doors)
  480. {
  481. var connectDoor = roomInfoDoor.ConnectDoor;
  482. connectDoor.RoomInfo.Doors.Remove(connectDoor);
  483. }
  484.  
  485. RoomInfos.Remove(roomInfo);
  486. roomInfo.Destroy();
  487.  
  488. if (IsParticipateCounting(roomInfo))
  489. {
  490. _count--;
  491. }
  492.  
  493. _id--;
  494. return true;
  495. }
  496.  
  497. /// <summary>
  498. /// 寻找层级最高的房间
  499. /// </summary>
  500. /// <param name="exclude">排除的房间</param>
  501. private RoomInfo FindMaxLayerRoom(List<RoomInfo> exclude)
  502. {
  503. RoomInfo temp = null;
  504. foreach (var roomInfo in RoomInfos)
  505. {
  506. if (temp == null || roomInfo.Layer > temp.Layer)
  507. {
  508. if (exclude == null || !exclude.Contains(roomInfo))
  509. {
  510. temp = roomInfo;
  511. }
  512. }
  513. }
  514.  
  515. return temp;
  516. }
  517.  
  518. /// <summary>
  519. /// 随机抽取层级小于 layer 的房间
  520. /// </summary>
  521. private RoomInfo RoundRoomLessThanLayer(int layer)
  522. {
  523. var list = new List<RoomInfo>();
  524. foreach (var roomInfo in RoomInfos)
  525. {
  526. if (roomInfo.Layer < layer)
  527. {
  528. list.Add(roomInfo);
  529. }
  530. }
  531.  
  532. return _random.RandomChoose(list);
  533. }
  534. /// <summary>
  535. /// 找两个房间的门
  536. /// </summary>
  537. private bool ConnectDoor(RoomInfo roomInfo, RoomInfo nextRoomInfo)
  538. {
  539. //门描述
  540. var roomDoor = new RoomDoorInfo();
  541. var nextRoomDoor = new RoomDoorInfo();
  542. roomDoor.RoomInfo = roomInfo;
  543. roomDoor.IsForward = true;
  544. nextRoomDoor.RoomInfo = nextRoomInfo;
  545. roomDoor.ConnectRoom = nextRoomInfo;
  546. roomDoor.ConnectDoor = nextRoomDoor;
  547. nextRoomDoor.ConnectRoom = roomInfo;
  548. nextRoomDoor.ConnectDoor = roomDoor;
  549.  
  550. //先寻找直通门
  551. if (_random.RandomBoolean())
  552. {
  553. //直行通道, 优先横轴
  554. if (TryConnectHorizontalDoor(roomInfo, roomDoor, nextRoomInfo, nextRoomDoor)
  555. || TryConnectVerticalDoor(roomInfo, roomDoor, nextRoomInfo, nextRoomDoor))
  556. {
  557. return true;
  558. }
  559. }
  560. else
  561. {
  562. //直行通道, 优先纵轴
  563. if (TryConnectVerticalDoor(roomInfo, roomDoor, nextRoomInfo, nextRoomDoor)
  564. || TryConnectHorizontalDoor(roomInfo, roomDoor, nextRoomInfo, nextRoomDoor))
  565. {
  566. return true;
  567. }
  568. }
  569. //包含拐角的通道
  570. return TryConnectCrossDoor(roomInfo, roomDoor, nextRoomInfo, nextRoomDoor);
  571. }
  572.  
  573. /// <summary>
  574. /// 尝试寻找横轴方向上两个房间的连通的门, 只查找直线通道, 返回是否找到
  575. /// </summary>
  576. private bool TryConnectHorizontalDoor(RoomInfo roomInfo, RoomDoorInfo roomDoor, RoomInfo nextRoomInfo, RoomDoorInfo nextRoomDoor)
  577. {
  578. var overlapX = Mathf.Min(roomInfo.GetHorizontalEnd(), nextRoomInfo.GetHorizontalEnd()) -
  579. Mathf.Max(roomInfo.GetHorizontalStart(), nextRoomInfo.GetHorizontalStart());
  580. //这种情况下x轴有重叠
  581. if (overlapX >= 6)
  582. {
  583. //找到重叠区域
  584. var rangeList = FindPassage(roomInfo, nextRoomInfo,
  585. roomInfo.GetVerticalStart() < nextRoomInfo.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 (roomInfo.GetVerticalStart() < nextRoomInfo.GetVerticalStart()) //room在上, nextRoom在下
  592. {
  593. roomDoor.Direction = DoorDirection.S;
  594. nextRoomDoor.Direction = DoorDirection.N;
  595. roomDoor.OriginPosition = new Vector2I(x, roomInfo.GetVerticalEnd());
  596. nextRoomDoor.OriginPosition = new Vector2I(x, nextRoomInfo.GetVerticalStart());
  597. }
  598. else //room在下, nextRoom在上
  599. {
  600. roomDoor.Direction = DoorDirection.N;
  601. nextRoomDoor.Direction = DoorDirection.S;
  602. roomDoor.OriginPosition = new Vector2I(x, roomInfo.GetVerticalStart());
  603. nextRoomDoor.OriginPosition = new Vector2I(x, nextRoomInfo.GetVerticalEnd());
  604. }
  605.  
  606. //判断门之间的通道是否有物体碰到
  607. if (!AddCorridorToGridRange(roomDoor, nextRoomDoor))
  608. {
  609. //此门不能连通
  610. continue;
  611. }
  612.  
  613. //没有撞到物体
  614. roomInfo.Doors.Add(roomDoor);
  615. nextRoomInfo.Doors.Add(nextRoomDoor);
  616. return true;
  617. }
  618. }
  619. return false;
  620. }
  621.  
  622. /// <summary>
  623. /// 尝试寻找纵轴方向上两个房间的连通的门, 只查找直线通道, 返回是否找到
  624. /// </summary>
  625. private bool TryConnectVerticalDoor(RoomInfo roomInfo, RoomDoorInfo roomDoor, RoomInfo nextRoomInfo, RoomDoorInfo nextRoomDoor)
  626. {
  627. var overlapY = Mathf.Min(roomInfo.GetVerticalEnd(), nextRoomInfo.GetVerticalEnd()) -
  628. Mathf.Max(roomInfo.GetVerticalStart(), nextRoomInfo.GetVerticalStart());
  629. //这种情况下y轴有重叠
  630. if (overlapY >= 6)
  631. {
  632. //找到重叠区域
  633. var rangeList = FindPassage(roomInfo, nextRoomInfo,
  634. roomInfo.GetHorizontalStart() < nextRoomInfo.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 (roomInfo.GetHorizontalStart() < nextRoomInfo.GetHorizontalStart()) //room在左, nextRoom在右
  642. {
  643. roomDoor.Direction = DoorDirection.E;
  644. nextRoomDoor.Direction = DoorDirection.W;
  645. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalEnd(), y);
  646. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart(), y);
  647. }
  648. else //room在右, nextRoom在左
  649. {
  650. roomDoor.Direction = DoorDirection.W;
  651. nextRoomDoor.Direction = DoorDirection.E;
  652. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalStart(), y);
  653. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalEnd(), y);
  654. }
  655.  
  656. //判断门之间的通道是否有物体碰到
  657. if (!AddCorridorToGridRange(roomDoor, nextRoomDoor))
  658. {
  659. //此门不能连通
  660. continue;
  661. }
  662.  
  663. //没有撞到物体
  664. roomInfo.Doors.Add(roomDoor);
  665. nextRoomInfo.Doors.Add(nextRoomDoor);
  666. return true;
  667. }
  668. }
  669.  
  670. return false;
  671. }
  672.  
  673. /// <summary>
  674. /// 尝试寻找包含拐角的两个房间的连通的门, 返回是否找到
  675. /// </summary>
  676. private bool TryConnectCrossDoor(RoomInfo roomInfo, RoomDoorInfo roomDoor, RoomInfo nextRoomInfo, RoomDoorInfo nextRoomDoor)
  677. {
  678. //焦点
  679. Vector2I cross = default;
  680.  
  681. if (roomInfo.GetHorizontalStart() > nextRoomInfo.GetHorizontalStart())
  682. {
  683. if (roomInfo.GetVerticalStart() > nextRoomInfo.GetVerticalStart())
  684. {
  685. if (_random.RandomBoolean()) //↑ //→
  686. {
  687. if (!TryConnect_NE_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  688. !TryConnect_WS_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  689. {
  690. return false;
  691. }
  692. }
  693. else //← //↓
  694. {
  695. if (!TryConnect_WS_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  696. !TryConnect_NE_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  697. {
  698. return false;
  699. }
  700. }
  701. }
  702. else
  703. {
  704. if (_random.RandomBoolean()) //↓ //→
  705. {
  706. if (!TryConnect_SE_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  707. !TryConnect_WN_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  708. {
  709. return false;
  710. }
  711. }
  712. else //← //↑
  713. {
  714. if (!TryConnect_WN_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  715. !TryConnect_SE_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  716. {
  717. return false;
  718. }
  719. }
  720. }
  721. }
  722. else
  723. {
  724. if (roomInfo.GetVerticalStart() > nextRoomInfo.GetVerticalStart()) //→ //↓
  725. {
  726. if (_random.RandomBoolean())
  727. {
  728. if (!TryConnect_ES_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  729. !TryConnect_NW_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  730. {
  731. return false;
  732. }
  733. }
  734. else //↑ //←
  735. {
  736. if (!TryConnect_NW_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  737. !TryConnect_ES_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  738. {
  739. return false;
  740. }
  741. }
  742. }
  743. else
  744. {
  745. if (_random.RandomBoolean()) //→ //↑
  746. {
  747. if (!TryConnect_EN_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  748. !TryConnect_SW_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross))
  749. {
  750. return false;
  751. }
  752. }
  753. else //↓ //←
  754. {
  755. if (!TryConnect_SW_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) &&
  756. !TryConnect_EN_Door(roomInfo, nextRoomInfo, 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. roomInfo.Doors.Add(roomDoor);
  777. nextRoomInfo.Doors.Add(nextRoomDoor);
  778. return true;
  779. }
  780.  
  781. private bool FindCrossPassage(RoomInfo roomInfo, RoomInfo nextRoomInfo, RoomDoorInfo roomDoor, RoomDoorInfo nextRoomDoor,ref int offset1, ref int offset2)
  782. {
  783. var room1 = roomInfo.RoomSplit.RoomInfo;
  784. var room2 = nextRoomInfo.RoomSplit.RoomInfo;
  785. int? temp1 = null;
  786. int? temp2 = null;
  787.  
  788. foreach (var areaInfo1 in room1.GetCompletionDoorArea())
  789. {
  790. if (areaInfo1.Direction == roomDoor.Direction)
  791. {
  792. FindCrossPassage_Area(areaInfo1, roomInfo, nextRoomInfo, ref temp1);
  793. }
  794. }
  795. if (temp1 == null)
  796. {
  797. return false;
  798. }
  799.  
  800. foreach (var areaInfo2 in room2.GetCompletionDoorArea())
  801. {
  802. if (areaInfo2.Direction == nextRoomDoor.Direction)
  803. {
  804. FindCrossPassage_Area(areaInfo2, nextRoomInfo, roomInfo, 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 roomInfo, RoomInfo nextRoomInfo, 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(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  913. {
  914. return false;
  915. }
  916. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalStart() + offset1, roomInfo.GetVerticalStart());
  917. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalEnd(),
  918. nextRoomInfo.GetVerticalStart() + offset2);
  919. cross = new Vector2I(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y);
  920. return true;
  921. }
  922.  
  923. private bool TryConnect_WS_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, 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(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  931. {
  932. return false;
  933. }
  934. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalStart(), roomInfo.GetVerticalStart() + offset1);
  935. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart() + offset2, nextRoomInfo.GetVerticalEnd());
  936. cross = new Vector2I(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y);
  937. return true;
  938. }
  939.  
  940. private bool TryConnect_SE_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, 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(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  947. {
  948. return false;
  949. }
  950.  
  951. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalStart() + offset1, roomInfo.GetVerticalEnd());
  952. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalEnd(),
  953. nextRoomInfo.GetVerticalStart() + offset2);
  954. cross = new Vector2I(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y);
  955. return true;
  956. }
  957.  
  958. private bool TryConnect_WN_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, 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(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  965. {
  966. return false;
  967. }
  968.  
  969. roomDoor.OriginPosition =
  970. new Vector2I(roomInfo.GetHorizontalStart(), roomInfo.GetVerticalStart() + offset1); //
  971. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart() + offset2,
  972. nextRoomInfo.GetVerticalStart());
  973. cross = new Vector2I(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y);
  974. return true;
  975. }
  976. private bool TryConnect_ES_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, 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(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  984. {
  985. return false;
  986. }
  987. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalEnd(), roomInfo.GetVerticalStart() + offset1);
  988. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart() + offset2,
  989. nextRoomInfo.GetVerticalEnd());
  990. cross = new Vector2I(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y);
  991. return true;
  992. }
  993. private bool TryConnect_NW_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, 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(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  1001. {
  1002. return false;
  1003. }
  1004. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalStart() + offset1, roomInfo.GetVerticalStart());
  1005. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart(),
  1006. nextRoomInfo.GetVerticalStart() + offset2);
  1007. cross = new Vector2I(roomDoor.OriginPosition.X, nextRoomDoor.OriginPosition.Y);
  1008. return true;
  1009. }
  1010. private bool TryConnect_EN_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, 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(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  1018. {
  1019. return false;
  1020. }
  1021. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalEnd(),
  1022. roomInfo.GetVerticalStart() + offset1);
  1023. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart() + offset2, nextRoomInfo.GetVerticalStart());
  1024. cross = new Vector2I(nextRoomDoor.OriginPosition.X, roomDoor.OriginPosition.Y);
  1025. return true;
  1026. }
  1027.  
  1028. private bool TryConnect_SW_Door(RoomInfo roomInfo, RoomInfo nextRoomInfo, 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(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref offset1, ref offset2))
  1036. {
  1037. return false;
  1038. }
  1039. roomDoor.OriginPosition = new Vector2I(roomInfo.GetHorizontalStart() + offset1,
  1040. roomInfo.GetVerticalEnd());
  1041. nextRoomDoor.OriginPosition = new Vector2I(nextRoomInfo.GetHorizontalStart(), nextRoomInfo.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="roomInfo">第一个房间</param>
  1050. /// <param name="nextRoomInfo">第二个房间</param>
  1051. /// <param name="direction">第一个房间连接方向</param>
  1052. private List<Vector2I> FindPassage(RoomInfo roomInfo, RoomInfo nextRoomInfo, DoorDirection direction)
  1053. {
  1054. var room1 = roomInfo.RoomSplit.RoomInfo;
  1055. var room2 = nextRoomInfo.RoomSplit.RoomInfo;
  1056. //用于存储符合生成条件的区域
  1057. var rangeList = new List<Vector2I>();
  1058. foreach (var doorAreaInfo1 in room1.GetCompletionDoorArea())
  1059. {
  1060. if (doorAreaInfo1.Direction == direction)
  1061. {
  1062. //第二个门的方向
  1063. var direction2 = GetReverseDirection(direction);
  1064. foreach (var doorAreaInfo2 in room2.GetCompletionDoorArea())
  1065. {
  1066. if (doorAreaInfo2.Direction == direction2)
  1067. {
  1068. Vector2 range;
  1069. if (direction == DoorDirection.E || direction == DoorDirection.W) //第二个门向← 或者 第二个门向→
  1070. {
  1071. range = CalcOverlapRange(
  1072. roomInfo.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo1.Start, roomInfo.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo1.End,
  1073. nextRoomInfo.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo2.Start, nextRoomInfo.GetVerticalStart() * GameConfig.TileCellSize + doorAreaInfo2.End
  1074. );
  1075. }
  1076. else //第二个门向↑ 或者 第二个门向↓
  1077. {
  1078. range = CalcOverlapRange(
  1079. roomInfo.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo1.Start, roomInfo.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo1.End,
  1080. nextRoomInfo.GetHorizontalStart() * GameConfig.TileCellSize + doorAreaInfo2.Start, nextRoomInfo.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. }