Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / room / DungeonManager.cs
@小李xl 小李xl on 29 May 2023 16 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 StartRoom => _dungeonGenerator?.StartRoom;
  17. /// <summary>
  18. /// 当前玩家所在的房间
  19. /// </summary>
  20. public RoomInfo ActiveRoom => 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. private DungeonConfig _config;
  32. private DungeonTile _dungeonTile;
  33. private AutoTileConfig _autoTileConfig;
  34. private DungeonGenerator _dungeonGenerator;
  35. //房间内所有静态导航网格数据
  36. private List<NavigationPolygonData> _roomStaticNavigationList;
  37. private World _world;
  38. //用于检查房间敌人的计时器
  39. private int _affiliationIndex = 0;
  40. private float _checkEnemyTimer = 0;
  41.  
  42.  
  43. public DungeonManager()
  44. {
  45. //绑定事件
  46. EventManager.AddEventListener(EventEnum.OnPlayerFirstEnterRoom, OnPlayerFirstEnterRoom);
  47. EventManager.AddEventListener(EventEnum.OnPlayerEnterRoom, OnPlayerEnterRoom);
  48. }
  49. /// <summary>
  50. /// 加载地牢
  51. /// </summary>
  52. public void LoadDungeon(DungeonConfig config, Action finish = null)
  53. {
  54. _config = config;
  55. GameApplication.Instance.StartCoroutine(RunLoadDungeonCoroutine(finish));
  56. }
  57.  
  58. /// <summary>
  59. /// 退出地牢
  60. /// </summary>
  61. public void ExitDungeon(Action finish = null)
  62. {
  63. IsInDungeon = false;
  64. GameApplication.Instance.StartCoroutine(RunExitDungeonCoroutine(finish));
  65. }
  66.  
  67. public override void _PhysicsProcess(double delta)
  68. {
  69. if (IsInDungeon)
  70. {
  71. _checkEnemyTimer += (float)delta;
  72. if (_checkEnemyTimer >= 1)
  73. {
  74. _checkEnemyTimer %= 1;
  75. //检查房间内的敌人存活状况
  76. OnCheckEnemy();
  77. }
  78. }
  79. }
  80.  
  81. public override void _Process(double delta)
  82. {
  83. if (IsInDungeon)
  84. {
  85. UpdateEnemiesView();
  86. if (GameApplication.Instance.Debug)
  87. {
  88. QueueRedraw();
  89. }
  90. }
  91. }
  92.  
  93. //执行加载地牢协程
  94. private IEnumerator RunLoadDungeonCoroutine(Action finish)
  95. {
  96. //打开 loading UI
  97. UiManager.Open_Loading();
  98. yield return 0;
  99. //创建世界场景
  100. _world = GameApplication.Instance.CreateNewWorld();
  101. yield return new WaitForFixedProcess(10);
  102. //生成地牢房间
  103. _dungeonGenerator = new DungeonGenerator(_config);
  104. _dungeonGenerator.Generate();
  105. yield return 0;
  106. //填充地牢
  107. _autoTileConfig = new AutoTileConfig();
  108. _dungeonTile = new DungeonTile(_world.TileRoot);
  109. _dungeonTile.AutoFillRoomTile(_autoTileConfig, _dungeonGenerator.StartRoom);
  110. yield return 0;
  111. //生成寻路网格, 这一步操作只生成过道的导航
  112. _dungeonTile.GenerateNavigationPolygon(GameConfig.AisleFloorMapLayer);
  113. yield return 0;
  114. //挂载过道导航区域
  115. _dungeonTile.MountNavigationPolygon(_world.TileRoot);
  116. yield return 0;
  117. //过道导航区域数据
  118. _roomStaticNavigationList = new List<NavigationPolygonData>();
  119. _roomStaticNavigationList.AddRange(_dungeonTile.GetPolygonData());
  120. yield return 0;
  121. //门导航区域数据
  122. _roomStaticNavigationList.AddRange(_dungeonTile.GetConnectDoorPolygonData());
  123. yield return new WaitForFixedProcess(10);
  124. //初始化所有房间
  125. _dungeonGenerator.EachRoom(InitRoom);
  126. yield return new WaitForFixedProcess(10);
  127.  
  128. //播放bgm
  129. //SoundManager.PlayMusic(ResourcePath.resource_sound_bgm_Intro_ogg, -17f);
  130.  
  131. //初始房间创建玩家标记
  132. var playerBirthMark = StartRoom.ActivityMarks.FirstOrDefault(mark => mark.Type == ActivityIdPrefix.ActivityPrefixType.Player);
  133. //创建玩家
  134. var player = ActivityObject.Create<Player>(ActivityIdPrefix.Role + "0001");
  135. if (playerBirthMark != null)
  136. {
  137. //player.Position = new Vector2(50, 50);
  138. player.Position = playerBirthMark.Position;
  139. }
  140. player.Name = "Player";
  141. Player.SetCurrentPlayer(player);
  142. player.PutDown(RoomLayerEnum.YSortLayer);
  143. //玩家手上添加武器
  144. player.PickUpWeapon(ActivityObject.Create<Weapon>(ActivityIdPrefix.Weapon + "0001"));
  145. player.PickUpWeapon(ActivityObject.Create<Weapon>(ActivityIdPrefix.Weapon + "0002"));
  146. GameApplication.Instance.Cursor.SetGuiMode(false);
  147. yield return 0;
  148. //打开游戏中的ui
  149. var roomUi = UiManager.Open_RoomUI();
  150. roomUi.InitData(player);
  151. //派发进入地牢事件
  152. EventManager.EmitEvent(EventEnum.OnEnterDungeon);
  153. IsInDungeon = true;
  154. yield return 0;
  155. //关闭 loading UI
  156. UiManager.Dispose_Loading();
  157. if (finish != null)
  158. {
  159. finish();
  160. }
  161. }
  162.  
  163. private IEnumerator RunExitDungeonCoroutine(Action finish)
  164. {
  165. //打开 loading UI
  166. UiManager.Open_Loading();
  167. yield return 0;
  168. _world.Pause = true;
  169. yield return 0;
  170. _dungeonGenerator.EachRoom(DisposeRoomInfo);
  171. yield return 0;
  172. _dungeonTile = null;
  173. _autoTileConfig = null;
  174. _dungeonGenerator = null;
  175. _roomStaticNavigationList.Clear();
  176. _roomStaticNavigationList = null;
  177. UiManager.Hide_RoomUI();
  178. yield return new WaitForFixedProcess(10);
  179. Player.SetCurrentPlayer(null);
  180. _world = null;
  181. GameApplication.Instance.DestroyWorld();
  182. yield return new WaitForFixedProcess(10);
  183. //鼠标还原
  184. GameApplication.Instance.Cursor.SetGuiMode(false);
  185. //派发退出地牢事件
  186. EventManager.EmitEvent(EventEnum.OnExitDungeon);
  187. yield return 0;
  188. //关闭 loading UI
  189. UiManager.Dispose_Loading();
  190. if (finish != null)
  191. {
  192. finish();
  193. }
  194. }
  195. // 初始化房间
  196. private void InitRoom(RoomInfo roomInfo)
  197. {
  198. //挂载房间导航区域
  199. MountNavFromRoomInfo(roomInfo);
  200. //创建门
  201. CreateDoor(roomInfo);
  202. //创建房间归属区域
  203. CreateRoomAisleAffiliation(roomInfo);
  204. }
  205. //挂载房间导航区域
  206. private void MountNavFromRoomInfo(RoomInfo roomInfo)
  207. {
  208. var polygonArray = roomInfo.RoomSplit.RoomInfo.NavigationList.ToArray();
  209. var polygon = new NavigationPolygon();
  210. var offset = roomInfo.GetOffsetPosition();
  211. for (var i = 0; i < polygonArray.Length; i++)
  212. {
  213. var navigationPolygonData = polygonArray[i];
  214. var polygonPointArray = navigationPolygonData.ConvertPointsToVector2Array();
  215. //这里的位置需要加上房间位置
  216. for (var j = 0; j < polygonPointArray.Length; j++)
  217. {
  218. polygonPointArray[j] = polygonPointArray[j] + roomInfo.GetWorldPosition() - offset;
  219. }
  220. polygon.AddOutline(polygonPointArray);
  221. var points = new List<SerializeVector2>();
  222. for (var j = 0; j < polygonPointArray.Length; j++)
  223. {
  224. points.Add(new SerializeVector2(polygonPointArray[j]));
  225. }
  226. //存入汇总列表
  227. _roomStaticNavigationList.Add(new NavigationPolygonData(navigationPolygonData.Type, points));
  228. }
  229. polygon.MakePolygonsFromOutlines();
  230. var navigationPolygon = new NavigationRegion2D();
  231. navigationPolygon.Name = "NavigationRegion" + (GetChildCount() + 1);
  232. navigationPolygon.NavigationPolygon = polygon;
  233. _world.TileRoot.AddChild(navigationPolygon);
  234. }
  235.  
  236. //创建门
  237. private void CreateDoor(RoomInfo roomInfo)
  238. {
  239. foreach (var doorInfo in roomInfo.Doors)
  240. {
  241. RoomDoor door;
  242. switch (doorInfo.Direction)
  243. {
  244. case DoorDirection.E:
  245. door = ActivityObject.Create<RoomDoor>(ActivityIdPrefix.Other + "door_e");
  246. door.Position = (doorInfo.OriginPosition + new Vector2(0.5f, 2)) * GameConfig.TileCellSize;
  247. door.ZIndex = GameConfig.TopMapLayer;
  248. break;
  249. case DoorDirection.W:
  250. door = ActivityObject.Create<RoomDoor>(ActivityIdPrefix.Other + "door_w");
  251. door.Position = (doorInfo.OriginPosition + new Vector2(-0.5f, 2)) * GameConfig.TileCellSize;
  252. door.ZIndex = GameConfig.TopMapLayer;
  253. break;
  254. case DoorDirection.S:
  255. door = ActivityObject.Create<RoomDoor>(ActivityIdPrefix.Other + "door_s");
  256. door.Position = (doorInfo.OriginPosition + new Vector2(2f, 1.5f)) * GameConfig.TileCellSize;
  257. door.ZIndex = GameConfig.TopMapLayer;
  258. break;
  259. case DoorDirection.N:
  260. door = ActivityObject.Create<RoomDoor>(ActivityIdPrefix.Other + "door_n");
  261. door.Position = (doorInfo.OriginPosition + new Vector2(2f, -0.5f)) * GameConfig.TileCellSize;
  262. door.ZIndex = GameConfig.MiddleMapLayer;
  263. break;
  264. default:
  265. return;
  266. }
  267. doorInfo.Door = door;
  268. door.Init(doorInfo);
  269. door.PutDown(RoomLayerEnum.NormalLayer, false);
  270. }
  271. }
  272.  
  273. //创建房间归属区域
  274. private void CreateRoomAisleAffiliation(RoomInfo roomInfo)
  275. {
  276. var affiliation = new AffiliationArea();
  277. affiliation.Name = "AffiliationArea" + (_affiliationIndex++);
  278. affiliation.Init(roomInfo, new Rect2(
  279. roomInfo.GetWorldPosition() + new Vector2(GameConfig.TileCellSize, GameConfig.TileCellSize),
  280. (roomInfo.Size - new Vector2I(2, 2)) * GameConfig.TileCellSize));
  281. roomInfo.Affiliation = affiliation;
  282. _world.AddChild(affiliation);
  283. }
  284. /// <summary>
  285. /// 玩家第一次进入某个房间回调
  286. /// </summary>
  287. private void OnPlayerFirstEnterRoom(object o)
  288. {
  289. var room = (RoomInfo)o;
  290. room.BeReady();
  291. //如果关门了, 那么房间外的敌人就会丢失目标
  292. if (room.IsSeclusion)
  293. {
  294. var playerAffiliationArea = Player.Current.AffiliationArea;
  295. foreach (var enemy in _world.Enemy_InstanceList)
  296. {
  297. //不与玩家处于同一个房间
  298. if (enemy.AffiliationArea != playerAffiliationArea)
  299. {
  300. if (enemy.StateController.CurrState != AiStateEnum.AiNormal)
  301. {
  302. enemy.StateController.ChangeState(AiStateEnum.AiNormal);
  303. }
  304. }
  305. }
  306. }
  307. }
  308.  
  309. /// <summary>
  310. /// 玩家进入某个房间回调
  311. /// </summary>
  312. private void OnPlayerEnterRoom(object o)
  313. {
  314. }
  315. /// <summary>
  316. /// 检测当前房间敌人是否已经消灭干净, 应当每秒执行一次
  317. /// </summary>
  318. private void OnCheckEnemy()
  319. {
  320. var activeRoom = ActiveRoom;
  321. if (activeRoom != null)// && //activeRoom.IsSeclusion)
  322. {
  323. if (activeRoom.IsSeclusion) //房间处于关上状态
  324. {
  325. if (activeRoom.IsCurrWaveOver()) //所有标记执行完成
  326. {
  327. //是否有存活的敌人
  328. var flag = ActiveAffiliationArea.ExistIncludeItem(
  329. activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy)
  330. );
  331. //GD.Print("当前房间存活数量: " + count);
  332. if (!flag)
  333. {
  334. activeRoom.OnClearRoom();
  335. }
  336. }
  337. }
  338. }
  339. }
  340.  
  341. /// <summary>
  342. /// 更新敌人视野
  343. /// </summary>
  344. private void UpdateEnemiesView()
  345. {
  346. _world.Enemy_IsFindTarget = false;
  347. _world.Enemy_FindTargetAffiliationSet.Clear();
  348. for (var i = 0; i < _world.Enemy_InstanceList.Count; i++)
  349. {
  350. var enemy = _world.Enemy_InstanceList[i];
  351. var state = enemy.StateController.CurrState;
  352. if (state == AiStateEnum.AiFollowUp || state == AiStateEnum.AiSurround) //目标在视野内
  353. {
  354. if (!_world.Enemy_IsFindTarget)
  355. {
  356. _world.Enemy_IsFindTarget = true;
  357. _world.Enemy_FindTargetPosition = Player.Current.GetCenterPosition();
  358. _world.Enemy_FindTargetAffiliationSet.Add(Player.Current.AffiliationArea);
  359. }
  360. _world.Enemy_FindTargetAffiliationSet.Add(enemy.AffiliationArea);
  361. }
  362. }
  363. }
  364.  
  365. private void DisposeRoomInfo(RoomInfo roomInfo)
  366. {
  367. foreach (var activityMark in roomInfo.ActivityMarks)
  368. {
  369. activityMark.QueueFree();
  370. }
  371. roomInfo.ActivityMarks.Clear();
  372. }
  373. public override void _Draw()
  374. {
  375. if (GameApplication.Instance.Debug)
  376. {
  377. if (_dungeonTile != null)
  378. {
  379. //绘制ai寻路区域
  380. Utils.DrawNavigationPolygon(this, _roomStaticNavigationList.ToArray());
  381. }
  382. //绘制房间区域
  383. // if (_dungeonGenerator != null)
  384. // {
  385. // DrawRoomInfo(StartRoom);
  386. // }
  387. //绘制边缘线
  388. }
  389. }
  390. //绘制房间区域, debug 用
  391. private void DrawRoomInfo(RoomInfo room)
  392. {
  393. var cellSize = _world.TileRoot.CellQuadrantSize;
  394. var pos1 = (room.Position + room.Size / 2) * cellSize;
  395. //绘制下一个房间
  396. foreach (var nextRoom in room.Next)
  397. {
  398. var pos2 = (nextRoom.Position + nextRoom.Size / 2) * cellSize;
  399. DrawLine(pos1, pos2, Colors.Red);
  400. DrawRoomInfo(nextRoom);
  401. }
  402.  
  403. DrawString(ResourceManager.DefaultFont16Px, pos1 - new Vector2I(0, 10), "Id: " + room.Id.ToString());
  404. DrawString(ResourceManager.DefaultFont16Px, pos1 + new Vector2I(0, 10), "Layer: " + room.Layer.ToString());
  405.  
  406. //绘制门
  407. foreach (var roomDoor in room.Doors)
  408. {
  409. var originPos = roomDoor.OriginPosition * cellSize;
  410. switch (roomDoor.Direction)
  411. {
  412. case DoorDirection.E:
  413. DrawLine(originPos, originPos + new Vector2(3, 0) * cellSize, Colors.Yellow);
  414. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos + new Vector2(3, 4) * cellSize,
  415. Colors.Yellow);
  416. break;
  417. case DoorDirection.W:
  418. DrawLine(originPos, originPos - new Vector2(3, 0) * cellSize, Colors.Yellow);
  419. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos - new Vector2(3, -4) * cellSize,
  420. Colors.Yellow);
  421. break;
  422. case DoorDirection.S:
  423. DrawLine(originPos, originPos + new Vector2(0, 3) * cellSize, Colors.Yellow);
  424. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos + new Vector2(4, 3) * cellSize,
  425. Colors.Yellow);
  426. break;
  427. case DoorDirection.N:
  428. DrawLine(originPos, originPos - new Vector2(0, 3) * cellSize, Colors.Yellow);
  429. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos - new Vector2(-4, 3) * cellSize,
  430. Colors.Yellow);
  431. break;
  432. }
  433. //绘制房间区域
  434. DrawRect(new Rect2(room.Position * cellSize, room.Size * cellSize), Colors.Blue, false);
  435.  
  436. if (roomDoor.HasCross && roomDoor.RoomInfo.Id < roomDoor.ConnectRoom.Id)
  437. {
  438. DrawRect(new Rect2(roomDoor.Cross * cellSize, new Vector2(cellSize * 4, cellSize * 4)), Colors.Yellow, false);
  439. }
  440. }
  441. }
  442. }