Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / room / RoomInfo.cs
  1.  
  2. using System;
  3. using System.Collections.Generic;
  4. using Godot;
  5.  
  6. /// <summary>
  7. /// 房间的数据描述
  8. /// </summary>
  9. public class RoomInfo : IDestroy
  10. {
  11. public RoomInfo(int id, DungeonRoomType type, DungeonRoomSplit roomSplit)
  12. {
  13. Id = id;
  14. RoomType = type;
  15. RoomSplit = roomSplit;
  16. }
  17.  
  18. /// <summary>
  19. /// 房间 id
  20. /// </summary>
  21. public int Id;
  22.  
  23. /// <summary>
  24. /// 房间类型
  25. /// </summary>
  26. public DungeonRoomType RoomType;
  27.  
  28. /// <summary>
  29. /// 层级, 也就是离初始房间间隔多少个房间
  30. /// </summary>
  31. public int Layer;
  32. /// <summary>
  33. /// 生成该房间使用的配置数据
  34. /// </summary>
  35. public DungeonRoomSplit RoomSplit;
  36. /// <summary>
  37. /// 房间大小, 单位: 格
  38. /// </summary>
  39. public Vector2I Size;
  40.  
  41. /// <summary>
  42. /// 房间位置, 单位: 格
  43. /// </summary>
  44. public Vector2I Position;
  45. /// <summary>
  46. /// 门
  47. /// </summary>
  48. public List<RoomDoorInfo> Doors = new List<RoomDoorInfo>();
  49.  
  50. /// <summary>
  51. /// 连接该房间的过道占用区域信息
  52. /// </summary>
  53. public List<Rect2I> AisleArea = new List<Rect2I>();
  54.  
  55. /// <summary>
  56. /// 下一个房间
  57. /// </summary>
  58. public List<RoomInfo> Next = new List<RoomInfo>();
  59. /// <summary>
  60. /// 上一个房间
  61. /// </summary>
  62. public RoomInfo Prev;
  63.  
  64. /// <summary>
  65. /// 当前房间使用的预设
  66. /// </summary>
  67. public RoomPreinstall RoomPreinstall;
  68.  
  69. /// <summary>
  70. /// 当前房间归属区域
  71. /// </summary>
  72. public AffiliationArea AffiliationArea;
  73.  
  74. /// <summary>
  75. /// 静态渲染精灵根节点, 用于放置sprite
  76. /// </summary>
  77. public RoomStaticSprite StaticSprite;
  78. /// <summary>
  79. /// 静态精灵绘制画布
  80. /// </summary>
  81. public ImageCanvas StaticImageCanvas;
  82.  
  83. /// <summary>
  84. /// 房间坐标相对于画布坐标偏移量, 单位: 像素
  85. /// </summary>
  86. public Vector2I RoomOffset;
  87.  
  88. /// <summary>
  89. /// 房间迷雾
  90. /// </summary>
  91. public FogMask RoomFogMask;
  92. /// <summary>
  93. /// 房间算上连接通道所占用的区域
  94. /// </summary>
  95. public Rect2I OuterRange { get; private set; }
  96.  
  97. /// <summary>
  98. /// 是否处于闭关状态, 也就是房间门没有主动打开
  99. /// </summary>
  100. public bool IsSeclusion { get; private set; } = false;
  101.  
  102. /// <summary>
  103. /// 用于标记攻击目标位置
  104. /// </summary>
  105. public Dictionary<long, Vector2> MarkTargetPosition { get; private set; } = new Dictionary<long, Vector2>();
  106. public bool IsDestroyed { get; private set; }
  107. private bool _openDoorFlag = true;
  108. // private bool _beReady = false;
  109. // private bool _waveStart = false;
  110. // private int _currWaveIndex = 0;
  111. // private int _currWaveNumber = 0;
  112. //private List<ActivityMark> _currActivityMarks = new List<ActivityMark>();
  113.  
  114. /// <summary>
  115. /// 重新计算占用的区域
  116. /// </summary>
  117. public void CalcOuterRange()
  118. {
  119. var worldPos = GetWorldPosition();
  120. var pos = new Vector2I(worldPos.X, worldPos.Y);
  121. var minX = pos.X;
  122. var minY = pos.Y;
  123. var maxX = minX + GetWidth();
  124. var maxY = minY + GetHeight();
  125.  
  126. //遍历每一个连接的门, 计算计算canvas覆盖范围
  127. foreach (var doorInfo in Doors)
  128. {
  129. var connectDoor = doorInfo.ConnectDoor;
  130. switch (connectDoor.Direction)
  131. {
  132. case DoorDirection.E:
  133. case DoorDirection.W:
  134. {
  135. var (px1, py1) = connectDoor.GetWorldOriginPosition();
  136. var py2 = py1 + 4 * GameConfig.TileCellSize;
  137. if (px1 < minX)
  138. {
  139. minX = px1;
  140. }
  141. else if (px1 > maxX)
  142. {
  143. maxX = px1;
  144. }
  145.  
  146. if (py1 < minY)
  147. {
  148. minY = py1;
  149. }
  150. else if (py1 > maxY)
  151. {
  152. maxY = py1;
  153. }
  154. if (py2 < minY)
  155. {
  156. minY = py2;
  157. }
  158. else if (py2 > maxY)
  159. {
  160. maxY = py2;
  161. }
  162. }
  163. break;
  164. case DoorDirection.S:
  165. case DoorDirection.N:
  166. {
  167. var (px1, py1) = connectDoor.GetWorldOriginPosition();
  168. var px2 = px1 + 4 * GameConfig.TileCellSize;
  169. if (px1 < minX)
  170. {
  171. minX = px1;
  172. }
  173. else if (px1 > maxX)
  174. {
  175. maxX = px1;
  176. }
  177.  
  178. if (py1 < minY)
  179. {
  180. minY = py1;
  181. }
  182. else if (py1 > maxY)
  183. {
  184. maxY = py1;
  185. }
  186. if (px2 < minX)
  187. {
  188. minX = px2;
  189. }
  190. else if (px2 > maxX)
  191. {
  192. maxX = px2;
  193. }
  194. }
  195. break;
  196. }
  197. }
  198.  
  199. OuterRange = new Rect2I(minX, minY, maxX - minX, maxY - minY);
  200. }
  201. /// <summary>
  202. /// 获取房间的全局坐标, 单位: 像素
  203. /// </summary>
  204. public Vector2I GetWorldPosition()
  205. {
  206. return new Vector2I(
  207. Position.X * GameConfig.TileCellSize,
  208. Position.Y * GameConfig.TileCellSize
  209. );
  210. }
  211.  
  212. /// <summary>
  213. /// 获取房间左上角的 Tile 距离全局坐标原点的偏移, 单位: 像素
  214. /// </summary>
  215. /// <returns></returns>
  216. public Vector2I GetOffsetPosition()
  217. {
  218. return RoomSplit.RoomInfo.Position.AsVector2I() * GameConfig.TileCellSize;
  219. }
  220. /// <summary>
  221. /// 将房间配置中的坐标转为全局坐标, 单位: 像素
  222. /// </summary>
  223. public Vector2 ToGlobalPosition(Vector2 pos)
  224. {
  225. return GetWorldPosition() + pos - GetOffsetPosition();
  226. }
  227. /// <summary>
  228. /// 获取房间横轴结束位置, 单位: 格
  229. /// </summary>
  230. public int GetHorizontalEnd()
  231. {
  232. return Position.X + Size.X;
  233. }
  234.  
  235. /// <summary>
  236. /// 获取房间纵轴结束位置, 单位: 格
  237. /// </summary>
  238. public int GetVerticalEnd()
  239. {
  240. return Position.Y + Size.Y;
  241. }
  242. /// <summary>
  243. /// 获取房间横轴开始位置, 单位: 格
  244. /// </summary>
  245. public int GetHorizontalStart()
  246. {
  247. return Position.X;
  248. }
  249.  
  250. /// <summary>
  251. /// 获取房间纵轴开始位置, 单位: 格
  252. /// </summary>
  253. public int GetVerticalStart()
  254. {
  255. return Position.Y;
  256. }
  257.  
  258. /// <summary>
  259. /// 获取房间宽度, 单位: 像素
  260. /// </summary>
  261. public int GetWidth()
  262. {
  263. return Size.X * GameConfig.TileCellSize;
  264. }
  265. /// <summary>
  266. /// 获取房间高度, 单位: 像素
  267. /// </summary>
  268. public int GetHeight()
  269. {
  270. return Size.Y * GameConfig.TileCellSize;
  271. }
  272. /// <summary>
  273. /// 将世界坐标转为画布下的坐标
  274. /// </summary>
  275. public Vector2 ToImageCanvasPosition(Vector2 pos)
  276. {
  277. return pos - StaticImageCanvas.Position;
  278. }
  279. public void Destroy()
  280. {
  281. if (IsDestroyed)
  282. {
  283. return;
  284. }
  285.  
  286. IsDestroyed = true;
  287. //递归销毁下一个房间
  288. foreach (var nextRoom in Next)
  289. {
  290. nextRoom.Destroy();
  291. }
  292. Next.Clear();
  293. //销毁连接的门
  294. foreach (var roomDoorInfo in Doors)
  295. {
  296. roomDoorInfo.Destroy();
  297. }
  298. //销毁预设
  299. if (RoomPreinstall != null)
  300. {
  301. RoomPreinstall.Destroy();
  302. RoomPreinstall = null;
  303. }
  304. //销毁画布
  305. if (StaticImageCanvas != null)
  306. {
  307. StaticImageCanvas.Destroy();
  308. }
  309. //
  310. if (StaticSprite != null)
  311. {
  312. StaticSprite.Destroy();
  313. }
  314.  
  315. //销毁迷雾
  316. if (RoomFogMask != null)
  317. {
  318. RoomFogMask.Destroy();
  319. }
  320.  
  321. //销毁所属区域对象
  322. if (AffiliationArea != null)
  323. {
  324. AffiliationArea.Destroy();
  325. }
  326. MarkTargetPosition.Clear();
  327. }
  328. /// <summary>
  329. /// 加载地牢完成
  330. /// </summary>
  331. public void OnReady()
  332. {
  333. //提前加载波
  334. RoomPreinstall.OnReady();
  335. }
  336. /// <summary>
  337. /// 玩家第一次进入房间, 房间准备好了, 准备刷敌人, 并且关闭所有<br/>
  338. /// 当清完每一波刷新的敌人后即可开门
  339. /// </summary>
  340. public void OnFirstEnter()
  341. {
  342. if (RoomPreinstall.IsRunWave)
  343. {
  344. return;
  345. }
  346. //房间内有敌人, 或者会刷新敌人才会关门
  347. var hasEnemy = false;
  348. if (AffiliationArea.ExistEnterItem(activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy))) //先判断房间里面是否有敌人
  349. {
  350. hasEnemy = true;
  351. }
  352. else if (RoomPreinstall.HasEnemy()) //在判断是否会刷出敌人
  353. {
  354. hasEnemy = true;
  355. }
  356. if (!hasEnemy) //没有敌人, 不关门
  357. {
  358. IsSeclusion = false;
  359. //执行第一波生成
  360. RoomPreinstall.StartWave();
  361. return;
  362. }
  363.  
  364. //关门
  365. CloseDoor();
  366. IsSeclusion = true;
  367.  
  368. //执行第一波生成
  369. RoomPreinstall.StartWave();
  370. }
  371.  
  372. /// <summary>
  373. /// 当前房间所有敌人都被清除了
  374. /// </summary>
  375. public void OnClearRoom()
  376. {
  377. if (RoomPreinstall.IsLastWave) //所有 mark 都走完了
  378. {
  379. IsSeclusion = false;
  380. if (RoomPreinstall.HasEnemy())
  381. {
  382. //开门
  383. OpenDoor();
  384. }
  385. //所有标记执行完成
  386. RoomPreinstall.OverWave();
  387. }
  388. else //执行下一波
  389. {
  390. RoomPreinstall.NextWave();
  391. }
  392. }
  393.  
  394. /// <summary>
  395. /// 打开所有门
  396. /// </summary>
  397. public void OpenDoor()
  398. {
  399. if (!_openDoorFlag)
  400. {
  401. _openDoorFlag = true;
  402. AffiliationArea.RestoreRegion();
  403. }
  404. foreach (var doorInfo in Doors)
  405. {
  406. doorInfo.Door.OpenDoor();
  407. //过道迷雾
  408. doorInfo.AisleFogArea.Monitoring = true;
  409. if (doorInfo.AisleFogMask.IsExplored)
  410. {
  411. //doorInfo.ClearFog();
  412. FogMaskHandler.RefreshAisleFog(doorInfo);
  413. }
  414. }
  415. }
  416.  
  417. /// <summary>
  418. /// 关闭所有门
  419. /// </summary>
  420. public void CloseDoor()
  421. {
  422. if (_openDoorFlag)
  423. {
  424. _openDoorFlag = false;
  425. AffiliationArea.ExtendedRegion(new Vector2(GameConfig.TileCellSize * 4, GameConfig.TileCellSize * 4));
  426. }
  427.  
  428. foreach (var doorInfo in Doors)
  429. {
  430. doorInfo.Door.CloseDoor();
  431. //过道迷雾
  432. doorInfo.AisleFogArea.Monitoring = false;
  433. if (doorInfo.AisleFogMask.IsExplored)
  434. {
  435. //doorInfo.DarkFog();
  436. FogMaskHandler.RefreshAisleFog(doorInfo);
  437. }
  438. }
  439. }
  440. }