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 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. var random = new SeedRandom();
  185. _dungeonGenerator = new DungeonGenerator(CurrConfig, random);
  186. if (!_dungeonGenerator.Generate()) //生成房间失败
  187. {
  188. _dungeonGenerator.EachRoom(DisposeRoomInfo);
  189. _dungeonGenerator = null;
  190. UiManager.Hide_Loading();
  191. if (IsEditorMode) //在编辑器模式下打开的Ui
  192. {
  193. EditorPlayManager.IsPlay = false;
  194. IsEditorMode = false;
  195. //显示上一个Ui
  196. if (_prevUi != null)
  197. {
  198. _prevUi.ShowUi();
  199. }
  200. }
  201. else //正常关闭Ui
  202. {
  203. UiManager.Open_Main();
  204. }
  205. EditorWindowManager.ShowTips("错误", "生成房间尝试次数过多,生成地牢房间失败,请加大房间门连接区域!");
  206. yield break;
  207. }
  208. yield return 0;
  209. //创建世界场景
  210. World = GameApplication.Instance.CreateNewWorld();
  211. yield return 0;
  212. //填充地牢
  213. AutoTileConfig = new AutoTileConfig(0, World.TileRoot.TileSet.GetSource(0) as TileSetAtlasSource);
  214. _dungeonTileMap = new DungeonTileMap(World.TileRoot);
  215. yield return _dungeonTileMap.AutoFillRoomTile(AutoTileConfig, _dungeonGenerator.StartRoomInfo, random);
  216. //yield return _dungeonTileMap.AddOutlineTile(AutoTileConfig.WALL_BLOCK);
  217. //生成寻路网格, 这一步操作只生成过道的导航
  218. _dungeonTileMap.GenerateNavigationPolygon(GameConfig.AisleFloorMapLayer);
  219. yield return 0;
  220. //将导航网格绑定到 DoorInfo 上
  221. BindAisleNavigation(StartRoomInfo, _dungeonTileMap.GetPolygonData());
  222. yield return 0;
  223. //挂载过道导航区域
  224. _dungeonTileMap.MountNavigationPolygon(World.NavigationRoot);
  225. yield return 0;
  226. //初始化所有房间
  227. yield return _dungeonGenerator.EachRoomCoroutine(InitRoom);
  228.  
  229. //播放bgm
  230. //SoundManager.PlayMusic(ResourcePath.resource_sound_bgm_Intro_ogg, -17f);
  231.  
  232. //地牢加载即将完成
  233. yield return _dungeonGenerator.EachRoomCoroutine(info => info.OnReady());
  234. //初始房间创建玩家标记
  235. var playerBirthMark = StartRoomInfo.RoomPreinstall.GetPlayerBirthMark();
  236. //创建玩家
  237. var player = ActivityObject.Create<Player>(ActivityObject.Ids.Id_role0001);
  238. if (playerBirthMark != null)
  239. {
  240. //player.Position = new Vector2(50, 50);
  241. player.Position = playerBirthMark.Position;
  242. }
  243. player.Name = "Player";
  244. player.PutDown(RoomLayerEnum.YSortLayer);
  245. Player.SetCurrentPlayer(player);
  246. GameApplication.Instance.Cursor.SetGuiMode(false);
  247. //打开游戏中的ui
  248. UiManager.Open_RoomUI();
  249. //派发进入地牢事件
  250. EventManager.EmitEvent(EventEnum.OnEnterDungeon);
  251. IsInDungeon = true;
  252. QueueRedraw();
  253. yield return 0;
  254. //关闭 loading UI
  255. UiManager.Destroy_Loading();
  256. if (finish != null)
  257. {
  258. finish();
  259. }
  260. }
  261.  
  262. //执行退出地牢流程
  263. private IEnumerator RunExitDungeonCoroutine(Action finish)
  264. {
  265. //打开 loading UI
  266. UiManager.Open_Loading();
  267. yield return 0;
  268. World.Pause = true;
  269. yield return 0;
  270. _dungeonGenerator.EachRoom(DisposeRoomInfo);
  271. yield return 0;
  272. _dungeonTileMap = null;
  273. AutoTileConfig = null;
  274. _dungeonGenerator = null;
  275. UiManager.Hide_RoomUI();
  276. yield return 0;
  277. Player.SetCurrentPlayer(null);
  278. World = null;
  279. GameApplication.Instance.DestroyWorld();
  280. yield return 0;
  281. FogMaskHandler.ClearRecordRoom();
  282. LiquidBrushManager.ClearData();
  283. BrushImageData.ClearBrushData();
  284. QueueRedraw();
  285. //鼠标还原
  286. GameApplication.Instance.Cursor.SetGuiMode(true);
  287. //派发退出地牢事件
  288. EventManager.EmitEvent(EventEnum.OnExitDungeon);
  289. yield return 0;
  290. //关闭 loading UI
  291. UiManager.Destroy_Loading();
  292. if (finish != null)
  293. {
  294. finish();
  295. }
  296. }
  297.  
  298. //将导航网格绑定到 DoorInfo 上
  299. private void BindAisleNavigation(RoomInfo startRoom, NavigationPolygonData[] polygonDatas)
  300. {
  301. var list = polygonDatas.ToList();
  302. startRoom.EachRoom(roomInfo =>
  303. {
  304. if (roomInfo.Doors != null)
  305. {
  306. foreach (var roomInfoDoor in roomInfo.Doors)
  307. {
  308. if (roomInfoDoor.IsForward)
  309. {
  310. var doorPosition = roomInfoDoor.GetWorldOriginPosition();
  311. for (var i = 0; i < list.Count; i++)
  312. {
  313. var data = list[i];
  314. var points = data.GetPoints();
  315. if (InLength(points, doorPosition, 32) && InLength(points, roomInfoDoor.GetWorldEndPosition(), 32))
  316. {
  317. roomInfoDoor.AisleNavigation = data;
  318. roomInfoDoor.ConnectDoor.AisleNavigation = data;
  319.  
  320. list.RemoveAt(i);
  321. }
  322. }
  323.  
  324. //Debug.Log(roomInfo.Id + ", 是否找到连接过道: " + flag);
  325. }
  326. }
  327. }
  328. });
  329. }
  330.  
  331. private bool InLength(Vector2[] points, Vector2 targetPoint, float len)
  332. {
  333. foreach (var point in points)
  334. {
  335. if (point.DistanceSquaredTo(targetPoint) <= len * len)
  336. {
  337. return true;
  338. }
  339. }
  340.  
  341. return false;
  342. }
  343.  
  344. // 初始化房间
  345. private void InitRoom(RoomInfo roomInfo)
  346. {
  347. roomInfo.CalcRange();
  348. //挂载房间导航区域
  349. MountNavFromRoomInfo(roomInfo);
  350. //创建门
  351. CreateDoor(roomInfo);
  352. //创建房间归属区域
  353. CreateRoomAffiliation(roomInfo);
  354. //创建 RoomStaticSprite
  355. CreateRoomStaticSprite(roomInfo);
  356. //创建静态精灵画布
  357. CreateRoomStaticImageCanvas(roomInfo);
  358. //创建液体区域
  359. CreateRoomLiquidCanvas(roomInfo);
  360. //创建迷雾遮罩
  361. CreateRoomFogMask(roomInfo);
  362. //创建房间/过道预览sprite
  363. CreatePreviewSprite(roomInfo);
  364. }
  365. //挂载房间导航区域
  366. private void MountNavFromRoomInfo(RoomInfo roomInfo)
  367. {
  368. var offset = roomInfo.GetOffsetPosition();
  369. var worldPosition = roomInfo.GetWorldPosition() - offset;
  370. var polygon = roomInfo.RoomSplit.TileInfo.NavigationPolygon;
  371. var vertices = roomInfo.RoomSplit.TileInfo.NavigationVertices;
  372. var polygonData = new NavigationPolygon();
  373. polygonData.CellSize = GameConfig.NavigationCellSize;
  374. //这里的位置需要加上房间位置
  375. polygonData.Vertices = vertices.Select(v => v.AsVector2() + worldPosition).ToArray();
  376. for (var i = 0; i < polygon.Count; i++)
  377. {
  378. polygonData.AddPolygon(polygon[i]);
  379. }
  380. var navigationPolygon = new NavigationRegion2D();
  381. navigationPolygon.Name = "NavigationRegion" + (GetChildCount() + 1);
  382. navigationPolygon.NavigationPolygon = polygonData;
  383. World.NavigationRoot.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() + new Vector2I(GameConfig.TileCellSize * 2, GameConfig.TileCellSize * 3),
  430. (roomInfo.Size - new Vector2I(4, 5)) * 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 + new Vector2I(1, 1), roomInfo.Size - new Vector2I(2, 2));
  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. if (roomDoorInfo.Direction == DoorDirection.E)
  504. {
  505. if (roomDoorInfo.ConnectDoor.Direction == DoorDirection.N) //→↑
  506. {
  507. calcRect.Position += new Vector2I(2, 0);
  508. calcRect.Size -= new Vector2I(2, 3);
  509. }
  510. else //→↓
  511. {
  512. calcRect.Position += new Vector2I(2, 3);
  513. calcRect.Size -= new Vector2I(2, 3);
  514. }
  515. }
  516. else if (roomDoorInfo.Direction == DoorDirection.W)
  517. {
  518. if (roomDoorInfo.ConnectDoor.Direction == DoorDirection.N) //←↑
  519. {
  520. calcRect.Size -= new Vector2I(2, 3);
  521. }
  522. else //←↓
  523. {
  524. calcRect.Position += new Vector2I(0, 3);
  525. calcRect.Size -= new Vector2I(2, 3);
  526. }
  527. }
  528. else if (roomDoorInfo.Direction == DoorDirection.N)
  529. {
  530. if (roomDoorInfo.ConnectDoor.Direction == DoorDirection.E) //↑→
  531. {
  532. calcRect.Position += new Vector2I(2, -1);
  533. calcRect.Size -= new Vector2I(2, 1);
  534. }
  535. else //↑←
  536. {
  537. calcRect.Position += new Vector2I(0, -1);
  538. calcRect.Size -= new Vector2I(2, 1);
  539. }
  540. }
  541. else if (roomDoorInfo.Direction == DoorDirection.S)
  542. {
  543. if (roomDoorInfo.ConnectDoor.Direction == DoorDirection.E) //↓→
  544. {
  545. calcRect.Position += new Vector2I(2, 2);
  546. calcRect.Size -= new Vector2I(2, 1);
  547. }
  548. else //↓←
  549. {
  550. calcRect.Position += new Vector2I(0, 2);
  551. calcRect.Size -= new Vector2I(2, 1);
  552. }
  553. }
  554. }
  555.  
  556. //过道迷雾遮罩
  557. var aisleFog = new FogMask();
  558. var calcRectSize = calcRect.Size;
  559. var calcRectPosition = calcRect.Position;
  560. if (roomDoorInfo.Direction == DoorDirection.N || roomDoorInfo.Direction == DoorDirection.S)
  561. {
  562. calcRectSize.Y -= 1;
  563. }
  564. else
  565. {
  566. calcRectPosition.Y -= 1;
  567. calcRectSize.Y += 1;
  568. }
  569.  
  570. aisleFog.InitFog(calcRectPosition, calcRectSize);
  571. World.FogMaskRoot.AddChild(aisleFog);
  572. roomDoorInfo.AisleFogMask = aisleFog;
  573. roomDoorInfo.ConnectDoor.AisleFogMask = aisleFog;
  574.  
  575. //过道迷雾区域
  576. var fogArea = new AisleFogArea();
  577. fogArea.Init(roomDoorInfo,
  578. new Rect2I(
  579. fogAreaRect.Position * GameConfig.TileCellSize,
  580. fogAreaRect.Size * GameConfig.TileCellSize
  581. )
  582. );
  583. roomDoorInfo.AisleFogArea = fogArea;
  584. roomDoorInfo.ConnectDoor.AisleFogArea = fogArea;
  585. World.AffiliationAreaRoot.AddChild(fogArea);
  586. }
  587.  
  588. //预览迷雾区域
  589. var previewRoomFog = new PreviewFogMask();
  590. roomDoorInfo.PreviewRoomFogMask = previewRoomFog;
  591. previewRoomFog.Init(roomDoorInfo, PreviewFogMask.PreviewFogType.Room);
  592. previewRoomFog.SetActive(false);
  593. World.FogMaskRoot.AddChild(previewRoomFog);
  594. var previewAisleFog = new PreviewFogMask();
  595. roomDoorInfo.PreviewAisleFogMask = previewAisleFog;
  596. previewAisleFog.Init(roomDoorInfo, PreviewFogMask.PreviewFogType.Aisle);
  597. previewAisleFog.SetActive(false);
  598. World.FogMaskRoot.AddChild(previewAisleFog);
  599. }
  600. }
  601.  
  602. private void CreatePreviewSprite(RoomInfo roomInfo)
  603. {
  604. //房间区域
  605. var sprite = new TextureRect();
  606. //sprite.Centered = false;
  607. sprite.Texture = roomInfo.PreviewTexture;
  608. sprite.Position = roomInfo.Position + new Vector2I(1, 3);
  609. var material = ResourceManager.Load<ShaderMaterial>(ResourcePath.resource_material_Outline2_tres, false);
  610. material.SetShaderParameter("outline_color", new Color(1, 1, 1, 0.9f));
  611. material.SetShaderParameter("scale", 0.5f);
  612. sprite.Material = material;
  613. roomInfo.PreviewSprite = sprite;
  614. //过道
  615. if (roomInfo.Doors != null)
  616. {
  617. foreach (var doorInfo in roomInfo.Doors)
  618. {
  619. if (doorInfo.IsForward)
  620. {
  621. var aisleSprite = new TextureRect();
  622. //aisleSprite.Centered = false;
  623. aisleSprite.Texture = doorInfo.AislePreviewTexture;
  624. //调整过道预览位置
  625. if (!doorInfo.HasCross) //不含交叉点
  626. {
  627. if (doorInfo.Direction == DoorDirection.N)
  628. {
  629. aisleSprite.Position = doorInfo.OriginPosition - new Vector2I(0, doorInfo.AislePreviewTexture.GetHeight() - 2);
  630. }
  631. else if (doorInfo.Direction == DoorDirection.S)
  632. {
  633. aisleSprite.Position = doorInfo.OriginPosition;
  634. }
  635. else if (doorInfo.Direction == DoorDirection.E)
  636. {
  637. aisleSprite.Position = doorInfo.OriginPosition - new Vector2I(1, -1);
  638. }
  639. else if (doorInfo.Direction == DoorDirection.W)
  640. {
  641. aisleSprite.Position = doorInfo.OriginPosition - new Vector2I(doorInfo.AislePreviewTexture.GetWidth() - 1, -1);
  642. }
  643. }
  644. else //包含交叉点
  645. {
  646. if (doorInfo.Direction == DoorDirection.S)
  647. {
  648. if (doorInfo.ConnectDoor.Direction == DoorDirection.E)
  649. {
  650. aisleSprite.Position = doorInfo.OriginPosition - new Vector2I(doorInfo.AislePreviewTexture.GetWidth() - 4, 1);
  651. }
  652. else if (doorInfo.ConnectDoor.Direction == DoorDirection.W)
  653. {
  654. aisleSprite.Position = doorInfo.OriginPosition - new Vector2I(0, 1);
  655. }
  656. else
  657. {
  658. aisleSprite.Position = doorInfo.OriginPosition;
  659. }
  660. }
  661. else if (doorInfo.Direction == DoorDirection.N)
  662. {
  663. if (doorInfo.ConnectDoor.Direction == DoorDirection.W)
  664. {
  665. aisleSprite.Position = doorInfo.OriginPosition - new Vector2I(0, doorInfo.AislePreviewTexture.GetHeight() - 1);
  666. }
  667. else
  668. {
  669. aisleSprite.Position = doorInfo.OriginPosition;
  670. }
  671. }
  672. else if (doorInfo.Direction == DoorDirection.W)
  673. {
  674. if (doorInfo.ConnectDoor.Direction == DoorDirection.N)
  675. {
  676. aisleSprite.Position = doorInfo.OriginPosition - new Vector2I(doorInfo.AislePreviewTexture.GetWidth() - 1, 0);
  677. }
  678. else
  679. {
  680. aisleSprite.Position = doorInfo.OriginPosition;
  681. }
  682. }
  683. else if (doorInfo.Direction == DoorDirection.E)
  684. {
  685. if (doorInfo.ConnectDoor.Direction == DoorDirection.S)
  686. {
  687. aisleSprite.Position = doorInfo.OriginPosition - new Vector2I(1, doorInfo.AislePreviewTexture.GetHeight() - 4);
  688. }
  689. else if (doorInfo.ConnectDoor.Direction == DoorDirection.N)
  690. {
  691. aisleSprite.Position = doorInfo.OriginPosition - new Vector2I(1, 0);
  692. }
  693. else
  694. {
  695. aisleSprite.Position = doorInfo.OriginPosition;
  696. }
  697. }
  698.  
  699. aisleSprite.Position += new Vector2(0, 1);
  700. }
  701.  
  702. var aisleSpriteMaterial = ResourceManager.Load<ShaderMaterial>(ResourcePath.resource_material_Outline2_tres, false);
  703. aisleSpriteMaterial.SetShaderParameter("outline_color", new Color(1, 1, 1, 0.9f));
  704. aisleSpriteMaterial.SetShaderParameter("scale", 0.5f);
  705. aisleSprite.Material = aisleSpriteMaterial;
  706. doorInfo.AislePreviewSprite = aisleSprite;
  707. doorInfo.ConnectDoor.AislePreviewSprite = aisleSprite;
  708. }
  709. }
  710. }
  711. }
  712. /// <summary>
  713. /// 玩家第一次进入某个房间回调
  714. /// </summary>
  715. private void OnPlayerFirstEnterRoom(object o)
  716. {
  717. var room = (RoomInfo)o;
  718. room.OnFirstEnter();
  719. //如果关门了, 那么房间外的敌人就会丢失目标
  720. if (room.IsSeclusion)
  721. {
  722. var playerAffiliationArea = Player.Current.AffiliationArea;
  723. foreach (var enemy in World.Enemy_InstanceList)
  724. {
  725. //不与玩家处于同一个房间
  726. if (!enemy.IsDestroyed && enemy.AffiliationArea != playerAffiliationArea)
  727. {
  728. if (enemy.StateController.CurrState != AIStateEnum.AiNormal)
  729. {
  730. enemy.StateController.ChangeState(AIStateEnum.AiNormal);
  731. }
  732. }
  733. }
  734. }
  735. }
  736.  
  737. /// <summary>
  738. /// 玩家进入某个房间回调
  739. /// </summary>
  740. private void OnPlayerEnterRoom(object o)
  741. {
  742. var roomInfo = (RoomInfo)o;
  743. if (_affiliationAreaFlag != roomInfo.AffiliationArea)
  744. {
  745. if (!roomInfo.AffiliationArea.IsDestroyed)
  746. {
  747. //刷新迷雾
  748. FogMaskHandler.RefreshRoomFog(roomInfo);
  749. }
  750.  
  751. _affiliationAreaFlag = roomInfo.AffiliationArea;
  752. }
  753. }
  754. /// <summary>
  755. /// 检测当前房间敌人是否已经消灭干净, 应当每秒执行一次
  756. /// </summary>
  757. private void OnCheckEnemy()
  758. {
  759. var activeRoom = ActiveRoomInfo;
  760. if (activeRoom != null)
  761. {
  762. if (activeRoom.RoomPreinstall.IsRunWave) //正在生成标记
  763. {
  764. if (activeRoom.RoomPreinstall.IsCurrWaveOver()) //所有标记执行完成
  765. {
  766. //房间内是否有存活的敌人
  767. var flag = ActiveAffiliationArea.ExistEnterItem(
  768. activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy)
  769. );
  770. //Debug.Log("当前房间存活数量: " + count);
  771. if (!flag)
  772. {
  773. activeRoom.OnClearRoom();
  774. }
  775. }
  776. }
  777. }
  778. }
  779.  
  780. private void DisposeRoomInfo(RoomInfo roomInfo)
  781. {
  782. roomInfo.Destroy();
  783. }
  784. public override void _Draw()
  785. {
  786. if (ActivityObject.IsDebug)
  787. {
  788. StartRoomInfo?.EachRoom(info =>
  789. {
  790. DrawRect(new Rect2(info.Waypoints * GameConfig.TileCellSize, new Vector2(16, 16)), Colors.Red);
  791. });
  792. //绘制房间区域
  793. if (_dungeonGenerator != null)
  794. {
  795. DrawRoomInfo(StartRoomInfo);
  796. }
  797. //绘制边缘线
  798.  
  799. }
  800. }
  801. //绘制房间区域, debug 用
  802. private void DrawRoomInfo(RoomInfo roomInfo)
  803. {
  804. var cellSize = GameConfig.TileCellSize;
  805. var pos1 = (roomInfo.Position + roomInfo.Size / 2) * cellSize;
  806. //绘制下一个房间
  807. foreach (var nextRoom in roomInfo.Next)
  808. {
  809. var pos2 = (nextRoom.Position + nextRoom.Size / 2) * cellSize;
  810. DrawLine(pos1, pos2, Colors.Red);
  811. DrawRoomInfo(nextRoom);
  812. }
  813.  
  814. DrawString(ResourceManager.DefaultFont16Px, pos1 - new Vector2I(0, 10), "Id: " + roomInfo.Id.ToString());
  815. DrawString(ResourceManager.DefaultFont16Px, pos1 + new Vector2I(0, 10), "Layer: " + roomInfo.Layer.ToString());
  816.  
  817. //绘制门
  818. foreach (var roomDoor in roomInfo.Doors)
  819. {
  820. var originPos = roomDoor.OriginPosition * cellSize;
  821. switch (roomDoor.Direction)
  822. {
  823. case DoorDirection.E:
  824. DrawLine(originPos, originPos + new Vector2(3, 0) * cellSize, Colors.Yellow);
  825. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos + new Vector2(3, 4) * cellSize,
  826. Colors.Yellow);
  827. break;
  828. case DoorDirection.W:
  829. DrawLine(originPos, originPos - new Vector2(3, 0) * cellSize, Colors.Yellow);
  830. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos - new Vector2(3, -4) * cellSize,
  831. Colors.Yellow);
  832. break;
  833. case DoorDirection.S:
  834. DrawLine(originPos, originPos + new Vector2(0, 3) * cellSize, Colors.Yellow);
  835. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos + new Vector2(4, 3) * cellSize,
  836. Colors.Yellow);
  837. break;
  838. case DoorDirection.N:
  839. DrawLine(originPos, originPos - new Vector2(0, 3) * cellSize, Colors.Yellow);
  840. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos - new Vector2(-4, 3) * cellSize,
  841. Colors.Yellow);
  842. break;
  843. }
  844. //绘制房间区域
  845. DrawRect(new Rect2(roomInfo.Position * cellSize, roomInfo.Size * cellSize), Colors.Blue, false);
  846.  
  847. if (roomDoor.HasCross && roomDoor.RoomInfo.Id < roomDoor.ConnectRoom.Id)
  848. {
  849. DrawRect(new Rect2(roomDoor.Cross * cellSize, new Vector2(cellSize * 4, cellSize * 4)), Colors.Yellow, false);
  850. }
  851. }
  852. }
  853. /// <summary>
  854. /// 将房间类型枚举转为字符串
  855. /// </summary>
  856. public static string DungeonRoomTypeToString(DungeonRoomType roomType)
  857. {
  858. switch (roomType)
  859. {
  860. case DungeonRoomType.Battle: return "battle";
  861. case DungeonRoomType.Inlet: return "inlet";
  862. case DungeonRoomType.Outlet: return "outlet";
  863. case DungeonRoomType.Boss: return "boss";
  864. case DungeonRoomType.Reward: return "reward";
  865. case DungeonRoomType.Shop: return "shop";
  866. case DungeonRoomType.Event: return "event";
  867. }
  868.  
  869. return "battle";
  870. }
  871. /// <summary>
  872. /// 将房间类型枚举转为描述字符串
  873. /// </summary>
  874. public static string DungeonRoomTypeToDescribeString(DungeonRoomType roomType)
  875. {
  876. switch (roomType)
  877. {
  878. case DungeonRoomType.Battle: return "战斗房间";
  879. case DungeonRoomType.Inlet: return "起始房间";
  880. case DungeonRoomType.Outlet: return "结束房间";
  881. case DungeonRoomType.Boss: return "Boss房间";
  882. case DungeonRoomType.Reward: return "奖励房间";
  883. case DungeonRoomType.Shop: return "商店房间";
  884. case DungeonRoomType.Event: return "事件房间";
  885. }
  886.  
  887. return "战斗房间";
  888. }
  889.  
  890. /// <summary>
  891. /// 检测地牢是否可以执行生成
  892. /// </summary>
  893. /// <param name="groupName">组名称</param>
  894. public static DungeonCheckState CheckDungeon(string groupName)
  895. {
  896. if (GameApplication.Instance.RoomConfig.TryGetValue(groupName, out var group))
  897. {
  898. //验证该组是否满足生成地牢的条件
  899. if (group.InletList.Count == 0)
  900. {
  901. return new DungeonCheckState(true, "当没有可用的起始房间!");
  902. }
  903. else if (group.OutletList.Count == 0)
  904. {
  905. return new DungeonCheckState(true, "没有可用的结束房间!");
  906. }
  907. else if (group.BattleList.Count == 0)
  908. {
  909. return new DungeonCheckState(true, "没有可用的战斗房间!");
  910. }
  911.  
  912. return new DungeonCheckState(false, null);
  913. }
  914.  
  915. return new DungeonCheckState(true, "未找到地牢组");
  916. }
  917. }