Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / DungeonRoomTemplate.cs
  1.  
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Text.Json;
  6. using Godot;
  7.  
  8. [Tool]
  9. public partial class DungeonRoomTemplate : TileMap
  10. {
  11. /// <summary>
  12. /// 地图路径
  13. /// </summary>
  14. public static readonly string RoomTileDir = System.Environment.CurrentDirectory + "\\resource\\map\\tileMaps\\";
  15. /// <summary>
  16. /// 地图描述数据路径
  17. /// </summary>
  18. public static readonly string RoomTileDataDir = System.Environment.CurrentDirectory + "\\resource\\map\\tiledata\\";
  19. /// <summary>
  20. /// 房间配置汇总
  21. /// </summary>
  22. public static readonly string RoomTileConfigFile = System.Environment.CurrentDirectory + "\\resource\\map\\RoomConfig.json";
  23. #if TOOLS
  24. //是否悬停在线上
  25. private bool _hover = false;
  26.  
  27. //悬停点
  28. private Vector2 _hoverPoint1;
  29. private Vector2 _hoverPoint2;
  30. private DoorDirection _hoverDirection;
  31. private bool _canPut = false;
  32.  
  33. //选中点
  34. private bool _hasActivePoint = false;
  35. //选中左/右点
  36. private byte _activePointType = 0;
  37. private DoorAreaInfo _activeArea = null;
  38. //拖拽
  39. private bool _isDrag = false;
  40. private float _startDragValue;
  41. private Vector2 _startDragPositionValue;
  42. private bool _dragHasCollision = false;
  43.  
  44. private bool _mouseDown = false;
  45.  
  46. //
  47. private List<DoorAreaInfo> _doorConfigs;
  48. private Rect2 _prevRect;
  49. public override void _Process(double delta)
  50. {
  51. if (!Engine.IsEditorHint())
  52. {
  53. return;
  54. }
  55.  
  56. var initConfigs = false;
  57. if (_doorConfigs == null)
  58. {
  59. initConfigs = true;
  60. _doorConfigs = ReadConfig(CalcTileRange(this), Name);
  61. }
  62. var isClick = false;
  63. if (Input.IsMouseButtonPressed(MouseButton.Left))
  64. {
  65. if (!_mouseDown)
  66. {
  67. _mouseDown = true;
  68. isClick = true;
  69. }
  70. }
  71. else if (_mouseDown)
  72. {
  73. _mouseDown = false;
  74. isClick = false;
  75. }
  76.  
  77. if (Input.IsMouseButtonPressed(MouseButton.Middle)) //中键移除门
  78. {
  79. if (_activeArea != null)
  80. {
  81. RemoveDoorArea(_activeArea);
  82. _hasActivePoint = false;
  83. _activeArea = null;
  84. }
  85. }
  86. else if (TileSet != null)
  87. {
  88. var mapRect = CalcTileRange(this);
  89. var mousePosition = GetLocalMousePosition();
  90. if (mapRect != _prevRect)
  91. {
  92. if (!initConfigs)
  93. {
  94. OnMapRectChange();
  95. }
  96. }
  97. _prevRect = mapRect;
  98. var tileSize = TileSet.TileSize;
  99. if (_isDrag) //拖拽中
  100. {
  101. if (_activeArea != null)
  102. {
  103. //拖拽节点操作
  104. if (_activeArea.Direction == DoorDirection.N || _activeArea.Direction == DoorDirection.S)
  105. {
  106. if (_activePointType == 0)
  107. {
  108. var mouseOffset = Approach(mousePosition.X, tileSize.X);
  109. _activeArea.StartPosition = new Vector2(mouseOffset, _activeArea.StartPosition.Y);
  110. _activeArea.Start = mouseOffset - mapRect.Position.X;
  111. _dragHasCollision = _activeArea.StartPosition.X <= mapRect.Position.X ||
  112. _activeArea.StartPosition.X + 3 * tileSize.X >= _activeArea.EndPosition.X ||
  113. CheckDoorCollision(_activeArea.Direction, _activeArea);
  114. }
  115. else
  116. {
  117. var mouseOffset = Approach(mousePosition.X, tileSize.X);
  118. _activeArea.EndPosition = new Vector2(mouseOffset, _activeArea.EndPosition.Y);
  119. _activeArea.End = mouseOffset - mapRect.Position.X;
  120. _dragHasCollision = _activeArea.EndPosition.X >= mapRect.Position.X + mapRect.Size.X ||
  121. _activeArea.EndPosition.X - 3 * tileSize.X <= _activeArea.StartPosition.X ||
  122. CheckDoorCollision(_activeArea.Direction, _activeArea);
  123. }
  124. }
  125. else
  126. {
  127. if (_activePointType == 0)
  128. {
  129. var mouseOffset = Approach(mousePosition.Y, tileSize.Y);
  130. _activeArea.StartPosition = new Vector2(_activeArea.StartPosition.X, mouseOffset);
  131. _activeArea.Start = mouseOffset - mapRect.Position.Y;
  132. _dragHasCollision = _activeArea.StartPosition.Y <= mapRect.Position.Y ||
  133. _activeArea.StartPosition.Y + 3 * tileSize.Y >= _activeArea.EndPosition.Y ||
  134. CheckDoorCollision(_activeArea.Direction, _activeArea);
  135. }
  136. else
  137. {
  138. var mouseOffset = Approach(mousePosition.Y, tileSize.Y);
  139. _activeArea.EndPosition = new Vector2(_activeArea.EndPosition.X, mouseOffset);
  140. _activeArea.End = mouseOffset - mapRect.Position.Y;
  141. _dragHasCollision = _activeArea.EndPosition.Y >= mapRect.Position.Y + mapRect.Size.Y ||
  142. _activeArea.EndPosition.Y - 3 * tileSize.Y <= _activeArea.StartPosition.Y ||
  143. CheckDoorCollision(_activeArea.Direction, _activeArea);
  144. }
  145. }
  146. }
  147. }
  148. else
  149. {
  150. if (Mathf.Abs(mousePosition.Y - mapRect.Position.Y) <= 8 && mousePosition.X >= mapRect.Position.X &&
  151. mousePosition.X <= mapRect.Position.X + mapRect.Size.X) //上
  152. {
  153. _hover = true;
  154. _hoverDirection = DoorDirection.N;
  155. var mouseOffset = Approach(mousePosition.X, tileSize.X);
  156. _hoverPoint1 = new Vector2(mouseOffset - tileSize.X * 2, mapRect.Position.Y);
  157. _hoverPoint2 = new Vector2(_hoverPoint1.X + tileSize.X * 4, _hoverPoint1.Y);
  158.  
  159. //判断是否能放下新的门
  160. if (_hoverPoint1.X <= mapRect.Position.X || _hoverPoint2.X >= mapRect.Position.X + mapRect.Size.X ||
  161. CheckDoorCollision())
  162. {
  163. _canPut = false;
  164. FindHoverPoint(mouseOffset);
  165. }
  166. else
  167. {
  168. _canPut = true;
  169. _hasActivePoint = false;
  170. _activeArea = null;
  171. }
  172. }
  173. else if (Mathf.Abs(mousePosition.X - mapRect.Position.X) <= 8 &&
  174. mousePosition.Y >= mapRect.Position.Y &&
  175. mousePosition.Y <= mapRect.Position.Y + mapRect.Size.Y) //左
  176. {
  177. _hover = true;
  178. _hoverDirection = DoorDirection.W;
  179. var mouseOffset = Approach(mousePosition.Y, tileSize.Y);
  180. _hoverPoint1 = new Vector2(mapRect.Position.X, mouseOffset - tileSize.Y * 2);
  181. _hoverPoint2 = new Vector2(_hoverPoint1.X, _hoverPoint1.Y + tileSize.X * 4);
  182.  
  183. //判断是否能放下新的门
  184. if (_hoverPoint1.Y <= mapRect.Position.Y || _hoverPoint2.Y >= mapRect.Position.Y + mapRect.Size.Y ||
  185. CheckDoorCollision())
  186. {
  187. _canPut = false;
  188. FindHoverPoint(mouseOffset);
  189. }
  190. else
  191. {
  192. _canPut = true;
  193. _hasActivePoint = false;
  194. _activeArea = null;
  195. }
  196. }
  197. else if (Mathf.Abs(mousePosition.Y - (mapRect.Position.Y + mapRect.Size.Y)) <= 8 &&
  198. mousePosition.X >= mapRect.Position.X &&
  199. mousePosition.X <= mapRect.Position.X + mapRect.Size.X) //下
  200. {
  201. _hover = true;
  202. _hoverDirection = DoorDirection.S;
  203. var mouseOffset = Approach(mousePosition.X, tileSize.X);
  204. _hoverPoint1 = new Vector2(mouseOffset - tileSize.X * 2,
  205. mapRect.Position.Y + mapRect.Size.Y);
  206. _hoverPoint2 = new Vector2(_hoverPoint1.X + tileSize.X * 4, _hoverPoint1.Y);
  207.  
  208. //判断是否能放下新的门
  209. if (_hoverPoint1.X <= mapRect.Position.X || _hoverPoint2.X >= mapRect.Position.X + mapRect.Size.X ||
  210. CheckDoorCollision())
  211. {
  212. _canPut = false;
  213. FindHoverPoint(mouseOffset);
  214. }
  215. else
  216. {
  217. _canPut = true;
  218. _hasActivePoint = false;
  219. _activeArea = null;
  220. }
  221. }
  222. else if (Mathf.Abs(mousePosition.X - (mapRect.Position.X + mapRect.Size.X)) <= 8 &&
  223. mousePosition.Y >= mapRect.Position.Y &&
  224. mousePosition.Y <= mapRect.Position.Y + mapRect.Size.Y) //右
  225. {
  226. _hover = true;
  227. _hoverDirection = DoorDirection.E;
  228. var mouseOffset = Approach(mousePosition.Y, tileSize.Y);
  229. _hoverPoint1 = new Vector2(mapRect.Position.X + mapRect.Size.X,
  230. mouseOffset - tileSize.Y * 2);
  231. _hoverPoint2 = new Vector2(_hoverPoint1.X, _hoverPoint1.Y + tileSize.X * 4);
  232.  
  233. //判断是否能放下新的门
  234. if (_hoverPoint1.Y <= mapRect.Position.Y || _hoverPoint2.Y >= mapRect.Position.Y + mapRect.Size.Y ||
  235. CheckDoorCollision())
  236. {
  237. _canPut = false;
  238. FindHoverPoint(mouseOffset);
  239. }
  240. else
  241. {
  242. _canPut = true;
  243. _hasActivePoint = false;
  244. _activeArea = null;
  245. }
  246. }
  247. else
  248. {
  249. _hover = false;
  250. _canPut = false;
  251. _hasActivePoint = false;
  252. _activeArea = null;
  253. }
  254. }
  255.  
  256. if (isClick && _canPut) //判断是否可以创建新的点
  257. {
  258. CreateDoorArea(mapRect);
  259. }
  260. else if (_mouseDown && !_isDrag) //拖拽节点
  261. {
  262. _isDrag = true;
  263. _dragHasCollision = false;
  264. if (_activeArea != null)
  265. {
  266. if (_activePointType == 0)
  267. {
  268. _startDragValue = _activeArea.Start;
  269. _startDragPositionValue = _activeArea.StartPosition;
  270. }
  271. else
  272. {
  273. _startDragValue = _activeArea.End;
  274. _startDragPositionValue = _activeArea.EndPosition;
  275. }
  276. }
  277. }
  278. else if (!_mouseDown && _isDrag) //松开拖拽的点
  279. {
  280. _isDrag = false;
  281. if (_activeArea != null) //提交拖拽结果
  282. {
  283. if (_dragHasCollision)
  284. {
  285. if (_activePointType == 0)
  286. {
  287. _activeArea.Start = _startDragValue;
  288. _activeArea.StartPosition = _startDragPositionValue;
  289. }
  290. else
  291. {
  292. _activeArea.End = _startDragValue;
  293. _activeArea.EndPosition = _startDragPositionValue;
  294. }
  295. }
  296. OnDoorAreaChange();
  297. }
  298.  
  299. _dragHasCollision = false;
  300. }
  301. QueueRedraw();
  302. }
  303. else
  304. {
  305. _hover = false;
  306. _canPut = false;
  307. _hasActivePoint = false;
  308. _activeArea = null;
  309. }
  310. }
  311.  
  312. public override void _Draw()
  313. {
  314. if (!Engine.IsEditorHint())
  315. {
  316. return;
  317. }
  318. if (TileSet != null)
  319. {
  320. //绘制地图轮廓
  321. var mapRange = CalcTileRange(this);
  322. mapRange.Position -= new Vector2(2, 2);
  323. mapRange.Size += new Vector2(4, 4);
  324. DrawRect(mapRange, _hover ? Colors.Green : new Color(0.03137255F, 0.59607846F, 0.03137255F), false, 2);
  325.  
  326. //绘制悬停
  327. if (_hover && !_isDrag)
  328. {
  329. if (!_hasActivePoint) //这里判断是否悬停在拖动点上
  330. {
  331. var color = _canPut ? new Color(0, 1, 0, 0.2f) : new Color(1, 0, 0, 0.2f);
  332. switch (_hoverDirection)
  333. {
  334. case DoorDirection.E:
  335. DrawRect(
  336. new Rect2(new Vector2(_hoverPoint1.X + 2, _hoverPoint1.Y), 30,
  337. _hoverPoint2.Y - _hoverPoint1.Y), color);
  338. DrawCircle(new Vector2(_hoverPoint1.X + 2, _hoverPoint1.Y), 5, color);
  339. DrawCircle(new Vector2(_hoverPoint2.X + 2, _hoverPoint2.Y), 5, color);
  340. break;
  341. case DoorDirection.W:
  342. DrawRect(
  343. new Rect2(new Vector2(_hoverPoint1.X - 2 - 30, _hoverPoint1.Y), 30,
  344. _hoverPoint2.Y - _hoverPoint1.Y), color);
  345. DrawCircle(new Vector2(_hoverPoint1.X - 2, _hoverPoint1.Y), 5, color);
  346. DrawCircle(new Vector2(_hoverPoint2.X - 2, _hoverPoint2.Y), 5, color);
  347. break;
  348. case DoorDirection.S:
  349. DrawRect(
  350. new Rect2(new Vector2(_hoverPoint1.X, _hoverPoint1.Y + 2),
  351. _hoverPoint2.X - _hoverPoint1.X, 30), color);
  352. DrawCircle(new Vector2(_hoverPoint1.X, _hoverPoint1.Y + 2), 5, color);
  353. DrawCircle(new Vector2(_hoverPoint2.X, _hoverPoint2.Y + 2), 5, color);
  354. break;
  355. case DoorDirection.N:
  356. DrawRect(
  357. new Rect2(new Vector2(_hoverPoint1.X, _hoverPoint1.Y - 30 - 2),
  358. _hoverPoint2.X - _hoverPoint1.X, 30), color);
  359. DrawCircle(new Vector2(_hoverPoint1.X, _hoverPoint1.Y - 2), 5, color);
  360. DrawCircle(new Vector2(_hoverPoint2.X, _hoverPoint2.Y - 2), 5, color);
  361. break;
  362. }
  363. }
  364. }
  365.  
  366. if (_doorConfigs != null)
  367. {
  368. var color2 = new Color(0, 1, 0, 0.8f);
  369. //绘制已经存在的
  370. foreach (var doorAreaInfo in _doorConfigs)
  371. {
  372. var flag = _hasActivePoint && _activeArea == doorAreaInfo;
  373. var color3 = (flag && _activePointType == 0)
  374. ? (_isDrag
  375. ? (_dragHasCollision
  376. ? new Color(1, 0, 0, 0.8f)
  377. : new Color(0.2F, 0.4117647F, 0.8392157F, 0.8f))
  378. : new Color(1, 1, 1, 0.8f))
  379. : color2;
  380. var color4 = (flag && _activePointType == 1)
  381. ? (_isDrag
  382. ? (_dragHasCollision
  383. ? new Color(1, 0, 0, 0.8f)
  384. : new Color(0.2F, 0.4117647F, 0.8392157F, 0.8f))
  385. : new Color(1, 1, 1, 0.8f))
  386. : color2;
  387. switch (doorAreaInfo.Direction)
  388. {
  389. case DoorDirection.E:
  390. DrawRect(
  391. new Rect2(
  392. new Vector2(mapRange.Position.X + mapRange.Size.X,
  393. mapRange.Position.Y + doorAreaInfo.Start + 2), 30,
  394. doorAreaInfo.End - doorAreaInfo.Start), color2);
  395. DrawCircle(
  396. new Vector2(mapRange.Position.X + mapRange.Size.X,
  397. mapRange.Position.Y + doorAreaInfo.Start + 2), 5, color3);
  398. DrawCircle(
  399. new Vector2(mapRange.Position.X + mapRange.Size.X,
  400. mapRange.Position.Y + doorAreaInfo.End + 2),
  401. 5, color4);
  402. break;
  403. case DoorDirection.W:
  404. DrawRect(
  405. new Rect2(
  406. new Vector2(mapRange.Position.X - 30, mapRange.Position.Y + doorAreaInfo.Start + 2),
  407. 30, doorAreaInfo.End - doorAreaInfo.Start), color2);
  408. DrawCircle(new Vector2(mapRange.Position.X, mapRange.Position.Y + doorAreaInfo.Start + 2),
  409. 5,
  410. color3);
  411. DrawCircle(new Vector2(mapRange.Position.X, mapRange.Position.Y + doorAreaInfo.End + 2), 5,
  412. color4);
  413. break;
  414. case DoorDirection.S:
  415. DrawRect(
  416. new Rect2(
  417. new Vector2(mapRange.Position.X + doorAreaInfo.Start + 2,
  418. mapRange.Position.Y + mapRange.Size.Y), doorAreaInfo.End - doorAreaInfo.Start,
  419. 30),
  420. color2);
  421. DrawCircle(
  422. new Vector2(mapRange.Position.X + doorAreaInfo.Start + 2,
  423. mapRange.Position.Y + mapRange.Size.Y), 5, color3);
  424. DrawCircle(
  425. new Vector2(mapRange.Position.X + doorAreaInfo.End + 2,
  426. mapRange.Position.Y + mapRange.Size.Y),
  427. 5, color4);
  428. break;
  429. case DoorDirection.N:
  430. DrawRect(
  431. new Rect2(
  432. new Vector2(mapRange.Position.X + doorAreaInfo.Start + 2, mapRange.Position.Y - 30),
  433. doorAreaInfo.End - doorAreaInfo.Start, 30), color2);
  434. DrawCircle(new Vector2(mapRange.Position.X + doorAreaInfo.Start + 2, mapRange.Position.Y),
  435. 5,
  436. color3);
  437. DrawCircle(new Vector2(mapRange.Position.X + doorAreaInfo.End + 2, mapRange.Position.Y), 5,
  438. color4);
  439. break;
  440. }
  441. }
  442. }
  443. }
  444. }
  445.  
  446. //创建门
  447. private void CreateDoorArea(Rect2 mapRect)
  448. {
  449. var doorAreaInfo = new DoorAreaInfo();
  450. doorAreaInfo.Direction = _hoverDirection;
  451. doorAreaInfo.StartPosition = _hoverPoint1;
  452. doorAreaInfo.EndPosition = _hoverPoint2;
  453. switch (_hoverDirection)
  454. {
  455. case DoorDirection.E:
  456. case DoorDirection.W:
  457. doorAreaInfo.Start = _hoverPoint1.Y - mapRect.Position.Y;
  458. doorAreaInfo.End = _hoverPoint2.Y - mapRect.Position.Y;
  459. break;
  460. case DoorDirection.N:
  461. case DoorDirection.S:
  462. doorAreaInfo.Start = _hoverPoint1.X - mapRect.Position.X;
  463. doorAreaInfo.End = _hoverPoint2.X - mapRect.Position.X;
  464. break;
  465. }
  466.  
  467. _doorConfigs.Add(doorAreaInfo);
  468. OnDoorAreaChange();
  469. }
  470.  
  471. //移除门
  472. private void RemoveDoorArea(DoorAreaInfo doorAreaInfo)
  473. {
  474. _doorConfigs.Remove(doorAreaInfo);
  475. OnDoorAreaChange();
  476. }
  477.  
  478. //检查门是否有碰撞
  479. private bool CheckDoorCollision()
  480. {
  481. foreach (var doorAreaInfo in _doorConfigs)
  482. {
  483. if (doorAreaInfo.Direction == _hoverDirection)
  484. {
  485. switch (_hoverDirection)
  486. {
  487. case DoorDirection.E:
  488. case DoorDirection.W:
  489. if (CheckValueCollision(doorAreaInfo.StartPosition.Y, doorAreaInfo.EndPosition.Y, _hoverPoint1.Y, _hoverPoint2.Y))
  490. {
  491. return true;
  492. }
  493. break;
  494. case DoorDirection.S:
  495. case DoorDirection.N:
  496. if (CheckValueCollision(doorAreaInfo.StartPosition.X, doorAreaInfo.EndPosition.X, _hoverPoint1.X, _hoverPoint2.X))
  497. {
  498. return true;
  499. }
  500. break;
  501. }
  502. }
  503. }
  504.  
  505. return false;
  506. }
  507.  
  508. //检查门是否有碰撞
  509. private bool CheckDoorCollision(DoorDirection direction, DoorAreaInfo info)
  510. {
  511. foreach (var doorAreaInfo in _doorConfigs)
  512. {
  513. if (doorAreaInfo.Direction == direction && info != doorAreaInfo &&
  514. CheckValueCollision(doorAreaInfo.Start, doorAreaInfo.End, info.Start, info.End))
  515. {
  516. return true;
  517. }
  518. }
  519.  
  520. return false;
  521. }
  522. private bool CheckValueCollision(float o1, float o2, float h1, float h2)
  523. {
  524. var size = TileSet.TileSize.X;
  525. return !(h2 < o1 - 3 * size || o2 + 3 * size < h1);
  526. }
  527.  
  528. private void FindHoverPoint(float mouseOffset)
  529. {
  530. if (_isDrag)
  531. {
  532. return;
  533. }
  534. //检测是否有碰撞的点
  535. var flag = false;
  536. foreach (var doorAreaInfo in _doorConfigs)
  537. {
  538. if (doorAreaInfo.Direction == _hoverDirection)
  539. {
  540. if (_hoverDirection == DoorDirection.N || _hoverDirection == DoorDirection.S)
  541. {
  542. if (Math.Abs(doorAreaInfo.StartPosition.X - mouseOffset) < 0.0001f)
  543. {
  544. _hasActivePoint = true;
  545. _activePointType = 0;
  546. _activeArea = doorAreaInfo;
  547. flag = true;
  548. break;
  549. }
  550. else if (Math.Abs(doorAreaInfo.EndPosition.X - mouseOffset) < 0.0001f)
  551. {
  552. _hasActivePoint = true;
  553. _activePointType = 1;
  554. _activeArea = doorAreaInfo;
  555. flag = true;
  556. break;
  557. }
  558. }
  559. else
  560. {
  561. if (Math.Abs(doorAreaInfo.StartPosition.Y - mouseOffset) < 0.0001f)
  562. {
  563. _hasActivePoint = true;
  564. _activePointType = 0;
  565. _activeArea = doorAreaInfo;
  566. flag = true;
  567. break;
  568. }
  569. else if (Math.Abs(doorAreaInfo.EndPosition.Y - mouseOffset) < 0.0001f)
  570. {
  571. _hasActivePoint = true;
  572. _activePointType = 1;
  573. _activeArea = doorAreaInfo;
  574. flag = true;
  575. break;
  576. }
  577. }
  578. }
  579. }
  580.  
  581. if (!flag)
  582. {
  583. _hasActivePoint = false;
  584. _activeArea = null;
  585. }
  586. }
  587.  
  588. private float Approach(float value, float period)
  589. {
  590. var temp = value % period;
  591. if (Mathf.Abs(temp) >= period / 2)
  592. {
  593. return ((int)(value / period) + (value >= 0 ? 1 : -1)) * period;
  594. }
  595.  
  596. return (int)(value / period) * period;
  597. }
  598.  
  599. //地图大小改变
  600. private void OnMapRectChange()
  601. {
  602. _doorConfigs.Clear();
  603. _canPut = false;
  604. _hasActivePoint = false;
  605. _activeArea = null;
  606. OnDoorAreaChange();
  607. }
  608.  
  609. //区域数据修改
  610. private void OnDoorAreaChange()
  611. {
  612. var rect = GetUsedRect();
  613. SaveConfig(_doorConfigs, rect.Position, rect.Size, Name);
  614. }
  615. /// <summary>
  616. /// 计算tile所占区域
  617. /// </summary>
  618. /// <returns></returns>
  619. public static Rect2 CalcTileRange(TileMap tileMap)
  620. {
  621. var usedRect = tileMap.GetUsedRect();
  622. var pos = usedRect.Position * tileMap.TileSet.TileSize;
  623. var size = usedRect.Size * tileMap.TileSet.TileSize;
  624. return new Rect2(tileMap.ToLocal(pos), size);
  625. }
  626. /// <summary>
  627. /// 保存房间配置
  628. /// </summary>
  629. public static void SaveConfig(List<DoorAreaInfo> doorConfigs, Vector2I position, Vector2I size, string name)
  630. {
  631. //存入本地
  632. var path = RoomTileDataDir + name + ".json";
  633. var roomInfo = new DungeonRoomInfo();
  634. roomInfo.Position = new SerializeVector2(position);
  635. roomInfo.Size = new SerializeVector2(size);
  636. roomInfo.DoorAreaInfos = doorConfigs;
  637. var config = new JsonSerializerOptions();
  638. config.WriteIndented = true;
  639. var jsonStr = JsonSerializer.Serialize(roomInfo, config);
  640. File.WriteAllText(path, jsonStr);
  641. }
  642.  
  643. /// <summary>
  644. /// 读取房间配置
  645. /// </summary>
  646. public static List<DoorAreaInfo> ReadConfig(Rect2 mapRect, string name)
  647. {
  648. var path = RoomTileDataDir + name + ".json";
  649. if (File.Exists(path))
  650. {
  651. var text = File.ReadAllText(path);
  652. try
  653. {
  654. var roomInfo = DeserializeDungeonRoomInfo(text);
  655. //填充 StartPosition 和 EndPosition 数据
  656. foreach (var doorAreaInfo in roomInfo.DoorAreaInfos)
  657. {
  658. doorAreaInfo.CalcPosition(mapRect.Position, mapRect.Size);
  659. }
  660. return roomInfo.DoorAreaInfos;
  661. }
  662. catch (Exception e)
  663. {
  664. GD.PrintErr($"加载房间数据'{path}'发生异常: " + e);
  665. return new List<DoorAreaInfo>();
  666. }
  667. }
  668. else
  669. {
  670. return new List<DoorAreaInfo>();
  671. }
  672. }
  673.  
  674. /// <summary>
  675. /// 反序列化 DungeonRoomInfo
  676. /// </summary>
  677. public static DungeonRoomInfo DeserializeDungeonRoomInfo(string text)
  678. {
  679. // 下面这句代码在 Godot4.0_rc2的编辑器模式下, 重载脚本会导致编辑器一直报错!, 所以暂时先用下面的方法
  680. //var roomInfo = JsonSerializer.Deserialize<DungeonRoomInfo>(text);
  681. var obj = Json.ParseString(text).AsGodotDictionary();
  682. var roomInfo = new DungeonRoomInfo();
  683. var position = obj["Position"].AsGodotDictionary();
  684. roomInfo.Position = new SerializeVector2(position["X"].AsInt32(), position["Y"].AsInt32());
  685. var size = obj["Size"].AsGodotDictionary();
  686. roomInfo.Size = new SerializeVector2(size["X"].AsInt32(), size["Y"].AsInt32());
  687. var doorAreaInfos = obj["DoorAreaInfos"].AsGodotArray<Variant>();
  688. roomInfo.DoorAreaInfos = new List<DoorAreaInfo>();
  689. foreach (var item in doorAreaInfos)
  690. {
  691. var temp = item.AsGodotDictionary();
  692. var doorInfo = new DoorAreaInfo();
  693. doorInfo.Direction = (DoorDirection)temp["Direction"].AsInt32();
  694. doorInfo.Start = temp["Start"].AsInt32();
  695. doorInfo.End = temp["End"].AsInt32();
  696. roomInfo.DoorAreaInfos.Add(doorInfo);
  697. }
  698.  
  699. return roomInfo;
  700. }
  701. #endif
  702. }