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