Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / DungeonRoomTemplate.cs
@小李xl 小李xl on 17 Jul 2023 36 KB 保存房间大小位置数据
  1. /*
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text.Json;
  7. using Generator;
  8. using Godot;
  9.  
  10. [Tool]
  11. public partial class DungeonRoomTemplate : TileMap
  12. {
  13. /// <summary>
  14. /// 是否启用编辑模式
  15. /// </summary>
  16. [Export]
  17. public bool EnableEdit = false;
  18.  
  19. /// <summary>
  20. /// 房间权重, 值越大, 生成地牢是越容易出现该房间
  21. /// </summary>
  22. [Export(PropertyHint.Range, "1, 500")]
  23. public int Weight
  24. {
  25. get => _weight;
  26. set
  27. {
  28. _weight = value;
  29. _changeWeight = true;
  30. _changeWeightTimer = 0;
  31. }
  32. }
  33. private int _weight = DefaultWeight;
  34. private bool _changeWeight = false;
  35. private float _changeWeightTimer = 0;
  36.  
  37. #if TOOLS
  38. //是否悬停在线上
  39. private bool _hover = false;
  40.  
  41. //悬停点
  42. private Vector2 _hoverPoint1;
  43. private Vector2 _hoverPoint2;
  44. private DoorDirection _hoverDirection;
  45. private bool _canPut = false;
  46.  
  47. //选中点
  48. private bool _hasActivePoint = false;
  49. //选中左/右点
  50. private byte _activePointType = 0;
  51. private DoorAreaInfo _activeArea = null;
  52.  
  53. //拖拽
  54. private bool _isDrag = false;
  55. private float _startDragValue;
  56. private Vector2 _startDragPositionValue;
  57. private bool _dragHasCollision = false;
  58.  
  59. private bool _mouseDown = false;
  60.  
  61. //房间配置
  62. private DungeonRoomInfo _dungeonRoomInfo;
  63. private Rect2 _prevRect;
  64.  
  65. //是否能是否按下
  66. private bool _clickSave = false;
  67.  
  68. private DungeonTileMap _dungeonTileMap;
  69. private TileDrawHandler _tileDrawHandler;
  70.  
  71. //计算导航的计时器
  72. private float _calcTileNavTimer = 0;
  73.  
  74. private partial class TileDrawHandler : Node2D
  75. {
  76. public DungeonRoomTemplate RoomTemplate;
  77.  
  78. public override void _Draw()
  79. {
  80. if (!Engine.IsEditorHint() || RoomTemplate == null)
  81. {
  82. return;
  83. }
  84. if (RoomTemplate.TileSet != null)
  85. {
  86. //绘制地图轮廓
  87. var mapRange = CalcTileRange(RoomTemplate);
  88. mapRange.Position -= new Vector2(2, 2);
  89. mapRange.Size += new Vector2(4, 4);
  90. DrawRect(mapRange, RoomTemplate._hover ? Colors.Green : new Color(0.03137255F, 0.59607846F, 0.03137255F), false, 2);
  91.  
  92. //绘制悬停
  93. if (RoomTemplate._hover && !RoomTemplate._isDrag)
  94. {
  95. if (!RoomTemplate._hasActivePoint) //这里判断是否悬停在拖动点上
  96. {
  97. var color = RoomTemplate._canPut ? new Color(0, 1, 0, 0.2f) : new Color(1, 0, 0, 0.2f);
  98. switch (RoomTemplate._hoverDirection)
  99. {
  100. case DoorDirection.E:
  101. DrawRect(
  102. new Rect2(new Vector2(RoomTemplate._hoverPoint1.X + 2, RoomTemplate._hoverPoint1.Y), 30,
  103. RoomTemplate._hoverPoint2.Y - RoomTemplate._hoverPoint1.Y), color);
  104. DrawCircle(new Vector2(RoomTemplate._hoverPoint1.X + 2, RoomTemplate._hoverPoint1.Y), 5, color);
  105. DrawCircle(new Vector2(RoomTemplate._hoverPoint2.X + 2, RoomTemplate._hoverPoint2.Y), 5, color);
  106. break;
  107. case DoorDirection.W:
  108. DrawRect(
  109. new Rect2(new Vector2(RoomTemplate._hoverPoint1.X - 2 - 30, RoomTemplate._hoverPoint1.Y), 30,
  110. RoomTemplate._hoverPoint2.Y - RoomTemplate._hoverPoint1.Y), color);
  111. DrawCircle(new Vector2(RoomTemplate._hoverPoint1.X - 2, RoomTemplate._hoverPoint1.Y), 5, color);
  112. DrawCircle(new Vector2(RoomTemplate._hoverPoint2.X - 2, RoomTemplate._hoverPoint2.Y), 5, color);
  113. break;
  114. case DoorDirection.S:
  115. DrawRect(
  116. new Rect2(new Vector2(RoomTemplate._hoverPoint1.X, RoomTemplate._hoverPoint1.Y + 2),
  117. RoomTemplate._hoverPoint2.X - RoomTemplate._hoverPoint1.X, 30), color);
  118. DrawCircle(new Vector2(RoomTemplate._hoverPoint1.X, RoomTemplate._hoverPoint1.Y + 2), 5, color);
  119. DrawCircle(new Vector2(RoomTemplate._hoverPoint2.X, RoomTemplate._hoverPoint2.Y + 2), 5, color);
  120. break;
  121. case DoorDirection.N:
  122. DrawRect(
  123. new Rect2(new Vector2(RoomTemplate._hoverPoint1.X, RoomTemplate._hoverPoint1.Y - 30 - 2),
  124. RoomTemplate._hoverPoint2.X - RoomTemplate._hoverPoint1.X, 30), color);
  125. DrawCircle(new Vector2(RoomTemplate._hoverPoint1.X, RoomTemplate._hoverPoint1.Y - 2), 5, color);
  126. DrawCircle(new Vector2(RoomTemplate._hoverPoint2.X, RoomTemplate._hoverPoint2.Y - 2), 5, color);
  127. break;
  128. }
  129. }
  130. }
  131.  
  132. //绘制区域
  133. if (RoomTemplate._dungeonRoomInfo != null && RoomTemplate._dungeonRoomInfo.DoorAreaInfos != null)
  134. {
  135. var color2 = new Color(0, 1, 0, 0.8f);
  136. //绘制已经存在的
  137. foreach (var doorAreaInfo in RoomTemplate._dungeonRoomInfo.DoorAreaInfos)
  138. {
  139. var flag = RoomTemplate._hasActivePoint && RoomTemplate._activeArea == doorAreaInfo;
  140. var color3 = (flag && RoomTemplate._activePointType == 0)
  141. ? (RoomTemplate._isDrag
  142. ? (RoomTemplate._dragHasCollision
  143. ? new Color(1, 0, 0, 0.8f)
  144. : new Color(0.2F, 0.4117647F, 0.8392157F, 0.8f))
  145. : new Color(1, 1, 1, 0.8f))
  146. : color2;
  147. var color4 = (flag && RoomTemplate._activePointType == 1)
  148. ? (RoomTemplate._isDrag
  149. ? (RoomTemplate._dragHasCollision
  150. ? new Color(1, 0, 0, 0.8f)
  151. : new Color(0.2F, 0.4117647F, 0.8392157F, 0.8f))
  152. : new Color(1, 1, 1, 0.8f))
  153. : color2;
  154. switch (doorAreaInfo.Direction)
  155. {
  156. case DoorDirection.E:
  157. DrawRect(
  158. new Rect2(
  159. new Vector2(mapRange.Position.X + mapRange.Size.X,
  160. mapRange.Position.Y + doorAreaInfo.Start + 2), 30,
  161. doorAreaInfo.End - doorAreaInfo.Start), color2);
  162. DrawCircle(
  163. new Vector2(mapRange.Position.X + mapRange.Size.X,
  164. mapRange.Position.Y + doorAreaInfo.Start + 2), 5, color3);
  165. DrawCircle(
  166. new Vector2(mapRange.Position.X + mapRange.Size.X,
  167. mapRange.Position.Y + doorAreaInfo.End + 2),
  168. 5, color4);
  169. break;
  170. case DoorDirection.W:
  171. DrawRect(
  172. new Rect2(
  173. new Vector2(mapRange.Position.X - 30, mapRange.Position.Y + doorAreaInfo.Start + 2),
  174. 30, doorAreaInfo.End - doorAreaInfo.Start), color2);
  175. DrawCircle(new Vector2(mapRange.Position.X, mapRange.Position.Y + doorAreaInfo.Start + 2),
  176. 5,
  177. color3);
  178. DrawCircle(new Vector2(mapRange.Position.X, mapRange.Position.Y + doorAreaInfo.End + 2), 5,
  179. color4);
  180. break;
  181. case DoorDirection.S:
  182. DrawRect(
  183. new Rect2(
  184. new Vector2(mapRange.Position.X + doorAreaInfo.Start + 2,
  185. mapRange.Position.Y + mapRange.Size.Y), doorAreaInfo.End - doorAreaInfo.Start,
  186. 30),
  187. color2);
  188. DrawCircle(
  189. new Vector2(mapRange.Position.X + doorAreaInfo.Start + 2,
  190. mapRange.Position.Y + mapRange.Size.Y), 5, color3);
  191. DrawCircle(
  192. new Vector2(mapRange.Position.X + doorAreaInfo.End + 2,
  193. mapRange.Position.Y + mapRange.Size.Y),
  194. 5, color4);
  195. break;
  196. case DoorDirection.N:
  197. DrawRect(
  198. new Rect2(
  199. new Vector2(mapRange.Position.X + doorAreaInfo.Start + 2, mapRange.Position.Y - 30),
  200. doorAreaInfo.End - doorAreaInfo.Start, 30), color2);
  201. DrawCircle(new Vector2(mapRange.Position.X + doorAreaInfo.Start + 2, mapRange.Position.Y),
  202. 5,
  203. color3);
  204. DrawCircle(new Vector2(mapRange.Position.X + doorAreaInfo.End + 2, mapRange.Position.Y), 5,
  205. color4);
  206. break;
  207. }
  208. }
  209. }
  210. //绘制导航, 现在有点问题, 绘制的内容会被自身的 tile 所挡住
  211. if (RoomTemplate._dungeonTileMap != null)
  212. {
  213. var result = RoomTemplate._dungeonTileMap.GetGenerateNavigationResult();
  214. if (result != null)
  215. {
  216. if (result.Success)
  217. {
  218. var polygonData = RoomTemplate._dungeonTileMap.GetPolygonData();
  219. Utils.DrawNavigationPolygon(this, polygonData, 2);
  220. }
  221. else
  222. {
  223. var color = new Color(1, 0, 0, 0.5f);
  224. var tileCellSize = GameConfig.TileCellSize;
  225. var point = (result.Exception.Point + new Vector2(0.5f, 0.5f)) * tileCellSize;
  226. DrawCircle(point, 4, color);
  227. DrawLine(point + new Vector2(-tileCellSize / 2f, -tileCellSize / 2f), point + new Vector2(tileCellSize / 2f, tileCellSize / 2f), color, 2);
  228. DrawLine(point + new Vector2(-tileCellSize / 2f, tileCellSize / 2f), point + new Vector2(tileCellSize / 2f, -tileCellSize / 2f), color, 2);
  229. }
  230. }
  231. }
  232. }
  233. }
  234.  
  235. }
  236. public override void _Ready()
  237. {
  238. if (!Engine.IsEditorHint())
  239. {
  240. return;
  241. }
  242. EnableEdit = false;
  243. }
  244.  
  245. public override void _Process(double delta)
  246. {
  247. if (!Engine.IsEditorHint())
  248. {
  249. return;
  250. }
  251.  
  252. if (TileSet == null)
  253. {
  254. return;
  255. }
  256.  
  257. if (_dungeonTileMap == null)
  258. {
  259. _dungeonTileMap = new DungeonTileMap(this);
  260. _dungeonTileMap.SetFloorAtlasCoords(new List<Vector2I>() { new Vector2I(0, 8) });
  261. OnTileChanged();
  262. var callable = new Callable(this, nameof(OnTileChanged));
  263. if (!IsConnected("changed", callable))
  264. {
  265. Connect("changed", callable);
  266. }
  267. }
  268.  
  269. if (_tileDrawHandler == null)
  270. {
  271. _tileDrawHandler = GetNodeOrNull<TileDrawHandler>("TileDrawHandler");
  272. if (_tileDrawHandler == null)
  273. {
  274. _tileDrawHandler = new TileDrawHandler();
  275. _tileDrawHandler.RoomTemplate = this;
  276. _tileDrawHandler.Name = "TileDrawHandler";
  277. _tileDrawHandler.ZIndex = 100;
  278. AddChild(_tileDrawHandler);
  279. }
  280. else
  281. {
  282. _tileDrawHandler.RoomTemplate = this;
  283. }
  284. }
  285. //导航计算
  286. if (_calcTileNavTimer > 0)
  287. {
  288. _calcTileNavTimer -= (float)delta;
  289. //重新计算导航
  290. if (_calcTileNavTimer <= 0)
  291. {
  292. _dungeonTileMap.GenerateNavigationPolygon(0);
  293. }
  294. }
  295.  
  296. //加载配置
  297. var initConfigs = false;
  298. if (_dungeonRoomInfo == null)
  299. {
  300. initConfigs = true;
  301.  
  302. var path = SceneFilePath;
  303. if (!string.IsNullOrEmpty(path))
  304. {
  305. var start = GameConfig.RoomTileDir.Length + 6;
  306. var name = path.Substring(start, path.Length - start - 5);
  307. ReadConfig(CalcTileRange(this), name);
  308. }
  309. }
  310.  
  311. //按键检测
  312. var isClick = false;
  313. if (Input.IsMouseButtonPressed(MouseButton.Left))
  314. {
  315. if (!_mouseDown)
  316. {
  317. _mouseDown = true;
  318. isClick = true;
  319. }
  320. }
  321. else if (_mouseDown)
  322. {
  323. _mouseDown = false;
  324. isClick = false;
  325. }
  326.  
  327. if (Input.IsMouseButtonPressed(MouseButton.Middle)) //中键移除门
  328. {
  329. if (EnableEdit && _activeArea != null)
  330. {
  331. RemoveDoorArea(_activeArea);
  332. _hasActivePoint = false;
  333. _activeArea = null;
  334. }
  335. }
  336. else if (TileSet != null) //编辑操作
  337. {
  338. var mapRect = CalcTileRange(this);
  339. var mousePosition = GetLocalMousePosition();
  340.  
  341. if (mapRect != _prevRect)
  342. {
  343. if (!initConfigs)
  344. {
  345. OnMapRectChange();
  346. }
  347. }
  348.  
  349. _prevRect = mapRect;
  350. if (EnableEdit)
  351. {
  352. var tileSize = TileSet.TileSize;
  353. if (_isDrag) //拖拽中
  354. {
  355. if (_activeArea != null)
  356. {
  357. //拖拽节点操作
  358. if (_activeArea.Direction == DoorDirection.N || _activeArea.Direction == DoorDirection.S)
  359. {
  360. if (_activePointType == 0)
  361. {
  362. var mouseOffset = Approach(mousePosition.X, tileSize.X);
  363. _activeArea.StartPosition = new Vector2(mouseOffset, _activeArea.StartPosition.Y);
  364. _activeArea.Start = mouseOffset - mapRect.Position.X;
  365. _dragHasCollision = _activeArea.StartPosition.X <= mapRect.Position.X ||
  366. _activeArea.StartPosition.X + 3 * tileSize.X >=
  367. _activeArea.EndPosition.X ||
  368. CheckDoorCollision(_activeArea.Direction, _activeArea);
  369. }
  370. else
  371. {
  372. var mouseOffset = Approach(mousePosition.X, tileSize.X);
  373. _activeArea.EndPosition = new Vector2(mouseOffset, _activeArea.EndPosition.Y);
  374. _activeArea.End = mouseOffset - mapRect.Position.X;
  375. _dragHasCollision = _activeArea.EndPosition.X >= mapRect.Position.X + mapRect.Size.X ||
  376. _activeArea.EndPosition.X - 3 * tileSize.X <=
  377. _activeArea.StartPosition.X ||
  378. CheckDoorCollision(_activeArea.Direction, _activeArea);
  379. }
  380. }
  381. else
  382. {
  383. if (_activePointType == 0)
  384. {
  385. var mouseOffset = Approach(mousePosition.Y, tileSize.Y);
  386. _activeArea.StartPosition = new Vector2(_activeArea.StartPosition.X, mouseOffset);
  387. _activeArea.Start = mouseOffset - mapRect.Position.Y;
  388. _dragHasCollision = _activeArea.StartPosition.Y <= mapRect.Position.Y ||
  389. _activeArea.StartPosition.Y + 3 * tileSize.Y >=
  390. _activeArea.EndPosition.Y ||
  391. CheckDoorCollision(_activeArea.Direction, _activeArea);
  392. }
  393. else
  394. {
  395. var mouseOffset = Approach(mousePosition.Y, tileSize.Y);
  396. _activeArea.EndPosition = new Vector2(_activeArea.EndPosition.X, mouseOffset);
  397. _activeArea.End = mouseOffset - mapRect.Position.Y;
  398. _dragHasCollision = _activeArea.EndPosition.Y >= mapRect.Position.Y + mapRect.Size.Y ||
  399. _activeArea.EndPosition.Y - 3 * tileSize.Y <=
  400. _activeArea.StartPosition.Y ||
  401. CheckDoorCollision(_activeArea.Direction, _activeArea);
  402. }
  403. }
  404. }
  405. }
  406. else
  407. {
  408. if (Mathf.Abs(mousePosition.Y - mapRect.Position.Y) <= 8 && mousePosition.X >= mapRect.Position.X &&
  409. mousePosition.X <= mapRect.Position.X + mapRect.Size.X) //上
  410. {
  411. _hover = true;
  412. _hoverDirection = DoorDirection.N;
  413. var mouseOffset = Approach(mousePosition.X, tileSize.X);
  414. _hoverPoint1 = new Vector2(mouseOffset - tileSize.X * 2, mapRect.Position.Y);
  415. _hoverPoint2 = new Vector2(_hoverPoint1.X + tileSize.X * 4, _hoverPoint1.Y);
  416.  
  417. //判断是否能放下新的门
  418. if (_hoverPoint1.X <= mapRect.Position.X ||
  419. _hoverPoint2.X >= mapRect.Position.X + mapRect.Size.X ||
  420. CheckDoorCollision())
  421. {
  422. _canPut = false;
  423. FindHoverPoint(mouseOffset);
  424. }
  425. else
  426. {
  427. _canPut = true;
  428. _hasActivePoint = false;
  429. _activeArea = null;
  430. }
  431. }
  432. else if (Mathf.Abs(mousePosition.X - mapRect.Position.X) <= 8 &&
  433. mousePosition.Y >= mapRect.Position.Y &&
  434. mousePosition.Y <= mapRect.Position.Y + mapRect.Size.Y) //左
  435. {
  436. _hover = true;
  437. _hoverDirection = DoorDirection.W;
  438. var mouseOffset = Approach(mousePosition.Y, tileSize.Y);
  439. _hoverPoint1 = new Vector2(mapRect.Position.X, mouseOffset - tileSize.Y * 2);
  440. _hoverPoint2 = new Vector2(_hoverPoint1.X, _hoverPoint1.Y + tileSize.X * 4);
  441.  
  442. //判断是否能放下新的门
  443. if (_hoverPoint1.Y <= mapRect.Position.Y ||
  444. _hoverPoint2.Y >= mapRect.Position.Y + mapRect.Size.Y ||
  445. CheckDoorCollision())
  446. {
  447. _canPut = false;
  448. FindHoverPoint(mouseOffset);
  449. }
  450. else
  451. {
  452. _canPut = true;
  453. _hasActivePoint = false;
  454. _activeArea = null;
  455. }
  456. }
  457. else if (Mathf.Abs(mousePosition.Y - (mapRect.Position.Y + mapRect.Size.Y)) <= 8 &&
  458. mousePosition.X >= mapRect.Position.X &&
  459. mousePosition.X <= mapRect.Position.X + mapRect.Size.X) //下
  460. {
  461. _hover = true;
  462. _hoverDirection = DoorDirection.S;
  463. var mouseOffset = Approach(mousePosition.X, tileSize.X);
  464. _hoverPoint1 = new Vector2(mouseOffset - tileSize.X * 2,
  465. mapRect.Position.Y + mapRect.Size.Y);
  466. _hoverPoint2 = new Vector2(_hoverPoint1.X + tileSize.X * 4, _hoverPoint1.Y);
  467.  
  468. //判断是否能放下新的门
  469. if (_hoverPoint1.X <= mapRect.Position.X ||
  470. _hoverPoint2.X >= mapRect.Position.X + mapRect.Size.X ||
  471. CheckDoorCollision())
  472. {
  473. _canPut = false;
  474. FindHoverPoint(mouseOffset);
  475. }
  476. else
  477. {
  478. _canPut = true;
  479. _hasActivePoint = false;
  480. _activeArea = null;
  481. }
  482. }
  483. else if (Mathf.Abs(mousePosition.X - (mapRect.Position.X + mapRect.Size.X)) <= 8 &&
  484. mousePosition.Y >= mapRect.Position.Y &&
  485. mousePosition.Y <= mapRect.Position.Y + mapRect.Size.Y) //右
  486. {
  487. _hover = true;
  488. _hoverDirection = DoorDirection.E;
  489. var mouseOffset = Approach(mousePosition.Y, tileSize.Y);
  490. _hoverPoint1 = new Vector2(mapRect.Position.X + mapRect.Size.X,
  491. mouseOffset - tileSize.Y * 2);
  492. _hoverPoint2 = new Vector2(_hoverPoint1.X, _hoverPoint1.Y + tileSize.X * 4);
  493.  
  494. //判断是否能放下新的门
  495. if (_hoverPoint1.Y <= mapRect.Position.Y ||
  496. _hoverPoint2.Y >= mapRect.Position.Y + mapRect.Size.Y ||
  497. CheckDoorCollision())
  498. {
  499. _canPut = false;
  500. FindHoverPoint(mouseOffset);
  501. }
  502. else
  503. {
  504. _canPut = true;
  505. _hasActivePoint = false;
  506. _activeArea = null;
  507. }
  508. }
  509. else
  510. {
  511. ClearState();
  512. }
  513. }
  514.  
  515. if (isClick && _canPut) //判断是否可以创建新的点
  516. {
  517. CreateDoorArea(mapRect);
  518. }
  519. else if (_mouseDown && !_isDrag) //拖拽节点
  520. {
  521. _isDrag = true;
  522. _dragHasCollision = false;
  523. if (_activeArea != null)
  524. {
  525. if (_activePointType == 0)
  526. {
  527. _startDragValue = _activeArea.Start;
  528. _startDragPositionValue = _activeArea.StartPosition;
  529. }
  530. else
  531. {
  532. _startDragValue = _activeArea.End;
  533. _startDragPositionValue = _activeArea.EndPosition;
  534. }
  535. }
  536. }
  537. else if (!_mouseDown && _isDrag) //松开拖拽的点
  538. {
  539. _isDrag = false;
  540. if (_activeArea != null) //提交拖拽结果
  541. {
  542. if (_dragHasCollision)
  543. {
  544. if (_activePointType == 0)
  545. {
  546. _activeArea.Start = _startDragValue;
  547. _activeArea.StartPosition = _startDragPositionValue;
  548. }
  549. else
  550. {
  551. _activeArea.End = _startDragValue;
  552. _activeArea.EndPosition = _startDragPositionValue;
  553. }
  554. }
  555.  
  556. //OnDoorAreaChange();
  557. }
  558.  
  559. _dragHasCollision = false;
  560. }
  561. }
  562. else
  563. {
  564. ClearState();
  565. }
  566.  
  567. _tileDrawHandler.QueueRedraw();
  568. }
  569. else
  570. {
  571. ClearState();
  572. }
  573.  
  574. //按下 ctrl + s 保存
  575. if (Input.IsKeyPressed(Key.Ctrl) && Input.IsKeyPressed(Key.S))
  576. {
  577. if (!_clickSave)
  578. {
  579. TriggerSave();
  580. }
  581. _clickSave = true;
  582. // if (_canSave)
  583. // {
  584. // _canSave = false;
  585. // TriggerSave();
  586. // }
  587. }
  588. else
  589. {
  590. _clickSave = false;
  591. }
  592. //权重发生改变
  593. if (_changeWeight)
  594. {
  595. _changeWeightTimer += (float)delta;
  596. if (_changeWeightTimer > 1)
  597. {
  598. _changeWeightTimer = 0;
  599. _changeWeight = false;
  600. //权重改变, 保存数据
  601. TriggerSave();
  602. }
  603. }
  604. }
  605. private void ClearState()
  606. {
  607. _hover = false;
  608. _canPut = false;
  609. _hasActivePoint = false;
  610. _activeArea = null;
  611. }
  612.  
  613. private void OnTileChanged()
  614. {
  615. _calcTileNavTimer = 1f;
  616. }
  617. //创建门
  618. private void CreateDoorArea(Rect2 mapRect)
  619. {
  620. var doorAreaInfo = new DoorAreaInfo();
  621. doorAreaInfo.Direction = _hoverDirection;
  622. doorAreaInfo.StartPosition = _hoverPoint1;
  623. doorAreaInfo.EndPosition = _hoverPoint2;
  624. switch (_hoverDirection)
  625. {
  626. case DoorDirection.E:
  627. case DoorDirection.W:
  628. doorAreaInfo.Start = _hoverPoint1.Y - mapRect.Position.Y;
  629. doorAreaInfo.End = _hoverPoint2.Y - mapRect.Position.Y;
  630. break;
  631. case DoorDirection.N:
  632. case DoorDirection.S:
  633. doorAreaInfo.Start = _hoverPoint1.X - mapRect.Position.X;
  634. doorAreaInfo.End = _hoverPoint2.X - mapRect.Position.X;
  635. break;
  636. }
  637.  
  638. _dungeonRoomInfo.DoorAreaInfos.Add(doorAreaInfo);
  639. //OnDoorAreaChange();
  640. }
  641.  
  642. //移除门
  643. private void RemoveDoorArea(DoorAreaInfo doorAreaInfo)
  644. {
  645. _dungeonRoomInfo.DoorAreaInfos.Remove(doorAreaInfo);
  646. //OnDoorAreaChange();
  647. }
  648.  
  649. //检查门是否有碰撞
  650. private bool CheckDoorCollision()
  651. {
  652. foreach (var doorAreaInfo in _dungeonRoomInfo.DoorAreaInfos)
  653. {
  654. if (doorAreaInfo.Direction == _hoverDirection)
  655. {
  656. switch (_hoverDirection)
  657. {
  658. case DoorDirection.E:
  659. case DoorDirection.W:
  660. if (CheckValueCollision(doorAreaInfo.StartPosition.Y, doorAreaInfo.EndPosition.Y, _hoverPoint1.Y, _hoverPoint2.Y))
  661. {
  662. return true;
  663. }
  664. break;
  665. case DoorDirection.S:
  666. case DoorDirection.N:
  667. if (CheckValueCollision(doorAreaInfo.StartPosition.X, doorAreaInfo.EndPosition.X, _hoverPoint1.X, _hoverPoint2.X))
  668. {
  669. return true;
  670. }
  671. break;
  672. }
  673. }
  674. }
  675.  
  676. return false;
  677. }
  678.  
  679. //检查门是否有碰撞
  680. private bool CheckDoorCollision(DoorDirection direction, DoorAreaInfo info)
  681. {
  682. foreach (var doorAreaInfo in _dungeonRoomInfo.DoorAreaInfos)
  683. {
  684. if (doorAreaInfo.Direction == direction && info != doorAreaInfo &&
  685. CheckValueCollision(doorAreaInfo.Start, doorAreaInfo.End, info.Start, info.End))
  686. {
  687. return true;
  688. }
  689. }
  690.  
  691. return false;
  692. }
  693. private bool CheckValueCollision(float o1, float o2, float h1, float h2)
  694. {
  695. var size = TileSet.TileSize.X;
  696. return !(h2 < o1 - 3 * size || o2 + 3 * size < h1);
  697. }
  698.  
  699. private void FindHoverPoint(float mouseOffset)
  700. {
  701. if (_isDrag)
  702. {
  703. return;
  704. }
  705. //检测是否有碰撞的点
  706. var flag = false;
  707. foreach (var doorAreaInfo in _dungeonRoomInfo.DoorAreaInfos)
  708. {
  709. if (doorAreaInfo.Direction == _hoverDirection)
  710. {
  711. if (_hoverDirection == DoorDirection.N || _hoverDirection == DoorDirection.S)
  712. {
  713. if (Math.Abs(doorAreaInfo.StartPosition.X - mouseOffset) < 0.0001f)
  714. {
  715. _hasActivePoint = true;
  716. _activePointType = 0;
  717. _activeArea = doorAreaInfo;
  718. flag = true;
  719. break;
  720. }
  721. else if (Math.Abs(doorAreaInfo.EndPosition.X - mouseOffset) < 0.0001f)
  722. {
  723. _hasActivePoint = true;
  724. _activePointType = 1;
  725. _activeArea = doorAreaInfo;
  726. flag = true;
  727. break;
  728. }
  729. }
  730. else
  731. {
  732. if (Math.Abs(doorAreaInfo.StartPosition.Y - mouseOffset) < 0.0001f)
  733. {
  734. _hasActivePoint = true;
  735. _activePointType = 0;
  736. _activeArea = doorAreaInfo;
  737. flag = true;
  738. break;
  739. }
  740. else if (Math.Abs(doorAreaInfo.EndPosition.Y - mouseOffset) < 0.0001f)
  741. {
  742. _hasActivePoint = true;
  743. _activePointType = 1;
  744. _activeArea = doorAreaInfo;
  745. flag = true;
  746. break;
  747. }
  748. }
  749. }
  750. }
  751.  
  752. if (!flag)
  753. {
  754. _hasActivePoint = false;
  755. _activeArea = null;
  756. }
  757. }
  758.  
  759. private float Approach(float value, float period)
  760. {
  761. var temp = value % period;
  762. if (Mathf.Abs(temp) >= period / 2)
  763. {
  764. return ((int)(value / period) + (value >= 0 ? 1 : -1)) * period;
  765. }
  766.  
  767. return (int)(value / period) * period;
  768. }
  769.  
  770. //地图大小改变
  771. private void OnMapRectChange()
  772. {
  773. _dungeonRoomInfo.DoorAreaInfos.Clear();
  774. _canPut = false;
  775. _hasActivePoint = false;
  776. _activeArea = null;
  777. //OnDoorAreaChange();
  778. }
  779.  
  780. // //区域数据修改
  781. // private void OnDoorAreaChange()
  782. // {
  783. // _canSave = true;
  784. // }
  785.  
  786. //触发保存操作
  787. private void TriggerSave()
  788. {
  789. //如果没有找到对应的场景文件,则不保存
  790. var path = _dungeonRoomInfo.GroupName + "/" + DungeonManager.DungeonRoomTypeToString(_dungeonRoomInfo.RoomType) + "/" + _dungeonRoomInfo.FileName;
  791. if (!File.Exists(GameConfig.RoomTileDir + path + ".tscn"))
  792. {
  793. return;
  794. }
  795. //计算导航网格
  796. _dungeonTileMap.GenerateNavigationPolygon(0);
  797. var rect = GetUsedRect();
  798. DungeonRoomInfo.SaveConfig(_dungeonRoomInfo.DoorAreaInfos, rect.Position, rect.Size,
  799. _dungeonRoomInfo.GroupName, _dungeonRoomInfo.RoomType, Name, Weight);
  800. }
  801. /// <summary>
  802. /// 计算tile所占区域
  803. /// </summary>
  804. /// <returns></returns>
  805. public static Rect2 CalcTileRange(TileMap tileMap)
  806. {
  807. var usedRect = tileMap.GetUsedRect();
  808. var pos = usedRect.Position * tileMap.TileSet.TileSize;
  809. var size = usedRect.Size * tileMap.TileSet.TileSize;
  810. return new Rect2(tileMap.ToLocal(pos), size);
  811. }
  812.  
  813. /// <summary>
  814. /// 读取房间配置
  815. /// </summary>
  816. private void ReadConfig(Rect2 mapRect, string name)
  817. {
  818. var path = GameConfig.RoomTileDataDir + name + ".json";
  819.  
  820. if (File.Exists(path))
  821. {
  822. var text = File.ReadAllText(path);
  823. try
  824. {
  825. _dungeonRoomInfo = DeserializeDungeonRoomInfo(text);
  826. //填充 StartPosition 和 EndPosition 数据
  827. foreach (var doorAreaInfo in _dungeonRoomInfo.DoorAreaInfos)
  828. {
  829. doorAreaInfo.CalcPosition(mapRect.Position, mapRect.Size);
  830. }
  831.  
  832. Weight = _dungeonRoomInfo.Weight;
  833. }
  834. catch (Exception e)
  835. {
  836. GD.PrintErr($"加载房间数据'{path}'发生异常: " + e);
  837. }
  838. }
  839. }
  840.  
  841. /// <summary>
  842. /// 反序列化 DungeonRoomInfo
  843. /// </summary>
  844. public static DungeonRoomInfo DeserializeDungeonRoomInfo(string text)
  845. {
  846. // 下面这句代码在 Godot4.0_rc2的编辑器模式下, 重载脚本会导致编辑器一直报错!, 所以暂时先用下面的方法
  847. //var roomInfo = JsonSerializer.Deserialize<DungeonRoomInfo>(text);
  848.  
  849. var obj = Json.ParseString(text).AsGodotDictionary();
  850. var roomInfo = new DungeonRoomInfo();
  851. if (obj.ContainsKey("Position"))
  852. {
  853. var position = obj["Position"].AsGodotDictionary();
  854. roomInfo.Position = new SerializeVector2(position["X"].AsInt32(), position["Y"].AsInt32());
  855. }
  856.  
  857. if (obj.ContainsKey("Size"))
  858. {
  859. var size = obj["Size"].AsGodotDictionary();
  860. roomInfo.Size = new SerializeVector2(size["X"].AsInt32(), size["Y"].AsInt32());
  861. }
  862.  
  863. if (obj.ContainsKey("RoomType"))
  864. {
  865. var roomType = obj["RoomType"].AsInt32();
  866. roomInfo.RoomType = (DungeonRoomType)roomType;
  867. }
  868. if (obj.ContainsKey("GroupName"))
  869. {
  870. roomInfo.GroupName = obj["GroupName"].AsString();
  871. }
  872. if (obj.ContainsKey("FileName"))
  873. {
  874. roomInfo.FileName = obj["FileName"].AsString();
  875. }
  876. if (obj.ContainsKey("Weight"))
  877. {
  878. roomInfo.Weight = obj["Weight"].AsInt32();
  879. }
  880.  
  881. if (obj.ContainsKey("DoorAreaInfos"))
  882. {
  883. var doorAreaInfos = obj["DoorAreaInfos"].AsGodotArray<Variant>();
  884. roomInfo.DoorAreaInfos = new List<DoorAreaInfo>();
  885. foreach (var item in doorAreaInfos)
  886. {
  887. var temp = item.AsGodotDictionary();
  888. var doorInfo = new DoorAreaInfo();
  889. doorInfo.Direction = (DoorDirection)temp["Direction"].AsInt32();
  890. doorInfo.Start = temp["Start"].AsInt32();
  891. doorInfo.End = temp["End"].AsInt32();
  892. roomInfo.DoorAreaInfos.Add(doorInfo);
  893. }
  894. }
  895.  
  896. return roomInfo;
  897. }
  898. #endif
  899.  
  900. /// <summary>
  901. /// 获取所有标记数据
  902. /// </summary>
  903. public ActivityMark[] GetMarks()
  904. {
  905. var list = new List<ActivityMark>();
  906. foreach (var child in GetChildren())
  907. {
  908. EachAndGetMarks(child, list);
  909. }
  910.  
  911. return list.ToArray();
  912. }
  913.  
  914. private void EachAndGetMarks(Node node, List<ActivityMark> list)
  915. {
  916. if (node is ActivityMark mark)
  917. {
  918. list.Add(mark);
  919. }
  920. foreach (var child in node.GetChildren())
  921. {
  922. EachAndGetMarks(child, list);
  923. }
  924. }
  925. }
  926. */