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