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