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