Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / room / DungeonManager.cs
@小李xl 小李xl on 21 Sep 2023 24 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 partial class DungeonManager : Node2D
  11. {
  12. /// <summary>
  13. /// 起始房间
  14. /// </summary>
  15. public RoomInfo StartRoomInfo => _dungeonGenerator?.StartRoomInfo;
  16. /// <summary>
  17. /// 当前玩家所在的房间
  18. /// </summary>
  19. public RoomInfo ActiveRoomInfo => Player.Current?.AffiliationArea?.RoomInfo;
  20. /// <summary>
  21. /// 当前玩家所在的区域
  22. /// </summary>
  23. public AffiliationArea ActiveAffiliationArea => Player.Current?.AffiliationArea;
  24.  
  25. /// <summary>
  26. /// 是否在地牢里
  27. /// </summary>
  28. public bool IsInDungeon { get; private set; }
  29.  
  30. /// <summary>
  31. /// 是否是编辑器模式
  32. /// </summary>
  33. public bool IsEditorMode { get; private set; }
  34. /// <summary>
  35. /// 当前使用的配置
  36. /// </summary>
  37. public DungeonConfig CurrConfig { get; private set; }
  38. /// <summary>
  39. /// 当前使用的世界对象
  40. /// </summary>
  41. public World World { get; private set; }
  42. private UiBase _prevUi;
  43. private DungeonTileMap _dungeonTileMap;
  44. private AutoTileConfig _autoTileConfig;
  45. private DungeonGenerator _dungeonGenerator;
  46. //房间内所有静态导航网格数据
  47. private List<NavigationPolygonData> _roomStaticNavigationList;
  48. //用于检查房间敌人的计时器
  49. private float _checkEnemyTimer = 0;
  50.  
  51.  
  52. public DungeonManager()
  53. {
  54. //绑定事件
  55. EventManager.AddEventListener(EventEnum.OnPlayerFirstEnterRoom, OnPlayerFirstEnterRoom);
  56. EventManager.AddEventListener(EventEnum.OnPlayerEnterRoom, OnPlayerEnterRoom);
  57. }
  58. /// <summary>
  59. /// 加载地牢
  60. /// </summary>
  61. public void LoadDungeon(DungeonConfig config, Action finish = null)
  62. {
  63. IsEditorMode = false;
  64. CurrConfig = config;
  65. GameApplication.Instance.StartCoroutine(RunLoadDungeonCoroutine(finish));
  66. }
  67. /// <summary>
  68. /// 重启地牢
  69. /// </summary>
  70. public void RestartDungeon(DungeonConfig config)
  71. {
  72. IsEditorMode = false;
  73. CurrConfig = config;
  74. ExitDungeon(() =>
  75. {
  76. LoadDungeon(CurrConfig);
  77. });
  78. }
  79.  
  80. /// <summary>
  81. /// 退出地牢
  82. /// </summary>
  83. public void ExitDungeon(Action finish = null)
  84. {
  85. IsInDungeon = false;
  86. GameApplication.Instance.StartCoroutine(RunExitDungeonCoroutine(finish));
  87. }
  88. //-------------------------------------------------------------------------------------
  89.  
  90. /// <summary>
  91. /// 在编辑器模式下进入地牢
  92. /// </summary>
  93. /// <param name="config">地牢配置</param>
  94. public void EditorPlayDungeon(DungeonConfig config)
  95. {
  96. IsEditorMode = true;
  97. CurrConfig = config;
  98. if (_prevUi != null)
  99. {
  100. _prevUi.HideUi();
  101. }
  102. GameApplication.Instance.StartCoroutine(RunLoadDungeonCoroutine(null));
  103. }
  104. /// <summary>
  105. /// 在编辑器模式下进入地牢
  106. /// </summary>
  107. /// <param name="prevUi">记录上一个Ui</param>
  108. /// <param name="config">地牢配置</param>
  109. public void EditorPlayDungeon(UiBase prevUi, DungeonConfig config)
  110. {
  111. IsEditorMode = true;
  112. CurrConfig = config;
  113. _prevUi = prevUi;
  114. if (_prevUi != null)
  115. {
  116. _prevUi.HideUi();
  117. }
  118. GameApplication.Instance.StartCoroutine(RunLoadDungeonCoroutine(null));
  119. }
  120.  
  121. /// <summary>
  122. /// 在编辑器模式下退出地牢, 并且打开上一个Ui
  123. /// </summary>
  124. public void EditorExitDungeon()
  125. {
  126. IsInDungeon = false;
  127. GameApplication.Instance.StartCoroutine(RunExitDungeonCoroutine(() =>
  128. {
  129. IsEditorMode = false;
  130. //显示上一个Ui
  131. if (_prevUi != null)
  132. {
  133. _prevUi.ShowUi();
  134. }
  135. }));
  136. }
  137. //-------------------------------------------------------------------------------------
  138.  
  139. public override void _Process(double delta)
  140. {
  141. if (IsInDungeon)
  142. {
  143. if (World.Pause) //已经暂停
  144. {
  145. return;
  146. }
  147. //暂停游戏
  148. if (Input.IsActionJustPressed("ui_cancel"))
  149. {
  150. World.Pause = true;
  151. //鼠标改为Ui鼠标
  152. GameApplication.Instance.Cursor.SetGuiMode(true);
  153. //打开暂停Ui
  154. UiManager.Open_PauseMenu();
  155. }
  156. _checkEnemyTimer += (float)delta;
  157. if (_checkEnemyTimer >= 1)
  158. {
  159. _checkEnemyTimer %= 1;
  160. //检查房间内的敌人存活状况
  161. OnCheckEnemy();
  162. }
  163. //更新敌人视野
  164. UpdateEnemiesView();
  165. if (GameApplication.Instance.Debug)
  166. {
  167. QueueRedraw();
  168. }
  169. }
  170. }
  171.  
  172. //执行加载地牢协程
  173. private IEnumerator RunLoadDungeonCoroutine(Action finish)
  174. {
  175. //打开 loading UI
  176. UiManager.Open_Loading();
  177. yield return 0;
  178. //创建世界场景
  179. World = GameApplication.Instance.CreateNewWorld();
  180. yield return 0;
  181. //生成地牢房间
  182. _dungeonGenerator = new DungeonGenerator(CurrConfig);
  183. _dungeonGenerator.Generate();
  184. yield return 0;
  185. //填充地牢
  186. _autoTileConfig = new AutoTileConfig();
  187. _dungeonTileMap = new DungeonTileMap(World.TileRoot);
  188. _dungeonTileMap.AutoFillRoomTile(_autoTileConfig, _dungeonGenerator.StartRoomInfo, _dungeonGenerator.Random);
  189. yield return 0;
  190. //生成寻路网格, 这一步操作只生成过道的导航
  191. _dungeonTileMap.GenerateNavigationPolygon(GameConfig.AisleFloorMapLayer);
  192. yield return 0;
  193. //挂载过道导航区域
  194. _dungeonTileMap.MountNavigationPolygon(World.TileRoot);
  195. yield return 0;
  196. //过道导航区域数据
  197. _roomStaticNavigationList = new List<NavigationPolygonData>();
  198. _roomStaticNavigationList.AddRange(_dungeonTileMap.GetPolygonData());
  199. yield return 0;
  200. //门导航区域数据
  201. _roomStaticNavigationList.AddRange(_dungeonTileMap.GetConnectDoorPolygonData());
  202. yield return 0;
  203. //初始化所有房间
  204. yield return _dungeonGenerator.EachRoomCoroutine(InitRoom);
  205. yield return 0;
  206.  
  207. //播放bgm
  208. //SoundManager.PlayMusic(ResourcePath.resource_sound_bgm_Intro_ogg, -17f);
  209.  
  210. //地牢加载即将完成
  211. yield return _dungeonGenerator.EachRoomCoroutine(info => info.OnReady());
  212. //初始房间创建玩家标记
  213. var playerBirthMark = StartRoomInfo.RoomPreinstall.GetPlayerBirthMark();
  214. //创建玩家
  215. var player = ActivityObject.Create<Player>(ActivityObject.Ids.Id_role0001);
  216. if (playerBirthMark != null)
  217. {
  218. //player.Position = new Vector2(50, 50);
  219. player.Position = playerBirthMark.Position;
  220. }
  221. player.Name = "Player";
  222. player.PutDown(RoomLayerEnum.YSortLayer);
  223. Player.SetCurrentPlayer(player);
  224. yield return 0;
  225.  
  226. //玩家手上添加武器
  227. //player.PickUpWeapon(ActivityObject.Create<Weapon>(ActivityObject.Ids.Id_weapon0001));
  228. // var weapon = ActivityObject.Create<Weapon>(ActivityObject.Ids.Id_weapon0001);
  229. // weapon.PutDown(player.Position, RoomLayerEnum.NormalLayer);
  230. // var weapon2 = ActivityObject.Create<Weapon>(ActivityObject.Ids.Id_weapon0002);
  231. // weapon2.PutDown(player.Position, RoomLayerEnum.NormalLayer);
  232. // var weapon3 = ActivityObject.Create<Weapon>(ActivityObject.Ids.Id_weapon0003);
  233. // weapon3.PutDown(player.Position, RoomLayerEnum.NormalLayer);
  234. // var weapon4 = ActivityObject.Create<Weapon>(ActivityObject.Ids.Id_weapon0004);
  235. // weapon4.PutDown(player.Position, RoomLayerEnum.NormalLayer);
  236.  
  237. GameApplication.Instance.Cursor.SetGuiMode(false);
  238. yield return 0;
  239. //打开游戏中的ui
  240. UiManager.Open_RoomUI();
  241. //派发进入地牢事件
  242. EventManager.EmitEvent(EventEnum.OnEnterDungeon);
  243. IsInDungeon = true;
  244. QueueRedraw();
  245. yield return 0;
  246. //关闭 loading UI
  247. UiManager.Destroy_Loading();
  248. if (finish != null)
  249. {
  250. finish();
  251. }
  252. }
  253.  
  254. //执行退出地牢流程
  255. private IEnumerator RunExitDungeonCoroutine(Action finish)
  256. {
  257. //打开 loading UI
  258. UiManager.Open_Loading();
  259. yield return 0;
  260. World.Pause = true;
  261. yield return 0;
  262. _dungeonGenerator.EachRoom(DisposeRoomInfo);
  263. yield return 0;
  264. _dungeonTileMap = null;
  265. _autoTileConfig = null;
  266. _dungeonGenerator = null;
  267. _roomStaticNavigationList.Clear();
  268. _roomStaticNavigationList = null;
  269. UiManager.Hide_RoomUI();
  270. yield return 0;
  271. Player.SetCurrentPlayer(null);
  272. World = null;
  273. GameApplication.Instance.DestroyWorld();
  274. yield return 0;
  275. QueueRedraw();
  276. //鼠标还原
  277. GameApplication.Instance.Cursor.SetGuiMode(true);
  278. //派发退出地牢事件
  279. EventManager.EmitEvent(EventEnum.OnExitDungeon);
  280. yield return 0;
  281. //关闭 loading UI
  282. UiManager.Destroy_Loading();
  283. if (finish != null)
  284. {
  285. finish();
  286. }
  287. }
  288. // 初始化房间
  289. private void InitRoom(RoomInfo roomInfo)
  290. {
  291. //挂载房间导航区域
  292. MountNavFromRoomInfo(roomInfo);
  293. //创建门
  294. CreateDoor(roomInfo);
  295. //创建房间归属区域
  296. CreateRoomAffiliation(roomInfo);
  297. //创建静态精灵画布
  298. CreateRoomStaticSpriteCanvas(roomInfo);
  299. //创建迷雾遮罩
  300. }
  301. //挂载房间导航区域
  302. private void MountNavFromRoomInfo(RoomInfo roomInfo)
  303. {
  304. var polygonArray = roomInfo.RoomSplit.TileInfo.NavigationList;
  305. var polygon = new NavigationPolygon();
  306. var offset = roomInfo.GetOffsetPosition();
  307. for (var i = 0; i < polygonArray.Count; i++)
  308. {
  309. var navigationPolygonData = polygonArray[i];
  310. var tempPosArray = navigationPolygonData.GetPoints();
  311. var polygonPointArray = new Vector2[tempPosArray.Length];
  312. //这里的位置需要加上房间位置
  313. for (var j = 0; j < tempPosArray.Length; j++)
  314. {
  315. polygonPointArray[j] = tempPosArray[j] + roomInfo.GetWorldPosition() - offset;
  316. }
  317. polygon.AddOutline(polygonPointArray);
  318.  
  319. //存入汇总列表
  320. var polygonData = new NavigationPolygonData(navigationPolygonData.Type);
  321. polygonData.SetPoints(polygonPointArray);
  322. _roomStaticNavigationList.Add(polygonData);
  323. }
  324. polygon.MakePolygonsFromOutlines();
  325. var navigationPolygon = new NavigationRegion2D();
  326. navigationPolygon.Name = "NavigationRegion" + (GetChildCount() + 1);
  327. navigationPolygon.NavigationPolygon = polygon;
  328. World.TileRoot.AddChild(navigationPolygon);
  329. }
  330.  
  331. //创建门
  332. private void CreateDoor(RoomInfo roomInfo)
  333. {
  334. foreach (var doorInfo in roomInfo.Doors)
  335. {
  336. RoomDoor door;
  337. switch (doorInfo.Direction)
  338. {
  339. case DoorDirection.E:
  340. door = ActivityObject.Create<RoomDoor>(ActivityObject.Ids.Id_other_door_e);
  341. door.Position = (doorInfo.OriginPosition + new Vector2(0.5f, 2)) * GameConfig.TileCellSize;
  342. door.ZIndex = GameConfig.TopMapLayer;
  343. break;
  344. case DoorDirection.W:
  345. door = ActivityObject.Create<RoomDoor>(ActivityObject.Ids.Id_other_door_w);
  346. door.Position = (doorInfo.OriginPosition + new Vector2(-0.5f, 2)) * GameConfig.TileCellSize;
  347. door.ZIndex = GameConfig.TopMapLayer;
  348. break;
  349. case DoorDirection.S:
  350. door = ActivityObject.Create<RoomDoor>(ActivityObject.Ids.Id_other_door_s);
  351. door.Position = (doorInfo.OriginPosition + new Vector2(2f, 1.5f)) * GameConfig.TileCellSize;
  352. door.ZIndex = GameConfig.TopMapLayer;
  353. break;
  354. case DoorDirection.N:
  355. door = ActivityObject.Create<RoomDoor>(ActivityObject.Ids.Id_other_door_n);
  356. door.Position = (doorInfo.OriginPosition + new Vector2(2f, -0.5f)) * GameConfig.TileCellSize;
  357. door.ZIndex = GameConfig.MiddleMapLayer;
  358. break;
  359. default:
  360. return;
  361. }
  362. doorInfo.Door = door;
  363. door.Init(doorInfo);
  364. door.PutDown(RoomLayerEnum.NormalLayer, false);
  365. }
  366. }
  367.  
  368. //创建房间归属区域
  369. private void CreateRoomAffiliation(RoomInfo roomInfo)
  370. {
  371. var affiliation = new AffiliationArea();
  372. affiliation.Name = "AffiliationArea" + roomInfo.Id;
  373. affiliation.Init(roomInfo, new Rect2(
  374. roomInfo.GetWorldPosition() + new Vector2(GameConfig.TileCellSize, GameConfig.TileCellSize),
  375. (roomInfo.Size - new Vector2I(2, 2)) * GameConfig.TileCellSize));
  376. roomInfo.AffiliationArea = affiliation;
  377. World.AffiliationAreaRoot.AddChild(affiliation);
  378. }
  379.  
  380. //创建静态精灵画布
  381. private void CreateRoomStaticSpriteCanvas(RoomInfo roomInfo)
  382. {
  383. var worldPos = roomInfo.GetWorldPosition();
  384. var pos = new Vector2I((int)worldPos.X, (int)worldPos.Y);
  385. int minX = pos.X;
  386. int minY = pos.Y;
  387. int maxX = minX + roomInfo.GetWidth();
  388. int maxY = minY + roomInfo.GetHeight();
  389.  
  390. //遍历每一个连接的门, 计算计算canvas覆盖范围
  391. foreach (var doorInfo in roomInfo.Doors)
  392. {
  393. var connectDoor = doorInfo.ConnectDoor;
  394. switch (connectDoor.Direction)
  395. {
  396. case DoorDirection.E:
  397. case DoorDirection.W:
  398. {
  399. var (px1, py1) = connectDoor.GetWorldOriginPosition();
  400. var py2 = py1 + 4 * GameConfig.TileCellSize;
  401. if (px1 < minX)
  402. {
  403. minX = px1;
  404. }
  405. else if (px1 > maxX)
  406. {
  407. maxX = px1;
  408. }
  409.  
  410. if (py1 < minY)
  411. {
  412. minY = py1;
  413. }
  414. else if (py1 > maxY)
  415. {
  416. maxY = py1;
  417. }
  418. if (py2 < minY)
  419. {
  420. minY = py2;
  421. }
  422. else if (py2 > maxY)
  423. {
  424. maxY = py2;
  425. }
  426. }
  427. break;
  428. case DoorDirection.S:
  429. case DoorDirection.N:
  430. {
  431. var (px1, py1) = connectDoor.GetWorldOriginPosition();
  432. var px2 = px1 + 4 * GameConfig.TileCellSize;
  433. if (px1 < minX)
  434. {
  435. minX = px1;
  436. }
  437. else if (px1 > maxX)
  438. {
  439. maxX = px1;
  440. }
  441.  
  442. if (py1 < minY)
  443. {
  444. minY = py1;
  445. }
  446. else if (py1 > maxY)
  447. {
  448. maxY = py1;
  449. }
  450. if (px2 < minX)
  451. {
  452. minX = px2;
  453. }
  454. else if (px2 > maxX)
  455. {
  456. maxX = px2;
  457. }
  458. }
  459. break;
  460. }
  461. }
  462.  
  463. minX -= GameConfig.TileCellSize;
  464. minY -= GameConfig.TileCellSize;
  465. maxX += GameConfig.TileCellSize;
  466. maxY += GameConfig.TileCellSize;
  467. var staticSpriteCanvas = new RoomStaticImageCanvas(
  468. World.StaticSpriteRoot,
  469. new Vector2I(minX, minY),
  470. maxX - minX, maxY - minY
  471. );
  472. staticSpriteCanvas.RoomOffset = new Vector2I(worldPos.X - minX, worldPos.Y - minY);
  473. roomInfo.StaticImageCanvas = staticSpriteCanvas;
  474. }
  475.  
  476. /// <summary>
  477. /// 玩家第一次进入某个房间回调
  478. /// </summary>
  479. private void OnPlayerFirstEnterRoom(object o)
  480. {
  481. var room = (RoomInfo)o;
  482. room.OnFirstEnter();
  483. //如果关门了, 那么房间外的敌人就会丢失目标
  484. if (room.IsSeclusion)
  485. {
  486. var playerAffiliationArea = Player.Current.AffiliationArea;
  487. foreach (var enemy in World.Enemy_InstanceList)
  488. {
  489. //不与玩家处于同一个房间
  490. if (enemy.AffiliationArea != playerAffiliationArea)
  491. {
  492. if (enemy.StateController.CurrState != AiStateEnum.AiNormal)
  493. {
  494. enemy.StateController.ChangeState(AiStateEnum.AiNormal);
  495. }
  496. }
  497. }
  498. }
  499. }
  500.  
  501. /// <summary>
  502. /// 玩家进入某个房间回调
  503. /// </summary>
  504. private void OnPlayerEnterRoom(object o)
  505. {
  506. }
  507. /// <summary>
  508. /// 检测当前房间敌人是否已经消灭干净, 应当每秒执行一次
  509. /// </summary>
  510. private void OnCheckEnemy()
  511. {
  512. var activeRoom = ActiveRoomInfo;
  513. if (activeRoom != null)
  514. {
  515. if (activeRoom.RoomPreinstall.IsRunWave) //正在生成标记
  516. {
  517. if (activeRoom.RoomPreinstall.IsCurrWaveOver()) //所有标记执行完成
  518. {
  519. //房间内是否有存活的敌人
  520. var flag = ActiveAffiliationArea.ExistEnterItem(
  521. activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy)
  522. );
  523. //GD.Print("当前房间存活数量: " + count);
  524. if (!flag)
  525. {
  526. activeRoom.OnClearRoom();
  527. }
  528. }
  529. }
  530. }
  531. }
  532.  
  533. /// <summary>
  534. /// 更新敌人视野
  535. /// </summary>
  536. private void UpdateEnemiesView()
  537. {
  538. World.Enemy_IsFindTarget = false;
  539. World.Enemy_FindTargetAffiliationSet.Clear();
  540. for (var i = 0; i < World.Enemy_InstanceList.Count; i++)
  541. {
  542. var enemy = World.Enemy_InstanceList[i];
  543. var state = enemy.StateController.CurrState;
  544. if (state == AiStateEnum.AiFollowUp || state == AiStateEnum.AiSurround) //目标在视野内
  545. {
  546. if (!World.Enemy_IsFindTarget)
  547. {
  548. World.Enemy_IsFindTarget = true;
  549. World.Enemy_FindTargetPosition = Player.Current.GetCenterPosition();
  550. World.Enemy_FindTargetAffiliationSet.Add(Player.Current.AffiliationArea);
  551. }
  552. World.Enemy_FindTargetAffiliationSet.Add(enemy.AffiliationArea);
  553. }
  554. }
  555. }
  556.  
  557. private void DisposeRoomInfo(RoomInfo roomInfo)
  558. {
  559. roomInfo.Destroy();
  560. }
  561. public override void _Draw()
  562. {
  563. if (GameApplication.Instance.Debug)
  564. {
  565. if (_dungeonTileMap != null)
  566. {
  567. //绘制ai寻路区域
  568. Utils.DrawNavigationPolygon(this, _roomStaticNavigationList.ToArray());
  569. }
  570. //绘制房间区域
  571. // if (_dungeonGenerator != null)
  572. // {
  573. // DrawRoomInfo(StartRoom);
  574. // }
  575. //绘制边缘线
  576. }
  577. }
  578. //绘制房间区域, debug 用
  579. private void DrawRoomInfo(RoomInfo roomInfo)
  580. {
  581. var cellSize = GameConfig.TileCellSize;
  582. var pos1 = (roomInfo.Position + roomInfo.Size / 2) * cellSize;
  583. //绘制下一个房间
  584. foreach (var nextRoom in roomInfo.Next)
  585. {
  586. var pos2 = (nextRoom.Position + nextRoom.Size / 2) * cellSize;
  587. DrawLine(pos1, pos2, Colors.Red);
  588. DrawRoomInfo(nextRoom);
  589. }
  590.  
  591. DrawString(ResourceManager.DefaultFont16Px, pos1 - new Vector2I(0, 10), "Id: " + roomInfo.Id.ToString());
  592. DrawString(ResourceManager.DefaultFont16Px, pos1 + new Vector2I(0, 10), "Layer: " + roomInfo.Layer.ToString());
  593.  
  594. //绘制门
  595. foreach (var roomDoor in roomInfo.Doors)
  596. {
  597. var originPos = roomDoor.OriginPosition * cellSize;
  598. switch (roomDoor.Direction)
  599. {
  600. case DoorDirection.E:
  601. DrawLine(originPos, originPos + new Vector2(3, 0) * cellSize, Colors.Yellow);
  602. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos + new Vector2(3, 4) * cellSize,
  603. Colors.Yellow);
  604. break;
  605. case DoorDirection.W:
  606. DrawLine(originPos, originPos - new Vector2(3, 0) * cellSize, Colors.Yellow);
  607. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos - new Vector2(3, -4) * cellSize,
  608. Colors.Yellow);
  609. break;
  610. case DoorDirection.S:
  611. DrawLine(originPos, originPos + new Vector2(0, 3) * cellSize, Colors.Yellow);
  612. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos + new Vector2(4, 3) * cellSize,
  613. Colors.Yellow);
  614. break;
  615. case DoorDirection.N:
  616. DrawLine(originPos, originPos - new Vector2(0, 3) * cellSize, Colors.Yellow);
  617. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos - new Vector2(-4, 3) * cellSize,
  618. Colors.Yellow);
  619. break;
  620. }
  621. //绘制房间区域
  622. DrawRect(new Rect2(roomInfo.Position * cellSize, roomInfo.Size * cellSize), Colors.Blue, false);
  623.  
  624. if (roomDoor.HasCross && roomDoor.RoomInfo.Id < roomDoor.ConnectRoom.Id)
  625. {
  626. DrawRect(new Rect2(roomDoor.Cross * cellSize, new Vector2(cellSize * 4, cellSize * 4)), Colors.Yellow, false);
  627. }
  628. }
  629. }
  630. /// <summary>
  631. /// 将房间类型枚举转为字符串
  632. /// </summary>
  633. public static string DungeonRoomTypeToString(DungeonRoomType roomType)
  634. {
  635. switch (roomType)
  636. {
  637. case DungeonRoomType.Battle: return "battle";
  638. case DungeonRoomType.Inlet: return "inlet";
  639. case DungeonRoomType.Outlet: return "outlet";
  640. case DungeonRoomType.Boss: return "boss";
  641. case DungeonRoomType.Reward: return "reward";
  642. case DungeonRoomType.Shop: return "shop";
  643. case DungeonRoomType.Event: return "event";
  644. }
  645.  
  646. return "battle";
  647. }
  648. /// <summary>
  649. /// 将房间类型枚举转为描述字符串
  650. /// </summary>
  651. public static string DungeonRoomTypeToDescribeString(DungeonRoomType roomType)
  652. {
  653. switch (roomType)
  654. {
  655. case DungeonRoomType.Battle: return "战斗房间";
  656. case DungeonRoomType.Inlet: return "起始房间";
  657. case DungeonRoomType.Outlet: return "结束房间";
  658. case DungeonRoomType.Boss: return "Boss房间";
  659. case DungeonRoomType.Reward: return "奖励房间";
  660. case DungeonRoomType.Shop: return "商店房间";
  661. case DungeonRoomType.Event: return "事件房间";
  662. }
  663.  
  664. return "战斗房间";
  665. }
  666.  
  667. /// <summary>
  668. /// 检测地牢是否可以执行生成
  669. /// </summary>
  670. /// <param name="groupName">组名称</param>
  671. public static DungeonCheckState CheckDungeon(string groupName)
  672. {
  673. if (GameApplication.Instance.RoomConfig.TryGetValue(groupName, out var group))
  674. {
  675. //验证该组是否满足生成地牢的条件
  676. if (group.InletList.Count == 0)
  677. {
  678. return new DungeonCheckState(true, "当没有可用的起始房间!");
  679. }
  680. else if (group.OutletList.Count == 0)
  681. {
  682. return new DungeonCheckState(true, "没有可用的结束房间!");
  683. }
  684. else if (group.BattleList.Count == 0)
  685. {
  686. return new DungeonCheckState(true, "没有可用的战斗房间!");
  687. }
  688.  
  689. return new DungeonCheckState(false, null);
  690. }
  691.  
  692. return new DungeonCheckState(true, "未找到地牢组");
  693. }
  694. }