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