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