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