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.  
  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 (ActivityObject.IsDebug)
  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. //创建 RoomStaticSprite
  307. CreateRoomStaticSprite(roomInfo);
  308. //创建静态精灵画布
  309. CreateRoomStaticSpriteCanvas(roomInfo);
  310. //创建迷雾遮罩
  311. CreateRoomFogMask(roomInfo);
  312. }
  313. //挂载房间导航区域
  314. private void MountNavFromRoomInfo(RoomInfo roomInfo)
  315. {
  316. var polygonArray = roomInfo.RoomSplit.TileInfo.NavigationList;
  317. var polygon = new NavigationPolygon();
  318. var offset = roomInfo.GetOffsetPosition();
  319. for (var i = 0; i < polygonArray.Count; i++)
  320. {
  321. var navigationPolygonData = polygonArray[i];
  322. var tempPosArray = navigationPolygonData.GetPoints();
  323. var polygonPointArray = new Vector2[tempPosArray.Length];
  324. //这里的位置需要加上房间位置
  325. for (var j = 0; j < tempPosArray.Length; j++)
  326. {
  327. polygonPointArray[j] = tempPosArray[j] + roomInfo.GetWorldPosition() - offset;
  328. }
  329. polygon.AddOutline(polygonPointArray);
  330.  
  331. //存入汇总列表
  332. var polygonData = new NavigationPolygonData(navigationPolygonData.Type);
  333. polygonData.SetPoints(polygonPointArray);
  334. _roomStaticNavigationList.Add(polygonData);
  335. }
  336. polygon.MakePolygonsFromOutlines();
  337. var navigationPolygon = new NavigationRegion2D();
  338. navigationPolygon.Name = "NavigationRegion" + (GetChildCount() + 1);
  339. navigationPolygon.NavigationPolygon = polygon;
  340. World.TileRoot.AddChild(navigationPolygon);
  341. }
  342.  
  343. //创建门
  344. private void CreateDoor(RoomInfo roomInfo)
  345. {
  346. foreach (var doorInfo in roomInfo.Doors)
  347. {
  348. RoomDoor door;
  349. switch (doorInfo.Direction)
  350. {
  351. case DoorDirection.E:
  352. door = ActivityObject.Create<RoomDoor>(ActivityObject.Ids.Id_other_door_e);
  353. door.Position = (doorInfo.OriginPosition + new Vector2(0.5f, 2)) * GameConfig.TileCellSize;
  354. door.ZIndex = GameConfig.TopMapLayer;
  355. break;
  356. case DoorDirection.W:
  357. door = ActivityObject.Create<RoomDoor>(ActivityObject.Ids.Id_other_door_w);
  358. door.Position = (doorInfo.OriginPosition + new Vector2(-0.5f, 2)) * GameConfig.TileCellSize;
  359. door.ZIndex = GameConfig.TopMapLayer;
  360. break;
  361. case DoorDirection.S:
  362. door = ActivityObject.Create<RoomDoor>(ActivityObject.Ids.Id_other_door_s);
  363. door.Position = (doorInfo.OriginPosition + new Vector2(2f, 1.5f)) * GameConfig.TileCellSize;
  364. door.ZIndex = GameConfig.TopMapLayer;
  365. break;
  366. case DoorDirection.N:
  367. door = ActivityObject.Create<RoomDoor>(ActivityObject.Ids.Id_other_door_n);
  368. door.Position = (doorInfo.OriginPosition + new Vector2(2f, -0.5f)) * GameConfig.TileCellSize;
  369. door.ZIndex = GameConfig.MiddleMapLayer;
  370. break;
  371. default:
  372. return;
  373. }
  374. doorInfo.Door = door;
  375. door.Init(doorInfo);
  376. door.PutDown(RoomLayerEnum.NormalLayer, false);
  377. }
  378. }
  379.  
  380. //创建房间归属区域
  381. private void CreateRoomAffiliation(RoomInfo roomInfo)
  382. {
  383. var affiliation = new AffiliationArea();
  384. affiliation.Name = "AffiliationArea" + roomInfo.Id;
  385. affiliation.Init(roomInfo, new Rect2I(
  386. roomInfo.GetWorldPosition() + GameConfig.TileCellSizeVector2I,
  387. (roomInfo.Size - new Vector2I(2, 2)) * GameConfig.TileCellSize));
  388. roomInfo.AffiliationArea = affiliation;
  389. World.AffiliationAreaRoot.AddChild(affiliation);
  390. }
  391.  
  392. //创建 RoomStaticSprite
  393. private void CreateRoomStaticSprite(RoomInfo roomInfo)
  394. {
  395. var spriteRoot = new RoomStaticSprite(roomInfo);
  396. spriteRoot.Name = "SpriteRoot";
  397. World.Current.StaticSpriteRoot.AddChild(spriteRoot);
  398. roomInfo.StaticSprite = spriteRoot;
  399. }
  400.  
  401. //创建静态精灵画布
  402. private void CreateRoomStaticSpriteCanvas(RoomInfo roomInfo)
  403. {
  404. var worldPos = roomInfo.GetWorldPosition();
  405. var rect = roomInfo.OuterRange;
  406.  
  407. var minX = rect.Position.X - GameConfig.TileCellSize;
  408. var minY = rect.Position.Y - GameConfig.TileCellSize;
  409. var maxX = rect.End.X + GameConfig.TileCellSize;
  410. var maxY = rect.End.Y + GameConfig.TileCellSize;
  411.  
  412. var canvasSprite = new ImageCanvas(maxX - minX, maxY - minY);
  413. canvasSprite.Position = new Vector2I(minX, minY);
  414. roomInfo.RoomOffset = new Vector2I(worldPos.X - minX, worldPos.Y - minY);
  415. roomInfo.StaticImageCanvas = canvasSprite;
  416. roomInfo.StaticSprite.AddChild(canvasSprite);
  417. }
  418.  
  419. //创建迷雾遮罩
  420. private void CreateRoomFogMask(RoomInfo roomInfo)
  421. {
  422. var roomFog = new FogMask();
  423. roomFog.Name = "FogMask" + roomFog.IsDestroyed;
  424. roomFog.InitFog(roomInfo.Position, roomInfo.Size);
  425.  
  426. World.FogMaskRoot.AddChild(roomFog);
  427. roomInfo.RoomFogMask = roomFog;
  428. //生成通道迷雾
  429. foreach (var roomDoorInfo in roomInfo.Doors)
  430. {
  431. //必须是正向门
  432. if (roomDoorInfo.IsForward)
  433. {
  434. Rect2I calcRect;
  435. Rect2I fogAreaRect;
  436. if (!roomDoorInfo.HasCross)
  437. {
  438. calcRect = roomDoorInfo.GetAisleRect();
  439. fogAreaRect = calcRect;
  440. if (roomDoorInfo.Direction == DoorDirection.E || roomDoorInfo.Direction == DoorDirection.W)
  441. {
  442. calcRect.Position += new Vector2I(2, 0);
  443. calcRect.Size -= new Vector2I(4, 0);
  444. }
  445. else
  446. {
  447. calcRect.Position += new Vector2I(0, 2);
  448. calcRect.Size -= new Vector2I(0, 4);
  449. }
  450. }
  451. else
  452. {
  453. var aisleRect = roomDoorInfo.GetCrossAisleRect();
  454. calcRect = aisleRect.CalcAisleRect();
  455. fogAreaRect = calcRect;
  456.  
  457. switch (roomDoorInfo.Direction)
  458. {
  459. case DoorDirection.E:
  460. calcRect.Position += new Vector2I(2, 0);
  461. calcRect.Size -= new Vector2I(2, 0);
  462. break;
  463. case DoorDirection.W:
  464. calcRect.Size -= new Vector2I(2, 0);
  465. break;
  466. case DoorDirection.S:
  467. calcRect.Position += new Vector2I(0, 2);
  468. calcRect.Size -= new Vector2I(0, 2);
  469. break;
  470. case DoorDirection.N:
  471. calcRect.Size -= new Vector2I(0, 2);
  472. break;
  473. }
  474.  
  475. switch (roomDoorInfo.ConnectDoor.Direction)
  476. {
  477. case DoorDirection.E:
  478. calcRect.Position += new Vector2I(2, 0);
  479. calcRect.Size -= new Vector2I(2, 0);
  480. break;
  481. case DoorDirection.W:
  482. calcRect.Size -= new Vector2I(2, 0);
  483. break;
  484. case DoorDirection.S:
  485. calcRect.Position += new Vector2I(0, 2);
  486. calcRect.Size -= new Vector2I(0, 2);
  487. break;
  488. case DoorDirection.N:
  489. calcRect.Size -= new Vector2I(0, 2);
  490. break;
  491. }
  492. }
  493.  
  494. //过道迷雾遮罩
  495. var aisleFog = new FogMask();
  496. aisleFog.InitFog(calcRect.Position, calcRect.Size);
  497. World.FogMaskRoot.AddChild(aisleFog);
  498. roomDoorInfo.AisleFogMask = aisleFog;
  499. roomDoorInfo.ConnectDoor.AisleFogMask = aisleFog;
  500.  
  501. //过道迷雾区域
  502. var fogArea = new AisleFogArea();
  503. fogArea.Init(roomDoorInfo,
  504. new Rect2I(
  505. fogAreaRect.Position * GameConfig.TileCellSize,
  506. fogAreaRect.Size * GameConfig.TileCellSize
  507. )
  508. );
  509. roomDoorInfo.AisleFogArea = fogArea;
  510. roomDoorInfo.ConnectDoor.AisleFogArea = fogArea;
  511. World.AffiliationAreaRoot.AddChild(fogArea);
  512. }
  513.  
  514. //预览迷雾区域
  515. var previewRoomFog = new PreviewFogMask();
  516. roomDoorInfo.PreviewRoomFogMask = previewRoomFog;
  517. previewRoomFog.Init(roomDoorInfo, PreviewFogMask.PreviewFogType.Room);
  518. previewRoomFog.SetActive(false);
  519. World.FogMaskRoot.AddChild(previewRoomFog);
  520. var previewAisleFog = new PreviewFogMask();
  521. roomDoorInfo.PreviewAisleFogMask = previewAisleFog;
  522. previewAisleFog.Init(roomDoorInfo, PreviewFogMask.PreviewFogType.Aisle);
  523. previewAisleFog.SetActive(false);
  524. World.FogMaskRoot.AddChild(previewAisleFog);
  525. }
  526. }
  527.  
  528. /// <summary>
  529. /// 玩家第一次进入某个房间回调
  530. /// </summary>
  531. private void OnPlayerFirstEnterRoom(object o)
  532. {
  533. var room = (RoomInfo)o;
  534. room.OnFirstEnter();
  535. //如果关门了, 那么房间外的敌人就会丢失目标
  536. if (room.IsSeclusion)
  537. {
  538. var playerAffiliationArea = Player.Current.AffiliationArea;
  539. foreach (var enemy in World.Enemy_InstanceList)
  540. {
  541. //不与玩家处于同一个房间
  542. if (enemy.AffiliationArea != playerAffiliationArea)
  543. {
  544. if (enemy.StateController.CurrState != AiStateEnum.AiNormal)
  545. {
  546. enemy.StateController.ChangeState(AiStateEnum.AiNormal);
  547. }
  548. }
  549. }
  550. }
  551. }
  552.  
  553. /// <summary>
  554. /// 玩家进入某个房间回调
  555. /// </summary>
  556. private void OnPlayerEnterRoom(object o)
  557. {
  558. var roomInfo = (RoomInfo)o;
  559. if (_affiliationAreaFlag != roomInfo.AffiliationArea)
  560. {
  561. if (!roomInfo.AffiliationArea.IsDestroyed)
  562. {
  563. //刷新迷雾
  564. FogMaskHandler.RefreshRoomFog(roomInfo);
  565. }
  566.  
  567. _affiliationAreaFlag = roomInfo.AffiliationArea;
  568. }
  569. }
  570. /// <summary>
  571. /// 检测当前房间敌人是否已经消灭干净, 应当每秒执行一次
  572. /// </summary>
  573. private void OnCheckEnemy()
  574. {
  575. var activeRoom = ActiveRoomInfo;
  576. if (activeRoom != null)
  577. {
  578. if (activeRoom.RoomPreinstall.IsRunWave) //正在生成标记
  579. {
  580. if (activeRoom.RoomPreinstall.IsCurrWaveOver()) //所有标记执行完成
  581. {
  582. //房间内是否有存活的敌人
  583. var flag = ActiveAffiliationArea.ExistEnterItem(
  584. activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy)
  585. );
  586. //Debug.Log("当前房间存活数量: " + count);
  587. if (!flag)
  588. {
  589. activeRoom.OnClearRoom();
  590. }
  591. }
  592. }
  593. }
  594. }
  595.  
  596. /// <summary>
  597. /// 更新敌人视野
  598. /// </summary>
  599. private void UpdateEnemiesView()
  600. {
  601. World.Enemy_IsFindTarget = false;
  602. World.Enemy_FindTargetAffiliationSet.Clear();
  603. for (var i = 0; i < World.Enemy_InstanceList.Count; i++)
  604. {
  605. var enemy = World.Enemy_InstanceList[i];
  606. var state = enemy.StateController.CurrState;
  607. if (state == AiStateEnum.AiFollowUp || state == AiStateEnum.AiSurround) //目标在视野内
  608. {
  609. if (!World.Enemy_IsFindTarget)
  610. {
  611. World.Enemy_IsFindTarget = true;
  612. World.Enemy_FindTargetPosition = Player.Current.GetCenterPosition();
  613. World.Enemy_FindTargetAffiliationSet.Add(Player.Current.AffiliationArea);
  614. }
  615. World.Enemy_FindTargetAffiliationSet.Add(enemy.AffiliationArea);
  616. }
  617. }
  618. }
  619.  
  620. private void DisposeRoomInfo(RoomInfo roomInfo)
  621. {
  622. roomInfo.Destroy();
  623. }
  624. public override void _Draw()
  625. {
  626. if (ActivityObject.IsDebug)
  627. {
  628. if (_dungeonTileMap != null && _roomStaticNavigationList != null)
  629. {
  630. //绘制ai寻路区域
  631. Utils.DrawNavigationPolygon(this, _roomStaticNavigationList.ToArray());
  632. }
  633. //绘制房间区域
  634. // if (_dungeonGenerator != null)
  635. // {
  636. // DrawRoomInfo(StartRoom);
  637. // }
  638. //绘制边缘线
  639. }
  640. }
  641. //绘制房间区域, debug 用
  642. private void DrawRoomInfo(RoomInfo roomInfo)
  643. {
  644. var cellSize = GameConfig.TileCellSize;
  645. var pos1 = (roomInfo.Position + roomInfo.Size / 2) * cellSize;
  646. //绘制下一个房间
  647. foreach (var nextRoom in roomInfo.Next)
  648. {
  649. var pos2 = (nextRoom.Position + nextRoom.Size / 2) * cellSize;
  650. DrawLine(pos1, pos2, Colors.Red);
  651. DrawRoomInfo(nextRoom);
  652. }
  653.  
  654. DrawString(ResourceManager.DefaultFont16Px, pos1 - new Vector2I(0, 10), "Id: " + roomInfo.Id.ToString());
  655. DrawString(ResourceManager.DefaultFont16Px, pos1 + new Vector2I(0, 10), "Layer: " + roomInfo.Layer.ToString());
  656.  
  657. //绘制门
  658. foreach (var roomDoor in roomInfo.Doors)
  659. {
  660. var originPos = roomDoor.OriginPosition * cellSize;
  661. switch (roomDoor.Direction)
  662. {
  663. case DoorDirection.E:
  664. DrawLine(originPos, originPos + new Vector2(3, 0) * cellSize, Colors.Yellow);
  665. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos + new Vector2(3, 4) * cellSize,
  666. Colors.Yellow);
  667. break;
  668. case DoorDirection.W:
  669. DrawLine(originPos, originPos - new Vector2(3, 0) * cellSize, Colors.Yellow);
  670. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos - new Vector2(3, -4) * cellSize,
  671. Colors.Yellow);
  672. break;
  673. case DoorDirection.S:
  674. DrawLine(originPos, originPos + new Vector2(0, 3) * cellSize, Colors.Yellow);
  675. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos + new Vector2(4, 3) * cellSize,
  676. Colors.Yellow);
  677. break;
  678. case DoorDirection.N:
  679. DrawLine(originPos, originPos - new Vector2(0, 3) * cellSize, Colors.Yellow);
  680. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos - new Vector2(-4, 3) * cellSize,
  681. Colors.Yellow);
  682. break;
  683. }
  684. //绘制房间区域
  685. DrawRect(new Rect2(roomInfo.Position * cellSize, roomInfo.Size * cellSize), Colors.Blue, false);
  686.  
  687. if (roomDoor.HasCross && roomDoor.RoomInfo.Id < roomDoor.ConnectRoom.Id)
  688. {
  689. DrawRect(new Rect2(roomDoor.Cross * cellSize, new Vector2(cellSize * 4, cellSize * 4)), Colors.Yellow, false);
  690. }
  691. }
  692. }
  693. /// <summary>
  694. /// 将房间类型枚举转为字符串
  695. /// </summary>
  696. public static string DungeonRoomTypeToString(DungeonRoomType roomType)
  697. {
  698. switch (roomType)
  699. {
  700. case DungeonRoomType.Battle: return "battle";
  701. case DungeonRoomType.Inlet: return "inlet";
  702. case DungeonRoomType.Outlet: return "outlet";
  703. case DungeonRoomType.Boss: return "boss";
  704. case DungeonRoomType.Reward: return "reward";
  705. case DungeonRoomType.Shop: return "shop";
  706. case DungeonRoomType.Event: return "event";
  707. }
  708.  
  709. return "battle";
  710. }
  711. /// <summary>
  712. /// 将房间类型枚举转为描述字符串
  713. /// </summary>
  714. public static string DungeonRoomTypeToDescribeString(DungeonRoomType roomType)
  715. {
  716. switch (roomType)
  717. {
  718. case DungeonRoomType.Battle: return "战斗房间";
  719. case DungeonRoomType.Inlet: return "起始房间";
  720. case DungeonRoomType.Outlet: return "结束房间";
  721. case DungeonRoomType.Boss: return "Boss房间";
  722. case DungeonRoomType.Reward: return "奖励房间";
  723. case DungeonRoomType.Shop: return "商店房间";
  724. case DungeonRoomType.Event: return "事件房间";
  725. }
  726.  
  727. return "战斗房间";
  728. }
  729.  
  730. /// <summary>
  731. /// 检测地牢是否可以执行生成
  732. /// </summary>
  733. /// <param name="groupName">组名称</param>
  734. public static DungeonCheckState CheckDungeon(string groupName)
  735. {
  736. if (GameApplication.Instance.RoomConfig.TryGetValue(groupName, out var group))
  737. {
  738. //验证该组是否满足生成地牢的条件
  739. if (group.InletList.Count == 0)
  740. {
  741. return new DungeonCheckState(true, "当没有可用的起始房间!");
  742. }
  743. else if (group.OutletList.Count == 0)
  744. {
  745. return new DungeonCheckState(true, "没有可用的结束房间!");
  746. }
  747. else if (group.BattleList.Count == 0)
  748. {
  749. return new DungeonCheckState(true, "没有可用的战斗房间!");
  750. }
  751.  
  752. return new DungeonCheckState(false, null);
  753. }
  754.  
  755. return new DungeonCheckState(true, "未找到地牢组");
  756. }
  757. }