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 DungeonGenerator _dungeonGenerator;
  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.OnPlayerFirstEnterRoom, OnPlayerFirstEnterRoom);
  54. EventManager.AddEventListener(EventEnum.OnPlayerEnterRoom, OnPlayerEnterRoom);
  55.  
  56. var nowTicks = DateTime.Now.Ticks;
  57. //生成地牢房间
  58. _dungeonGenerator = new DungeonGenerator();
  59. _dungeonGenerator.Generate();
  60. //填充地牢
  61. _autoTileConfig = new AutoTileConfig();
  62. _dungeonTile = new DungeonTile(TileRoot);
  63. _dungeonTile.AutoFillRoomTile(_autoTileConfig, _dungeonGenerator.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. _dungeonGenerator.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.  
  87. var weapon = ActivityObject.Create<Weapon>(ActivityIdPrefix.Weapon + "0001");
  88. weapon.PutDown(RoomLayerEnum.NormalLayer);
  89. weapon.Altitude = 32;
  90.  
  91. // for (int i = 0; i < 10; i++)
  92. // {
  93. // var enemy = ActivityObject.Create<Enemy>(ActivityIdPrefix.Enemy + "0001");
  94. // enemy.PutDown(new Vector2(100 + i * 20, 100), RoomLayerEnum.YSortLayer);
  95. // enemy.PickUpWeapon(ActivityObject.Create<Weapon>(ActivityIdPrefix.Weapon + Utils.RandomChoose("0001", "0002", "0003")));
  96. // }
  97.  
  98. //相机跟随玩家
  99. GameCamera.Main.SetFollowTarget(Player);
  100. //修改鼠标指针
  101. var cursor = GameApplication.Instance.Cursor;
  102. cursor.SetGuiMode(false);
  103. cursor.SetMountRole(Player);
  104. }
  105.  
  106. public override void _PhysicsProcess(double delta)
  107. {
  108. _checkEnemyTimer += (float)delta;
  109. if (_checkEnemyTimer >= 1)
  110. {
  111. _checkEnemyTimer %= 1;
  112. //检查房间内的敌人存活状况
  113. OnCheckEnemy();
  114. }
  115. }
  116.  
  117. /// <summary>
  118. /// 获取指定层级根节点
  119. /// </summary>
  120. public Node2D GetRoomLayer(RoomLayerEnum layerEnum)
  121. {
  122. switch (layerEnum)
  123. {
  124. case RoomLayerEnum.NormalLayer:
  125. return NormalLayer;
  126. case RoomLayerEnum.YSortLayer:
  127. return YSortLayer;
  128. }
  129.  
  130. return null;
  131. }
  132.  
  133. public override void _Process(double delta)
  134. {
  135. Enemy.UpdateEnemiesView();
  136. if (GameApplication.Instance.Debug)
  137. {
  138. QueueRedraw();
  139. }
  140. }
  141.  
  142. public override void _Draw()
  143. {
  144. if (GameApplication.Instance.Debug)
  145. {
  146. if (_dungeonTile != null)
  147. {
  148. //绘制ai寻路区域
  149. Utils.DrawNavigationPolygon(this, _roomStaticNavigationList.ToArray());
  150. }
  151. //绘制房间区域
  152. //DrawRoomInfo(_generateDungeon.StartRoom);
  153. }
  154. }
  155.  
  156. // 初始化房间
  157. private void InitRoom(RoomInfo roomInfo)
  158. {
  159. //挂载房间导航区域
  160. MountNavFromRoomInfo(roomInfo);
  161. //创建门
  162. CreateDoor(roomInfo);
  163. //创建房间归属区域
  164. CreateRoomAisleAffiliation(roomInfo);
  165. }
  166. //挂载房间导航区域
  167. private void MountNavFromRoomInfo(RoomInfo roomInfo)
  168. {
  169. var polygonArray = roomInfo.RoomSplit.RoomInfo.NavigationList.ToArray();
  170. var polygon = new NavigationPolygon();
  171. var offset = roomInfo.GetOffsetPosition();
  172. for (var i = 0; i < polygonArray.Length; i++)
  173. {
  174. var navigationPolygonData = polygonArray[i];
  175. var polygonPointArray = navigationPolygonData.ConvertPointsToVector2Array();
  176. //这里的位置需要加上房间位置
  177. for (var j = 0; j < polygonPointArray.Length; j++)
  178. {
  179. polygonPointArray[j] = polygonPointArray[j] + roomInfo.GetWorldPosition() - offset;
  180. }
  181. polygon.AddOutline(polygonPointArray);
  182. var points = new List<SerializeVector2>();
  183. for (var j = 0; j < polygonPointArray.Length; j++)
  184. {
  185. points.Add(new SerializeVector2(polygonPointArray[j]));
  186. }
  187. //存入汇总列表
  188. _roomStaticNavigationList.Add(new NavigationPolygonData(navigationPolygonData.Type, points));
  189. }
  190. polygon.MakePolygonsFromOutlines();
  191. var navigationPolygon = new NavigationRegion2D();
  192. navigationPolygon.Name = "NavigationRegion" + (GetChildCount() + 1);
  193. navigationPolygon.NavigationPolygon = polygon;
  194. AddChild(navigationPolygon);
  195. }
  196.  
  197. //创建门
  198. private void CreateDoor(RoomInfo roomInfo)
  199. {
  200. foreach (var doorInfo in roomInfo.Doors)
  201. {
  202. var door = ActivityObject.Create<RoomDoor>(ActivityIdPrefix.Other + "0001");
  203. doorInfo.Door = door;
  204. Vector2 offset;
  205. switch (doorInfo.Direction)
  206. {
  207. case DoorDirection.E:
  208. offset = new Vector2(-0.5f, 2);
  209. break;
  210. case DoorDirection.W:
  211. offset = new Vector2(0.5f, 2);
  212. break;
  213. case DoorDirection.S:
  214. offset = new Vector2(2f, -0.5f);
  215. break;
  216. case DoorDirection.N:
  217. offset = new Vector2(2f, 0.5f);
  218. break;
  219. default: offset = new Vector2();
  220. break;
  221. }
  222. door.Position = (doorInfo.OriginPosition + offset) * GameConfig.TileCellSize;
  223. door.Init(doorInfo);
  224. door.PutDown(RoomLayerEnum.NormalLayer, false);
  225. }
  226. }
  227.  
  228. //创建房间归属区域
  229. private void CreateRoomAisleAffiliation(RoomInfo roomInfo)
  230. {
  231. var affiliation = new AffiliationArea();
  232. affiliation.Name = "AffiliationArea" + (_affiliationIndex++);
  233. affiliation.Init(roomInfo, new Rect2(
  234. roomInfo.GetWorldPosition() + new Vector2(GameConfig.TileCellSize, GameConfig.TileCellSize),
  235. (roomInfo.Size - new Vector2I(2, 2)) * GameConfig.TileCellSize));
  236. roomInfo.Affiliation = affiliation;
  237. TileRoot.AddChild(affiliation);
  238. }
  239.  
  240. /// <summary>
  241. /// 玩家第一次进入某个房间回调
  242. /// </summary>
  243. private void OnPlayerFirstEnterRoom(object o)
  244. {
  245. var room = (RoomInfo)o;
  246. room.BeReady();
  247. }
  248.  
  249. /// <summary>
  250. /// 玩家进入某个房间回调
  251. /// </summary>
  252. private void OnPlayerEnterRoom(object o)
  253. {
  254. }
  255. /// <summary>
  256. /// 检测当前房间敌人是否已经消灭干净, 应当每秒执行一次
  257. /// </summary>
  258. private void OnCheckEnemy()
  259. {
  260. var activeRoom = ActiveRoom;
  261. if (activeRoom != null && activeRoom.IsSeclusion)
  262. {
  263. if (activeRoom.IsCurrWaveOver()) //所有标记执行完成
  264. {
  265. //存活敌人数量
  266. var count = ActiveAffiliation.FindIncludeItemsCount(
  267. activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy)
  268. );
  269. GD.Print("当前房间存活数量: " + count);
  270. if (count == 0)
  271. {
  272. activeRoom.OnClearRoom();
  273. }
  274. }
  275. }
  276. }
  277.  
  278. //绘制房间区域, debug 用
  279. private void DrawRoomInfo(RoomInfo room)
  280. {
  281. var cellSize = TileRoot.CellQuadrantSize;
  282. var pos1 = (room.Position + room.Size / 2) * cellSize;
  283. //绘制下一个房间
  284. foreach (var nextRoom in room.Next)
  285. {
  286. var pos2 = (nextRoom.Position + nextRoom.Size / 2) * cellSize;
  287. DrawLine(pos1, pos2, Colors.Red);
  288. DrawRoomInfo(nextRoom);
  289. }
  290.  
  291. DrawString(_font, pos1, room.Id.ToString());
  292.  
  293. //绘制门
  294. foreach (var roomDoor in room.Doors)
  295. {
  296. var originPos = roomDoor.OriginPosition * cellSize;
  297. switch (roomDoor.Direction)
  298. {
  299. case DoorDirection.E:
  300. DrawLine(originPos, originPos + new Vector2(3, 0) * cellSize, Colors.Yellow);
  301. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos + new Vector2(3, 4) * cellSize,
  302. Colors.Yellow);
  303. break;
  304. case DoorDirection.W:
  305. DrawLine(originPos, originPos - new Vector2(3, 0) * cellSize, Colors.Yellow);
  306. DrawLine(originPos + new Vector2(0, 4) * cellSize, originPos - new Vector2(3, -4) * cellSize,
  307. Colors.Yellow);
  308. break;
  309. case DoorDirection.S:
  310. DrawLine(originPos, originPos + new Vector2(0, 3) * cellSize, Colors.Yellow);
  311. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos + new Vector2(4, 3) * cellSize,
  312. Colors.Yellow);
  313. break;
  314. case DoorDirection.N:
  315. DrawLine(originPos, originPos - new Vector2(0, 3) * cellSize, Colors.Yellow);
  316. DrawLine(originPos + new Vector2(4, 0) * cellSize, originPos - new Vector2(-4, 3) * cellSize,
  317. Colors.Yellow);
  318. break;
  319. }
  320. //绘制房间区域
  321. DrawRect(new Rect2(room.Position * cellSize, room.Size * cellSize), Colors.Blue, false);
  322.  
  323. if (roomDoor.HasCross && roomDoor.RoomInfo.Id < roomDoor.ConnectRoom.Id)
  324. {
  325. DrawRect(new Rect2(roomDoor.Cross * cellSize, new Vector2(cellSize * 4, cellSize * 4)), Colors.Yellow, false);
  326. }
  327. }
  328. }
  329. }