Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / room / RoomManager.cs
  1. using System;
  2. using System.Collections.Generic;
  3. using Godot;
  4.  
  5. /// <summary>
  6. /// 房间管理器
  7. /// </summary>
  8. public partial class RoomManager : Node2D
  9. {
  10. /// <summary>
  11. /// //对象根节点
  12. /// </summary>
  13. [Export] public Node2D NormalLayer;
  14. /// <summary>
  15. /// 对象根节点, 带y轴排序功能
  16. /// </summary>
  17. [Export] public Node2D YSortLayer;
  18. /// <summary>
  19. /// 地图根节点
  20. /// </summary>
  21. [Export] public TileMap TileRoot;
  22.  
  23. /// <summary>
  24. /// 玩家对象
  25. /// </summary>
  26. public Player Player { get; private set; }
  27.  
  28. /// <summary>
  29. /// 当前玩家所在的房间
  30. /// </summary>
  31. public RoomInfo ActiveRoom => Player?.Affiliation?.RoomInfo;
  32. /// <summary>
  33. /// 当前玩家所在的区域
  34. /// </summary>
  35. public AffiliationArea ActiveAffiliation => Player?.Affiliation;
  36. private DungeonTile _dungeonTile;
  37. private AutoTileConfig _autoTileConfig;
  38. private Font _font;
  39. private GenerateDungeon _generateDungeon;
  40.  
  41. private int _affiliationIndex = 0;
  42.  
  43. private float _checkEnemyTimer = 0;
  44.  
  45. //房间内所有静态导航网格数据
  46. private static List<NavigationPolygonData> _roomStaticNavigationList = new List<NavigationPolygonData>();
  47. public override void _Ready()
  48. {
  49. TileRoot.YSortEnabled = false;
  50. _font = ResourceManager.Load<Font>(ResourcePath.resource_font_cn_font_36_tres);
  51.  
  52. //绑定事件
  53. //EventManager.AddEventListener(EventEnum.OnEnemyDie, OnEnemyDie);
  54. EventManager.AddEventListener(EventEnum.OnPlayerFirstEnterRoom, OnPlayerFirstEnterRoom);
  55. EventManager.AddEventListener(EventEnum.OnPlayerEnterRoom, OnPlayerEnterRoom);
  56. var nowTicks = DateTime.Now.Ticks;
  57. //生成地牢房间
  58. _generateDungeon = new GenerateDungeon();
  59. _generateDungeon.Generate();
  60. //填充地牢
  61. _autoTileConfig = new AutoTileConfig();
  62. _dungeonTile = new DungeonTile(TileRoot);
  63. _dungeonTile.AutoFillRoomTile(_autoTileConfig, _generateDungeon.StartRoom);
  64. //生成寻路网格, 这一步操作只生成过道的导航
  65. _dungeonTile.GenerateNavigationPolygon(DungeonTile.AisleFloorMapLayer);
  66. //挂载过道导航区域
  67. _dungeonTile.MountNavigationPolygon(this);
  68. //过道导航区域数据
  69. _roomStaticNavigationList.AddRange(_dungeonTile.GetPolygonData());
  70. //门导航区域数据
  71. _roomStaticNavigationList.AddRange(_dungeonTile.GetConnectDoorPolygonData());
  72. //初始化所有房间
  73. _generateDungeon.EachRoom(InitRoom);
  74.  
  75. GD.Print("生成地牢用时: " + (DateTime.Now.Ticks - nowTicks) / 10000 + "毫秒");
  76.  
  77. //播放bgm
  78. //SoundManager.PlayMusic(ResourcePath.resource_sound_bgm_Intro_ogg, -17f);
  79.  
  80. //创建玩家
  81. Player = ActivityObject.Create<Player>(ActivityIdPrefix.Role + "0001");
  82. Player.Position = new Vector2(30, 30);
  83. Player.Name = "Player";
  84. Player.PutDown(RoomLayerEnum.YSortLayer);
  85. Player.PickUpWeapon(ActivityObject.Create<Weapon>(ActivityIdPrefix.Weapon + "0001"));
  86. // Player.PickUpWeapon(ActivityObject.Create<Weapon>(ActivityIdPrefix.Weapon + "0002"));
  87. // Player.PickUpWeapon(ActivityObject.Create<Weapon>(ActivityIdPrefix.Weapon + "0004"));
  88. // Player.PickUpWeapon(ActivityObject.Create<Weapon>(ActivityIdPrefix.Weapon + "0003"));
  89.  
  90. //相机跟随玩家
  91. GameCamera.Main.SetFollowTarget(Player);
  92. //修改鼠标指针
  93. var cursor = GameApplication.Instance.Cursor;
  94. cursor.SetGuiMode(false);
  95. cursor.SetMountRole(Player);
  96. }
  97.  
  98. public override void _PhysicsProcess(double delta)
  99. {
  100. _checkEnemyTimer += (float)delta;
  101. if (_checkEnemyTimer >= 1)
  102. {
  103. _checkEnemyTimer %= 1;
  104. //检查房间内的敌人存活状况
  105. OnCheckEnemy();
  106. }
  107. }
  108.  
  109. /// <summary>
  110. /// 获取指定层级根节点
  111. /// </summary>
  112. public Node2D GetRoomLayer(RoomLayerEnum layerEnum)
  113. {
  114. switch (layerEnum)
  115. {
  116. case RoomLayerEnum.NormalLayer:
  117. return NormalLayer;
  118. case RoomLayerEnum.YSortLayer:
  119. return YSortLayer;
  120. }
  121.  
  122. return null;
  123. }
  124.  
  125. public override void _Process(double delta)
  126. {
  127. Enemy.UpdateEnemiesView();
  128. if (GameApplication.Instance.Debug)
  129. {
  130. QueueRedraw();
  131. }
  132. }
  133.  
  134. public override void _Draw()
  135. {
  136. if (GameApplication.Instance.Debug)
  137. {
  138. if (_dungeonTile != null)
  139. {
  140. //绘制ai寻路区域
  141. Utils.DrawNavigationPolygon(this, _roomStaticNavigationList.ToArray());
  142. }
  143. //绘制房间区域
  144. //DrawRoomInfo(_generateDungeon.StartRoom);
  145. }
  146. }
  147.  
  148. // 初始化房间
  149. private void InitRoom(RoomInfo roomInfo)
  150. {
  151. //挂载房间导航区域
  152. MountNavFromRoomInfo(roomInfo);
  153. //创建门
  154. CreateDoor(roomInfo);
  155. //创建房间归属区域
  156. CreateRoomAisleAffiliation(roomInfo);
  157. }
  158. //挂载房间导航区域
  159. private void MountNavFromRoomInfo(RoomInfo roomInfo)
  160. {
  161. var polygonArray = roomInfo.RoomSplit.RoomInfo.NavigationList.ToArray();
  162. var polygon = new NavigationPolygon();
  163. var offset = roomInfo.GetOffsetPosition();
  164. for (var i = 0; i < polygonArray.Length; i++)
  165. {
  166. var navigationPolygonData = polygonArray[i];
  167. var polygonPointArray = navigationPolygonData.ConvertPointsToVector2Array();
  168. //这里的位置需要加上房间位置
  169. for (var j = 0; j < polygonPointArray.Length; j++)
  170. {
  171. polygonPointArray[j] = polygonPointArray[j] + roomInfo.GetWorldPosition() - offset;
  172. }
  173. polygon.AddOutline(polygonPointArray);
  174. var points = new List<SerializeVector2>();
  175. for (var j = 0; j < polygonPointArray.Length; j++)
  176. {
  177. points.Add(new SerializeVector2(polygonPointArray[j]));
  178. }
  179. //存入汇总列表
  180. _roomStaticNavigationList.Add(new NavigationPolygonData(navigationPolygonData.Type, points));
  181. }
  182. polygon.MakePolygonsFromOutlines();
  183. var navigationPolygon = new NavigationRegion2D();
  184. navigationPolygon.Name = "NavigationRegion" + (GetChildCount() + 1);
  185. navigationPolygon.NavigationPolygon = polygon;
  186. AddChild(navigationPolygon);
  187. }
  188.  
  189. //创建门
  190. private void CreateDoor(RoomInfo roomInfo)
  191. {
  192. foreach (var doorInfo in roomInfo.Doors)
  193. {
  194. var door = ActivityObject.Create<RoomDoor>(ActivityIdPrefix.Other + "0001");
  195. doorInfo.Door = door;
  196. Vector2 offset;
  197. switch (doorInfo.Direction)
  198. {
  199. case DoorDirection.E:
  200. offset = new Vector2(-0.5f, 2);
  201. break;
  202. case DoorDirection.W:
  203. offset = new Vector2(0.5f, 2);
  204. break;
  205. case DoorDirection.S:
  206. offset = new Vector2(2f, -0.5f);
  207. break;
  208. case DoorDirection.N:
  209. offset = new Vector2(2f, 0.5f);
  210. break;
  211. default: offset = new Vector2();
  212. break;
  213. }
  214. door.Position = (doorInfo.OriginPosition + offset) * GameConfig.TileCellSize;
  215. door.Init(doorInfo);
  216. door.PutDown(RoomLayerEnum.NormalLayer, false);
  217. }
  218. }
  219.  
  220. //创建房间归属区域
  221. private void CreateRoomAisleAffiliation(RoomInfo roomInfo)
  222. {
  223. var affiliation = new AffiliationArea();
  224. affiliation.Name = "AffiliationArea" + (_affiliationIndex++);
  225. affiliation.Init(roomInfo, new Rect2(
  226. roomInfo.GetWorldPosition() + new Vector2(GameConfig.TileCellSize, GameConfig.TileCellSize),
  227. (roomInfo.Size - new Vector2I(2, 2)) * GameConfig.TileCellSize));
  228. roomInfo.Affiliation = affiliation;
  229. TileRoot.AddChild(affiliation);
  230. }
  231.  
  232. /// <summary>
  233. /// 玩家第一次进入某个房间回调
  234. /// </summary>
  235. private void OnPlayerFirstEnterRoom(object o)
  236. {
  237. var room = (RoomInfo)o;
  238. room.BeReady();
  239. }
  240.  
  241. /// <summary>
  242. /// 玩家进入某个房间回调
  243. /// </summary>
  244. private void OnPlayerEnterRoom(object o)
  245. {
  246. }
  247. /// <summary>
  248. /// 检测当前房间敌人是否已经消灭干净, 应当每秒执行一次
  249. /// </summary>
  250. private void OnCheckEnemy()
  251. {
  252. var activeRoom = ActiveRoom;
  253. if (activeRoom != null && activeRoom.IsSeclusion)
  254. {
  255. if (activeRoom.IsCurrWaveOver()) //所有标记执行完成
  256. {
  257. //存活敌人数量
  258. var count = ActiveAffiliation.FindIncludeItemsCount(
  259. activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy)
  260. );
  261. GD.Print("当前房间存活数量: " + count);
  262. if (count == 0)
  263. {
  264. activeRoom.OnClearRoom();
  265. }
  266. }
  267. }
  268. }
  269.  
  270. //绘制房间区域, debug 用
  271. private void DrawRoomInfo(RoomInfo room)
  272. {
  273. var cellSize = TileRoot.CellQuadrantSize;
  274. var pos1 = (room.Position + room.Size / 2) * cellSize;
  275. //绘制下一个房间
  276. foreach (var nextRoom in room.Next)
  277. {
  278. var pos2 = (nextRoom.Position + nextRoom.Size / 2) * cellSize;
  279. DrawLine(pos1, pos2, Colors.Red);
  280. DrawRoomInfo(nextRoom);
  281. }
  282.  
  283. DrawString(_font, pos1, room.Id.ToString());
  284.  
  285. //绘制门
  286. foreach (var roomDoor in room.Doors)
  287. {
  288. var originPos = roomDoor.OriginPosition * cellSize;
  289. switch (roomDoor.Direction)
  290. {
  291. case DoorDirection.E:
  292. DrawLine(originPos, originPos + new Vector2(3, 0) * cellSize, Colors.Yellow);
  293. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos + new Vector2(3, 4) * cellSize,
  294. Colors.Yellow);
  295. break;
  296. case DoorDirection.W:
  297. DrawLine(originPos, originPos - new Vector2(3, 0) * cellSize, Colors.Yellow);
  298. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos - new Vector2(3, -4) * cellSize,
  299. Colors.Yellow);
  300. break;
  301. case DoorDirection.S:
  302. DrawLine(originPos, originPos + new Vector2(0, 3) * cellSize, Colors.Yellow);
  303. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos + new Vector2(4, 3) * cellSize,
  304. Colors.Yellow);
  305. break;
  306. case DoorDirection.N:
  307. DrawLine(originPos, originPos - new Vector2(0, 3) * cellSize, Colors.Yellow);
  308. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos - new Vector2(-4, 3) * cellSize,
  309. Colors.Yellow);
  310. break;
  311. }
  312. //绘制房间区域
  313. DrawRect(new Rect2(room.Position * cellSize, room.Size * cellSize), Colors.Blue, false);
  314.  
  315. if (roomDoor.HasCross && roomDoor.RoomInfo.Id < roomDoor.ConnectRoom.Id)
  316. {
  317. DrawRect(new Rect2(roomDoor.Cross * cellSize, new Vector2(cellSize * 4, cellSize * 4)), Colors.Yellow, false);
  318. }
  319. }
  320. }
  321. }