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