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 System.Linq;
  6. using Godot;
  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.  
  49. private UiBase _prevUi;
  50. private DungeonTileMap _dungeonTileMap;
  51. private DungeonGenerator _dungeonGenerator;
  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 (InputManager.Menu)
  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. var random = new SeedRandom(1);
  186. _dungeonGenerator = new DungeonGenerator(CurrConfig, random);
  187. var rule = new DefaultDungeonRule(_dungeonGenerator);
  188. if (!_dungeonGenerator.Generate(rule)) //生成房间失败
  189. {
  190. _dungeonGenerator.EachRoom(DisposeRoomInfo);
  191. _dungeonGenerator = null;
  192. UiManager.Hide_Loading();
  193. if (IsEditorMode) //在编辑器模式下打开的Ui
  194. {
  195. EditorPlayManager.IsPlay = false;
  196. IsEditorMode = false;
  197. //显示上一个Ui
  198. if (_prevUi != null)
  199. {
  200. _prevUi.ShowUi();
  201. }
  202. }
  203. else //正常关闭Ui
  204. {
  205. UiManager.Open_Main();
  206. }
  207. EditorWindowManager.ShowTips("错误", "生成房间尝试次数过多,生成地牢房间失败,请加大房间门连接区域,或者修改地牢生成规则!");
  208. yield break;
  209. }
  210. yield return 0;
  211. //创建世界场景
  212. World = GameApplication.Instance.CreateNewWorld(random);
  213. yield return 0;
  214. var group = GameApplication.Instance.RoomConfig[CurrConfig.GroupName];
  215. var tileSetSplit = GameApplication.Instance.TileSetConfig[group.TileSet];
  216. World.TileRoot.TileSet = tileSetSplit.GetTileSet();
  217. //填充地牢
  218. AutoTileConfig = new AutoTileConfig(0, tileSetSplit.TileSetInfo.Sources[0].Terrain[0]);
  219. _dungeonTileMap = new DungeonTileMap(World.TileRoot);
  220. yield return _dungeonTileMap.AutoFillRoomTile(AutoTileConfig, _dungeonGenerator.StartRoomInfo, World);
  221. yield return _dungeonTileMap.AutoFillAisleTile(AutoTileConfig, _dungeonGenerator.StartRoomInfo, World);
  222. //yield return _dungeonTileMap.AddOutlineTile(AutoTileConfig.WALL_BLOCK);
  223. yield return 0;
  224. //生成墙壁, 生成导航网格
  225. _dungeonTileMap.GenerateWallAndNavigation(World, AutoTileConfig);
  226. yield return 0;
  227. //初始化所有房间
  228. yield return _dungeonGenerator.EachRoomCoroutine(InitRoom);
  229.  
  230. //播放bgm
  231. //SoundManager.PlayMusic(ResourcePath.resource_sound_bgm_Intro_ogg, -17f);
  232.  
  233. //地牢加载即将完成
  234. yield return _dungeonGenerator.EachRoomCoroutine(info => info.OnReady());
  235. //初始房间创建玩家标记
  236. var playerBirthMark = StartRoomInfo.RoomPreinstall.GetPlayerBirthMark();
  237. //创建玩家
  238. var player = ActivityObject.Create<Player>(ActivityObject.Ids.Id_role0001);
  239. if (playerBirthMark != null)
  240. {
  241. //player.Position = new Vector2(50, 50);
  242. player.Position = playerBirthMark.Position;
  243. }
  244. player.Name = "Player";
  245. player.PutDown(RoomLayerEnum.YSortLayer);
  246. Player.SetCurrentPlayer(player);
  247. GameApplication.Instance.Cursor.SetGuiMode(false);
  248. //打开游戏中的ui
  249. UiManager.Open_RoomUI();
  250. //派发进入地牢事件
  251. EventManager.EmitEvent(EventEnum.OnEnterDungeon);
  252. IsInDungeon = true;
  253. QueueRedraw();
  254. yield return 0;
  255. //关闭 loading UI
  256. UiManager.Destroy_Loading();
  257. if (finish != null)
  258. {
  259. finish();
  260. }
  261. }
  262.  
  263. //执行退出地牢流程
  264. private IEnumerator RunExitDungeonCoroutine(Action finish)
  265. {
  266. //打开 loading UI
  267. UiManager.Open_Loading();
  268. yield return 0;
  269. World.Pause = true;
  270. yield return 0;
  271. _dungeonGenerator.EachRoom(DisposeRoomInfo);
  272. yield return 0;
  273. _dungeonTileMap = null;
  274. AutoTileConfig = null;
  275. _dungeonGenerator = 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. LiquidBrushManager.ClearData();
  284. BrushImageData.ClearBrushData();
  285. QueueRedraw();
  286. //鼠标还原
  287. GameApplication.Instance.Cursor.SetGuiMode(true);
  288. //派发退出地牢事件
  289. EventManager.EmitEvent(EventEnum.OnExitDungeon);
  290. yield return 0;
  291. //关闭 loading UI
  292. UiManager.Destroy_Loading();
  293. if (finish != null)
  294. {
  295. finish();
  296. }
  297. }
  298.  
  299. // 初始化房间
  300. private void InitRoom(RoomInfo roomInfo)
  301. {
  302. roomInfo.CalcRange();
  303. //创建门
  304. CreateDoor(roomInfo);
  305. //创建房间归属区域
  306. CreateRoomAffiliation(roomInfo);
  307. //创建 RoomStaticSprite
  308. CreateRoomStaticSprite(roomInfo);
  309. //创建静态精灵画布
  310. CreateRoomStaticImageCanvas(roomInfo);
  311. //创建液体区域
  312. CreateRoomLiquidCanvas(roomInfo);
  313. //创建迷雾遮罩
  314. CreateRoomFogMask(roomInfo);
  315. //创建房间/过道预览sprite
  316. CreatePreviewSprite(roomInfo);
  317. }
  318.  
  319. //创建门
  320. private void CreateDoor(RoomInfo roomInfo)
  321. {
  322. foreach (var doorInfo in roomInfo.Doors)
  323. {
  324. RoomDoor door;
  325. switch (doorInfo.Direction)
  326. {
  327. case DoorDirection.E:
  328. door = ActivityObject.Create<RoomDoor>(ActivityObject.Ids.Id_other_door_e);
  329. door.Position = (doorInfo.OriginPosition + new Vector2(0.5f, 2)) * GameConfig.TileCellSize;
  330. door.ZIndex = MapLayer.AutoTopLayer;
  331. break;
  332. case DoorDirection.W:
  333. door = ActivityObject.Create<RoomDoor>(ActivityObject.Ids.Id_other_door_w);
  334. door.Position = (doorInfo.OriginPosition + new Vector2(-0.5f, 2)) * GameConfig.TileCellSize;
  335. door.ZIndex = MapLayer.AutoTopLayer;
  336. break;
  337. case DoorDirection.S:
  338. door = ActivityObject.Create<RoomDoor>(ActivityObject.Ids.Id_other_door_s);
  339. door.Position = (doorInfo.OriginPosition + new Vector2(2f, 1.5f)) * GameConfig.TileCellSize;
  340. door.ZIndex = MapLayer.AutoTopLayer;
  341. break;
  342. case DoorDirection.N:
  343. door = ActivityObject.Create<RoomDoor>(ActivityObject.Ids.Id_other_door_n);
  344. door.Position = (doorInfo.OriginPosition + new Vector2(2f, -0.5f)) * GameConfig.TileCellSize;
  345. door.ZIndex = MapLayer.AutoMiddleLayer;
  346. break;
  347. default:
  348. return;
  349. }
  350. doorInfo.Door = door;
  351. door.Init(doorInfo);
  352. door.PutDown(RoomLayerEnum.NormalLayer, false);
  353. }
  354. }
  355.  
  356. //创建房间归属区域
  357. private void CreateRoomAffiliation(RoomInfo roomInfo)
  358. {
  359. var affiliation = new AffiliationArea();
  360. affiliation.Name = "AffiliationArea" + roomInfo.Id;
  361. affiliation.Init(roomInfo, new Rect2I(
  362. roomInfo.GetWorldPosition() + new Vector2I(GameConfig.TileCellSize * 2, GameConfig.TileCellSize * 3),
  363. (roomInfo.Size - new Vector2I(4, 5)) * GameConfig.TileCellSize));
  364. roomInfo.AffiliationArea = affiliation;
  365. World.AffiliationAreaRoot.AddChild(affiliation);
  366. }
  367.  
  368. //创建 RoomStaticSprite
  369. private void CreateRoomStaticSprite(RoomInfo roomInfo)
  370. {
  371. var spriteRoot = new RoomStaticSprite(roomInfo);
  372. spriteRoot.Name = "SpriteRoot";
  373. World.Current.StaticSpriteRoot.AddChild(spriteRoot);
  374. roomInfo.StaticSprite = spriteRoot;
  375. }
  376. //创建液体画布
  377. private void CreateRoomLiquidCanvas(RoomInfo roomInfo)
  378. {
  379. var rect = roomInfo.CanvasRect;
  380.  
  381. var liquidCanvas = new LiquidCanvas(roomInfo, rect.Size.X, rect.Size.Y);
  382. liquidCanvas.Position = rect.Position;
  383. roomInfo.LiquidCanvas = liquidCanvas;
  384. roomInfo.StaticSprite.AddChild(liquidCanvas);
  385. }
  386.  
  387. //创建静态图像画布
  388. private void CreateRoomStaticImageCanvas(RoomInfo roomInfo)
  389. {
  390. var rect = roomInfo.CanvasRect;
  391.  
  392. var canvasSprite = new ImageCanvas(rect.Size.X, rect.Size.Y);
  393. canvasSprite.Position = rect.Position;
  394. roomInfo.StaticImageCanvas = canvasSprite;
  395. roomInfo.StaticSprite.AddChild(canvasSprite);
  396. }
  397.  
  398. //创建迷雾遮罩
  399. private void CreateRoomFogMask(RoomInfo roomInfo)
  400. {
  401. var roomFog = new FogMask();
  402. roomFog.Name = "FogMask" + roomFog.IsDestroyed;
  403. roomFog.InitFog(roomInfo.Position + new Vector2I(1, 0), roomInfo.Size - new Vector2I(2, 1));
  404. //roomFog.InitFog(roomInfo.Position + new Vector2I(1, 1), roomInfo.Size - new Vector2I(2, 2));
  405.  
  406. World.FogMaskRoot.AddChild(roomFog);
  407. roomInfo.RoomFogMask = roomFog;
  408. //生成通道迷雾
  409. foreach (var roomDoorInfo in roomInfo.Doors)
  410. {
  411. //必须是正向门
  412. if (roomDoorInfo.IsForward)
  413. {
  414. Rect2I calcRect;
  415. Rect2I fogAreaRect;
  416. if (!roomDoorInfo.HasCross)
  417. {
  418. calcRect = roomDoorInfo.GetAisleRect();
  419. fogAreaRect = calcRect;
  420. if (roomDoorInfo.Direction == DoorDirection.E || roomDoorInfo.Direction == DoorDirection.W)
  421. {
  422. calcRect.Position += new Vector2I(2, 0);
  423. calcRect.Size -= new Vector2I(4, 0);
  424. }
  425. else
  426. {
  427. calcRect.Position += new Vector2I(0, 2);
  428. calcRect.Size -= new Vector2I(0, 5);
  429. }
  430. }
  431. else
  432. {
  433. var aisleRect = roomDoorInfo.GetCrossAisleRect();
  434. calcRect = aisleRect.CalcAisleRect();
  435. fogAreaRect = calcRect;
  436.  
  437. if (roomDoorInfo.Direction == DoorDirection.E)
  438. {
  439. if (roomDoorInfo.ConnectDoor.Direction == DoorDirection.N) //→↑
  440. {
  441. calcRect.Position += new Vector2I(2, 0);
  442. calcRect.Size -= new Vector2I(2, 4);
  443. }
  444. else //→↓
  445. {
  446. calcRect.Position += new Vector2I(2, 3);
  447. calcRect.Size -= new Vector2I(2, 3);
  448. }
  449. }
  450. else if (roomDoorInfo.Direction == DoorDirection.W)
  451. {
  452. if (roomDoorInfo.ConnectDoor.Direction == DoorDirection.N) //←↑
  453. {
  454. calcRect.Size -= new Vector2I(2, 4);
  455. }
  456. else //←↓
  457. {
  458. calcRect.Position += new Vector2I(0, 3);
  459. calcRect.Size -= new Vector2I(2, 3);
  460. }
  461. }
  462. else if (roomDoorInfo.Direction == DoorDirection.N)
  463. {
  464. if (roomDoorInfo.ConnectDoor.Direction == DoorDirection.E) //↑→
  465. {
  466. calcRect.Position += new Vector2I(2, -1);
  467. calcRect.Size -= new Vector2I(2, 2);
  468. }
  469. else //↑←
  470. {
  471. calcRect.Position += new Vector2I(0, -1);
  472. calcRect.Size -= new Vector2I(2, 2);
  473. }
  474. }
  475. else if (roomDoorInfo.Direction == DoorDirection.S)
  476. {
  477. if (roomDoorInfo.ConnectDoor.Direction == DoorDirection.E) //↓→
  478. {
  479. calcRect.Position += new Vector2I(2, 2);
  480. calcRect.Size -= new Vector2I(2, 1);
  481. }
  482. else //↓←
  483. {
  484. calcRect.Position += new Vector2I(0, 2);
  485. calcRect.Size -= new Vector2I(2, 1);
  486. }
  487. }
  488. }
  489.  
  490. //过道迷雾遮罩
  491. var aisleFog = new FogMask();
  492. var calcRectSize = calcRect.Size;
  493. var calcRectPosition = calcRect.Position;
  494. if (roomDoorInfo.Direction == DoorDirection.N || roomDoorInfo.Direction == DoorDirection.S)
  495. {
  496. calcRectSize.Y -= 1;
  497. }
  498. else
  499. {
  500. calcRectPosition.Y -= 1;
  501. calcRectSize.Y += 1;
  502. }
  503.  
  504. aisleFog.InitFog(calcRectPosition, calcRectSize);
  505. World.FogMaskRoot.AddChild(aisleFog);
  506. roomDoorInfo.AisleFogMask = aisleFog;
  507. roomDoorInfo.ConnectDoor.AisleFogMask = aisleFog;
  508.  
  509. //过道迷雾区域
  510. var fogArea = new AisleFogArea();
  511. fogArea.Init(roomDoorInfo,
  512. new Rect2I(
  513. fogAreaRect.Position * GameConfig.TileCellSize,
  514. fogAreaRect.Size * GameConfig.TileCellSize
  515. )
  516. );
  517. roomDoorInfo.AisleFogArea = fogArea;
  518. roomDoorInfo.ConnectDoor.AisleFogArea = fogArea;
  519. World.AffiliationAreaRoot.AddChild(fogArea);
  520. }
  521.  
  522. //预览迷雾区域
  523. var previewRoomFog = new PreviewFogMask();
  524. roomDoorInfo.PreviewRoomFogMask = previewRoomFog;
  525. previewRoomFog.Init(roomDoorInfo, PreviewFogMask.PreviewFogType.Room);
  526. previewRoomFog.SetActive(false);
  527. World.FogMaskRoot.AddChild(previewRoomFog);
  528. var previewAisleFog = new PreviewFogMask();
  529. roomDoorInfo.PreviewAisleFogMask = previewAisleFog;
  530. previewAisleFog.Init(roomDoorInfo, PreviewFogMask.PreviewFogType.Aisle);
  531. previewAisleFog.SetActive(false);
  532. World.FogMaskRoot.AddChild(previewAisleFog);
  533. }
  534. }
  535.  
  536. private void CreatePreviewSprite(RoomInfo roomInfo)
  537. {
  538. //房间区域
  539. var sprite = new TextureRect();
  540. //sprite.Centered = false;
  541. sprite.Texture = roomInfo.PreviewTexture;
  542. sprite.Position = roomInfo.Position + new Vector2I(1, 3);
  543. var material = ResourceManager.Load<ShaderMaterial>(ResourcePath.resource_material_Outline2_tres, false);
  544. material.SetShaderParameter("outline_color", new Color(1, 1, 1, 0.9f));
  545. material.SetShaderParameter("scale", 0.5f);
  546. sprite.Material = material;
  547. roomInfo.PreviewSprite = sprite;
  548. //过道
  549. if (roomInfo.Doors != null)
  550. {
  551. foreach (var doorInfo in roomInfo.Doors)
  552. {
  553. if (doorInfo.IsForward)
  554. {
  555. var aisleSprite = new TextureRect();
  556. //aisleSprite.Centered = false;
  557. aisleSprite.Texture = doorInfo.AislePreviewTexture;
  558. //调整过道预览位置
  559. if (doorInfo.Direction == DoorDirection.N || doorInfo.Direction == DoorDirection.S ||
  560. doorInfo.ConnectDoor.Direction == DoorDirection.N || doorInfo.ConnectDoor.Direction == DoorDirection.S)
  561. {
  562. aisleSprite.Position = doorInfo.AisleFloorRect.Position + new Vector2I(0, 1);
  563. }
  564. else
  565. {
  566. aisleSprite.Position = doorInfo.AisleFloorRect.Position;
  567. }
  568.  
  569. // var aisleSpriteMaterial = ResourceManager.Load<ShaderMaterial>(ResourcePath.resource_material_Outline2_tres, false);
  570. // aisleSpriteMaterial.SetShaderParameter("outline_color", new Color(1, 1, 1, 0.9f));
  571. // aisleSpriteMaterial.SetShaderParameter("scale", 0.5f);
  572. // aisleSprite.Material = aisleSpriteMaterial;
  573. doorInfo.AislePreviewSprite = aisleSprite;
  574. doorInfo.ConnectDoor.AislePreviewSprite = aisleSprite;
  575. }
  576. }
  577. }
  578. }
  579. /// <summary>
  580. /// 玩家第一次进入某个房间回调
  581. /// </summary>
  582. private void OnPlayerFirstEnterRoom(object o)
  583. {
  584. var room = (RoomInfo)o;
  585. room.OnFirstEnter();
  586. //如果关门了, 那么房间外的敌人就会丢失目标
  587. if (room.IsSeclusion)
  588. {
  589. var playerAffiliationArea = Player.Current.AffiliationArea;
  590. foreach (var enemy in World.Enemy_InstanceList)
  591. {
  592. //不与玩家处于同一个房间
  593. if (!enemy.IsDestroyed && enemy.AffiliationArea != playerAffiliationArea)
  594. {
  595. if (enemy.StateController.CurrState != AIStateEnum.AiNormal)
  596. {
  597. enemy.StateController.ChangeState(AIStateEnum.AiNormal);
  598. }
  599. }
  600. }
  601. }
  602. }
  603.  
  604. /// <summary>
  605. /// 玩家进入某个房间回调
  606. /// </summary>
  607. private void OnPlayerEnterRoom(object o)
  608. {
  609. var roomInfo = (RoomInfo)o;
  610. if (_affiliationAreaFlag != roomInfo.AffiliationArea)
  611. {
  612. if (!roomInfo.AffiliationArea.IsDestroyed)
  613. {
  614. //刷新迷雾
  615. FogMaskHandler.RefreshRoomFog(roomInfo);
  616. }
  617.  
  618. _affiliationAreaFlag = roomInfo.AffiliationArea;
  619. }
  620. }
  621. /// <summary>
  622. /// 检测当前房间敌人是否已经消灭干净, 应当每秒执行一次
  623. /// </summary>
  624. private void OnCheckEnemy()
  625. {
  626. var activeRoom = ActiveRoomInfo;
  627. if (activeRoom != null)
  628. {
  629. if (activeRoom.RoomPreinstall.IsRunWave) //正在生成标记
  630. {
  631. if (activeRoom.RoomPreinstall.IsCurrWaveOver()) //所有标记执行完成
  632. {
  633. //房间内是否有存活的敌人
  634. var flag = ActiveAffiliationArea.ExistEnterItem(
  635. activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy)
  636. );
  637. //Debug.Log("当前房间存活数量: " + count);
  638. if (!flag)
  639. {
  640. activeRoom.OnClearRoom();
  641. }
  642. }
  643. }
  644. }
  645. }
  646.  
  647. private void DisposeRoomInfo(RoomInfo roomInfo)
  648. {
  649. roomInfo.Destroy();
  650. }
  651. public override void _Draw()
  652. {
  653. if (ActivityObject.IsDebug)
  654. {
  655. StartRoomInfo?.EachRoom(info =>
  656. {
  657. DrawRect(new Rect2(info.Waypoints * GameConfig.TileCellSize, new Vector2(16, 16)), Colors.Red);
  658. });
  659. //绘制房间区域
  660. if (_dungeonGenerator != null)
  661. {
  662. DrawRoomInfo(StartRoomInfo);
  663. }
  664. //绘制边缘线
  665.  
  666. }
  667. }
  668. //绘制房间区域, debug 用
  669. private void DrawRoomInfo(RoomInfo roomInfo)
  670. {
  671. var cellSize = GameConfig.TileCellSize;
  672. var pos1 = (roomInfo.Position + roomInfo.Size / 2) * cellSize;
  673. //绘制下一个房间
  674. foreach (var nextRoom in roomInfo.Next)
  675. {
  676. var pos2 = (nextRoom.Position + nextRoom.Size / 2) * cellSize;
  677. DrawLine(pos1, pos2, Colors.Red);
  678. DrawRoomInfo(nextRoom);
  679. }
  680.  
  681. DrawString(ResourceManager.DefaultFont16Px, pos1 - new Vector2I(0, 10), "Id: " + roomInfo.Id.ToString());
  682. DrawString(ResourceManager.DefaultFont16Px, pos1 + new Vector2I(0, 10), "Layer: " + roomInfo.Layer.ToString());
  683.  
  684. //绘制门
  685. foreach (var roomDoor in roomInfo.Doors)
  686. {
  687. var originPos = roomDoor.OriginPosition * cellSize;
  688. switch (roomDoor.Direction)
  689. {
  690. case DoorDirection.E:
  691. DrawLine(originPos, originPos + new Vector2(3, 0) * cellSize, Colors.Yellow);
  692. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos + new Vector2(3, 4) * cellSize,
  693. Colors.Yellow);
  694. break;
  695. case DoorDirection.W:
  696. DrawLine(originPos, originPos - new Vector2(3, 0) * cellSize, Colors.Yellow);
  697. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos - new Vector2(3, -4) * cellSize,
  698. Colors.Yellow);
  699. break;
  700. case DoorDirection.S:
  701. DrawLine(originPos, originPos + new Vector2(0, 3) * cellSize, Colors.Yellow);
  702. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos + new Vector2(4, 3) * cellSize,
  703. Colors.Yellow);
  704. break;
  705. case DoorDirection.N:
  706. DrawLine(originPos, originPos - new Vector2(0, 3) * cellSize, Colors.Yellow);
  707. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos - new Vector2(-4, 3) * cellSize,
  708. Colors.Yellow);
  709. break;
  710. }
  711. //绘制房间区域
  712. DrawRect(new Rect2(roomInfo.Position * cellSize, roomInfo.Size * cellSize), Colors.Blue, false);
  713.  
  714. if (roomDoor.HasCross && roomDoor.RoomInfo.Id < roomDoor.ConnectRoom.Id)
  715. {
  716. DrawRect(new Rect2(roomDoor.Cross * cellSize, new Vector2(cellSize * 4, cellSize * 4)), Colors.Yellow, false);
  717. }
  718. }
  719. }
  720. /// <summary>
  721. /// 将房间类型枚举转为字符串
  722. /// </summary>
  723. public static string DungeonRoomTypeToString(DungeonRoomType roomType)
  724. {
  725. switch (roomType)
  726. {
  727. case DungeonRoomType.Battle: return "battle";
  728. case DungeonRoomType.Inlet: return "inlet";
  729. case DungeonRoomType.Outlet: return "outlet";
  730. case DungeonRoomType.Boss: return "boss";
  731. case DungeonRoomType.Reward: return "reward";
  732. case DungeonRoomType.Shop: return "shop";
  733. case DungeonRoomType.Event: return "event";
  734. }
  735.  
  736. return "battle";
  737. }
  738. /// <summary>
  739. /// 将房间类型枚举转为描述字符串
  740. /// </summary>
  741. public static string DungeonRoomTypeToDescribeString(DungeonRoomType roomType)
  742. {
  743. switch (roomType)
  744. {
  745. case DungeonRoomType.Battle: return "战斗房间";
  746. case DungeonRoomType.Inlet: return "起始房间";
  747. case DungeonRoomType.Outlet: return "结束房间";
  748. case DungeonRoomType.Boss: return "Boss房间";
  749. case DungeonRoomType.Reward: return "奖励房间";
  750. case DungeonRoomType.Shop: return "商店房间";
  751. case DungeonRoomType.Event: return "事件房间";
  752. }
  753.  
  754. return "战斗房间";
  755. }
  756.  
  757. /// <summary>
  758. /// 检测地牢是否可以执行生成
  759. /// </summary>
  760. /// <param name="groupName">组名称</param>
  761. public static DungeonCheckState CheckDungeon(string groupName)
  762. {
  763. if (GameApplication.Instance.RoomConfig.TryGetValue(groupName, out var group))
  764. {
  765. //验证该组是否满足生成地牢的条件
  766. if (group.InletList.Count == 0)
  767. {
  768. return new DungeonCheckState(true, "当没有可用的起始房间!");
  769. }
  770. else if (group.OutletList.Count == 0)
  771. {
  772. return new DungeonCheckState(true, "没有可用的结束房间!");
  773. }
  774. else if (group.BattleList.Count == 0)
  775. {
  776. return new DungeonCheckState(true, "没有可用的战斗房间!");
  777. }
  778.  
  779. return new DungeonCheckState(false, null);
  780. }
  781.  
  782. return new DungeonCheckState(true, "未找到地牢组");
  783. }
  784. }