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