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