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