Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / room / RoomManager.cs
@小李xl 小李xl on 23 Nov 2022 21 KB 测试是否能识别可行走区域
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using Godot;
  5.  
  6. /// <summary>
  7. /// 房间管理器
  8. /// </summary>
  9. public class RoomManager : Navigation2D
  10. {
  11. /// <summary>
  12. /// 玩家对象
  13. /// </summary>
  14. public Role Player { get; private set; }
  15.  
  16. //对象根节点
  17. private Node2D _objectRoot;
  18.  
  19. //对象根节点, 带y轴排序功能
  20. private YSort _sortRoot;
  21.  
  22. private Node2D _mapRoot;
  23.  
  24. private NavigationPolygonInstance _navigationPolygon;
  25. private Enemy _enemy;
  26.  
  27. //可行走区域的tileId
  28. private List<int> _wayIds = new List<int>(new[] { 129 });
  29.  
  30. //已经标记过的点
  31. private HashSet<Vector2> _usePoints = new HashSet<Vector2>();
  32.  
  33. //导航区域数据
  34. private List<NavigationPolygonData> _polygonDataList = new List<NavigationPolygonData>();
  35.  
  36. public override void _EnterTree()
  37. {
  38. Input.MouseMode = Input.MouseModeEnum.Hidden;
  39.  
  40. _sortRoot = GetNode<YSort>("SortRoot");
  41. _objectRoot = GetNode<Node2D>("ObjectRoot");
  42.  
  43. _navigationPolygon = GetNode<NavigationPolygonInstance>("NavigationPolygonInstance");
  44.  
  45. //初始化地图
  46. _mapRoot = GetNode<Node2D>("MapRoot");
  47. var node = _mapRoot.GetChild(0).GetNode("Config");
  48. Color color = (Color)node.GetMeta("ClearColor");
  49. VisualServer.SetDefaultClearColor(color);
  50.  
  51. //创建玩家
  52. Player = new Player();
  53. Player.Position = new Vector2(100, 100);
  54. Player.Name = "Player";
  55. Player.PutDown();
  56.  
  57. _enemy = new Enemy();
  58. _enemy.Name = "Enemy";
  59. _enemy.PutDown(new Vector2(150, 150));
  60. }
  61.  
  62. public override void _Ready()
  63. {
  64. var nowTicks = DateTime.Now.Ticks;
  65. GenerateNavigationPolygon();
  66. GD.Print("useTime: " + (DateTime.Now.Ticks - nowTicks) / 10000 + "毫秒");
  67.  
  68. //播放bgm
  69. SoundManager.PlayMusic(ResourcePath.resource_sound_bgm_Intro_ogg, -17f);
  70. _enemy.PickUpWeapon(WeaponManager.GetGun("1001"));
  71.  
  72. WeaponManager.GetGun("1001").PutDown(new Vector2(80, 100));
  73. WeaponManager.GetGun("1001").PutDown(new Vector2(80, 80));
  74. WeaponManager.GetGun("1002").PutDown(new Vector2(80, 120));
  75. WeaponManager.GetGun("1003").PutDown(new Vector2(120, 80));
  76.  
  77. WeaponManager.GetGun("1003").PutDown(new Vector2(180, 80));
  78. WeaponManager.GetGun("1003").PutDown(new Vector2(180, 180));
  79. WeaponManager.GetGun("1002").PutDown(new Vector2(180, 120));
  80.  
  81. WeaponManager.GetGun("1004").PutDown(new Vector2(220, 120));
  82. }
  83.  
  84. public override void _Process(float delta)
  85. {
  86. if (GameApplication.Instance.Debug)
  87. {
  88. Update();
  89. }
  90. }
  91.  
  92. public override void _Draw()
  93. {
  94. if (GameApplication.Instance.Debug)
  95. {
  96. for (var i = 0; i < _polygonDataList.Count; i++)
  97. {
  98. var item = _polygonDataList[i];
  99. if (item.Points.Count >= 2)
  100. {
  101. DrawPolyline(item.Points.ToArray(), Colors.Red);
  102. }
  103. }
  104. }
  105. }
  106.  
  107. /// <summary>
  108. /// 获取房间根节点
  109. /// </summary>
  110. /// <param name="useYSort">是否获取 YSort 节点</param>
  111. /// <returns></returns>
  112. public Node2D GetRoot(bool useYSort = false)
  113. {
  114. return useYSort ? _sortRoot : _objectRoot;
  115. }
  116.  
  117. /// <summary>
  118. /// 自动生成导航区域
  119. /// </summary>
  120. private void GenerateNavigationPolygon()
  121. {
  122. var tileMap = _mapRoot.GetChild(0).GetNode<TileMap>("Wall");
  123. var size = tileMap.CellSize;
  124.  
  125. var rect = tileMap.GetUsedRect();
  126.  
  127. var x = (int)rect.Position.x;
  128. var y = (int)rect.Position.y;
  129. var w = (int)rect.Size.x;
  130. var h = (int)rect.Size.y;
  131.  
  132. for (int j = y; j < h; j++)
  133. {
  134. for (int i = x; i < w; i++)
  135. {
  136. var tileId = tileMap.GetCell(i, j);
  137. if (IsWayCell(tileId))
  138. {
  139. if (!_usePoints.Contains(new Vector2(i, j)))
  140. {
  141. NavigationPolygonData polygonData = null;
  142.  
  143. if (!IsWayCell(tileMap.GetCell(i, j - 1)))
  144. {
  145. polygonData = CalcOutline(i, j, tileMap, size);
  146. }
  147. else if (!IsWayCell(tileMap.GetCell(i, j + 1)))
  148. {
  149. polygonData = CalcInline(i, j, tileMap, size);
  150. }
  151.  
  152. if (polygonData != null)
  153. {
  154. _polygonDataList.Add(polygonData);
  155. //return;
  156. }
  157. }
  158. }
  159. }
  160. }
  161. }
  162.  
  163. private NavigationPolygonData CalcOutline(int i, int j, TileMap tileMap, Vector2 size)
  164. {
  165. var polygonData = new NavigationPolygonData();
  166. var points = polygonData.Points;
  167. // 0:右, 1:下, 2:左, 3:上
  168. var dir = 0;
  169. var offset = new Vector2(size.x * 0.5f, size.y * 0.5f);
  170. //找到路, 向右开始找边界
  171. var startPos = new Vector2(i, j);
  172.  
  173. var tempI = i;
  174. var tempJ = j;
  175.  
  176. while (true)
  177. {
  178. switch (dir)
  179. {
  180. case 0: //右
  181. {
  182. if (IsWayCell(tileMap.GetCell(tempI, tempJ - 1))) //先向上找
  183. {
  184. dir = 3;
  185.  
  186. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  187. var pos = new Vector2(tempI, tempJ);
  188. if (points.Count > 1 && pos == startPos)
  189. {
  190. return polygonData;
  191. }
  192.  
  193. PutUsePoint(pos);
  194.  
  195. tempJ--;
  196. break;
  197. }
  198. else if (IsWayCell(tileMap.GetCell(tempI + 1, tempJ))) //再向右找
  199. {
  200. if (points.Count == 0)
  201. {
  202. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  203. }
  204.  
  205. var pos = new Vector2(tempI, tempJ);
  206. if (points.Count > 1 && pos == startPos)
  207. {
  208. return polygonData;
  209. }
  210.  
  211. PutUsePoint(new Vector2(tempI, tempJ));
  212. tempI++;
  213. break;
  214. }
  215. else if (IsWayCell(tileMap.GetCell(tempI, tempJ + 1))) //向下找
  216. {
  217. dir = 1;
  218.  
  219. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  220. var pos = new Vector2(tempI, tempJ);
  221. if (points.Count > 1 && pos == startPos)
  222. {
  223. return polygonData;
  224. }
  225.  
  226. PutUsePoint(pos);
  227.  
  228. tempJ++;
  229. break;
  230. }
  231.  
  232. return null;
  233. }
  234. case 1: //下
  235. {
  236. if (IsWayCell(tileMap.GetCell(tempI + 1, tempJ))) //先向右找
  237. {
  238. dir = 0;
  239.  
  240. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  241. var pos = new Vector2(tempI, tempJ);
  242. if (points.Count > 1 && pos == startPos)
  243. {
  244. return polygonData;
  245. }
  246.  
  247. PutUsePoint(pos);
  248.  
  249. tempI++;
  250. break;
  251. }
  252. else if (IsWayCell(tileMap.GetCell(tempI, tempJ + 1))) //再向下找
  253. {
  254. if (points.Count == 0)
  255. {
  256. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  257. }
  258.  
  259. var pos = new Vector2(tempI, tempJ);
  260. if (points.Count > 1 && pos == startPos)
  261. {
  262. return polygonData;
  263. }
  264.  
  265. PutUsePoint(new Vector2(tempI, tempJ));
  266. tempJ++;
  267. break;
  268. }
  269. else if (IsWayCell(tileMap.GetCell(tempI - 1, tempJ))) //向左找
  270. {
  271. dir = 2;
  272.  
  273. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  274. var pos = new Vector2(tempI, tempJ);
  275. if (points.Count > 1 && pos == startPos)
  276. {
  277. return polygonData;
  278. }
  279.  
  280. PutUsePoint(pos);
  281.  
  282. tempI--;
  283. break;
  284. }
  285.  
  286. return null;
  287. }
  288. case 2: //左
  289. {
  290. if (IsWayCell(tileMap.GetCell(tempI, tempJ + 1))) //先向下找
  291. {
  292. dir = 1;
  293.  
  294. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  295. var pos = new Vector2(tempI, tempJ);
  296. if (points.Count > 1 && pos == startPos)
  297. {
  298. return polygonData;
  299. }
  300.  
  301. PutUsePoint(pos);
  302.  
  303. tempJ++;
  304. break;
  305. }
  306. else if (IsWayCell(tileMap.GetCell(tempI - 1, tempJ))) //再向左找
  307. {
  308. if (points.Count == 0)
  309. {
  310. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  311. }
  312.  
  313. var pos = new Vector2(tempI, tempJ);
  314. if (points.Count > 1 && pos == startPos)
  315. {
  316. return polygonData;
  317. }
  318.  
  319. PutUsePoint(new Vector2(tempI, tempJ));
  320. tempI--;
  321. break;
  322. }
  323. else if (IsWayCell(tileMap.GetCell(tempI, tempJ - 1))) //向上找
  324. {
  325. dir = 3;
  326.  
  327. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  328. var pos = new Vector2(tempI, tempJ);
  329. if (points.Count > 1 && pos == startPos)
  330. {
  331. return polygonData;
  332. }
  333.  
  334. PutUsePoint(pos);
  335.  
  336. tempJ--;
  337. break;
  338. }
  339.  
  340. return null;
  341. }
  342. case 3: //上
  343. {
  344. if (IsWayCell(tileMap.GetCell(tempI - 1, tempJ))) //先向左找
  345. {
  346. dir = 2;
  347.  
  348. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  349. var pos = new Vector2(tempI, tempJ);
  350. if (points.Count > 1 && pos == startPos)
  351. {
  352. return polygonData;
  353. }
  354.  
  355. PutUsePoint(pos);
  356.  
  357. tempI--;
  358. break;
  359. }
  360. else if (IsWayCell(tileMap.GetCell(tempI, tempJ - 1))) //再向上找
  361. {
  362. if (points.Count == 0)
  363. {
  364. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  365. }
  366.  
  367. var pos = new Vector2(tempI, tempJ);
  368. if (points.Count > 1 && pos == startPos)
  369. {
  370. return polygonData;
  371. }
  372.  
  373. PutUsePoint(new Vector2(tempI, tempJ));
  374. tempJ--;
  375. break;
  376. }
  377. else if (IsWayCell(tileMap.GetCell(tempI + 1, tempJ))) //向右找
  378. {
  379. dir = 0;
  380.  
  381. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  382. var pos = new Vector2(tempI, tempJ);
  383. if (points.Count > 1 && pos == startPos)
  384. {
  385. return polygonData;
  386. }
  387.  
  388. PutUsePoint(pos);
  389.  
  390. tempI++;
  391. break;
  392. }
  393.  
  394. return null;
  395. }
  396. }
  397. }
  398. }
  399.  
  400. private NavigationPolygonData CalcInline(int i, int j, TileMap tileMap, Vector2 size)
  401. {
  402. var polygonData = new NavigationPolygonData();
  403. var points = polygonData.Points;
  404. // 0:右, 1:下, 2:左, 3:上
  405. var dir = 0;
  406. var offset = new Vector2(size.x * 0.5f, size.y * 0.5f);
  407. //找到路, 向右开始找边界
  408. var startPos = new Vector2(i, j);
  409.  
  410. var tempI = i;
  411. var tempJ = j;
  412.  
  413. while (true)
  414. {
  415. switch (dir)
  416. {
  417. case 0: //右
  418. {
  419. if (IsWayCell(tileMap.GetCell(tempI, tempJ + 1))) //向下找
  420. {
  421. dir = 1;
  422.  
  423. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  424. var pos = new Vector2(tempI, tempJ);
  425. if (points.Count > 1 && pos == startPos)
  426. {
  427. return polygonData;
  428. }
  429.  
  430. PutUsePoint(pos);
  431.  
  432. tempJ++;
  433. break;
  434. }
  435. else if (IsWayCell(tileMap.GetCell(tempI + 1, tempJ))) //再向右找
  436. {
  437. if (points.Count == 0)
  438. {
  439. points.Add(new Vector2((tempI - 1) * size.x, tempJ * size.y) + offset);
  440. }
  441.  
  442. var pos = new Vector2(tempI, tempJ);
  443. if (points.Count > 1 && pos == startPos)
  444. {
  445. return polygonData;
  446. }
  447.  
  448. PutUsePoint(new Vector2(tempI, tempJ));
  449. tempI++;
  450. break;
  451. }
  452. else if (IsWayCell(tileMap.GetCell(tempI, tempJ - 1))) //先向上找
  453. {
  454. dir = 3;
  455.  
  456. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  457. var pos = new Vector2(tempI, tempJ);
  458. if (points.Count > 1 && pos == startPos)
  459. {
  460. return polygonData;
  461. }
  462.  
  463. PutUsePoint(pos);
  464.  
  465. tempJ--;
  466. break;
  467. }
  468.  
  469. return null;
  470. }
  471. case 1: //下
  472. {
  473. if (IsWayCell(tileMap.GetCell(tempI - 1, tempJ))) //向左找
  474. {
  475. dir = 2;
  476.  
  477. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  478. var pos = new Vector2(tempI, tempJ);
  479. if (points.Count > 1 && pos == startPos)
  480. {
  481. return polygonData;
  482. }
  483.  
  484. PutUsePoint(pos);
  485.  
  486. tempI--;
  487. break;
  488. }
  489. else if (IsWayCell(tileMap.GetCell(tempI, tempJ + 1))) //再向下找
  490. {
  491. if (points.Count == 0)
  492. {
  493. points.Add(new Vector2((tempI - 1) * size.x, tempJ * size.y) + offset);
  494. }
  495.  
  496. var pos = new Vector2(tempI, tempJ);
  497. if (points.Count > 1 && pos == startPos)
  498. {
  499. return polygonData;
  500. }
  501.  
  502. PutUsePoint(new Vector2(tempI, tempJ));
  503. tempJ++;
  504. break;
  505. }
  506. else if (IsWayCell(tileMap.GetCell(tempI + 1, tempJ))) //先向右找
  507. {
  508. dir = 0;
  509.  
  510. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  511. var pos = new Vector2(tempI, tempJ);
  512. if (points.Count > 1 && pos == startPos)
  513. {
  514. return polygonData;
  515. }
  516.  
  517. PutUsePoint(pos);
  518.  
  519. tempI++;
  520. break;
  521. }
  522.  
  523. return null;
  524. }
  525. case 2: //左
  526. {
  527. if (IsWayCell(tileMap.GetCell(tempI, tempJ - 1))) //向上找
  528. {
  529. dir = 3;
  530.  
  531. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  532. var pos = new Vector2(tempI, tempJ);
  533. if (points.Count > 1 && pos == startPos)
  534. {
  535. return polygonData;
  536. }
  537.  
  538. PutUsePoint(pos);
  539.  
  540. tempJ--;
  541. break;
  542. }
  543. else if (IsWayCell(tileMap.GetCell(tempI - 1, tempJ))) //再向左找
  544. {
  545. if (points.Count == 0)
  546. {
  547. points.Add(new Vector2((tempI - 1) * size.x, tempJ * size.y) + offset);
  548. }
  549.  
  550. var pos = new Vector2(tempI, tempJ);
  551. if (points.Count > 1 && pos == startPos)
  552. {
  553. return polygonData;
  554. }
  555.  
  556. PutUsePoint(new Vector2(tempI, tempJ));
  557. tempI--;
  558. break;
  559. }
  560. else if (IsWayCell(tileMap.GetCell(tempI, tempJ + 1))) //先向下找
  561. {
  562. dir = 1;
  563.  
  564. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  565. var pos = new Vector2(tempI, tempJ);
  566. if (points.Count > 1 && pos == startPos)
  567. {
  568. return polygonData;
  569. }
  570.  
  571. PutUsePoint(pos);
  572.  
  573. tempJ++;
  574. break;
  575. }
  576.  
  577. return null;
  578. }
  579. case 3: //上
  580. {
  581. if (IsWayCell(tileMap.GetCell(tempI + 1, tempJ))) //向右找
  582. {
  583. dir = 0;
  584.  
  585. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  586. var pos = new Vector2(tempI, tempJ);
  587. if (points.Count > 1 && pos == startPos)
  588. {
  589. return polygonData;
  590. }
  591.  
  592. PutUsePoint(pos);
  593.  
  594. tempI++;
  595. break;
  596. }
  597. else if (IsWayCell(tileMap.GetCell(tempI, tempJ - 1))) //再向上找
  598. {
  599. if (points.Count == 0)
  600. {
  601. points.Add(new Vector2((tempI - 1) * size.x, tempJ * size.y) + offset);
  602. }
  603.  
  604. var pos = new Vector2(tempI, tempJ);
  605. if (points.Count > 1 && pos == startPos)
  606. {
  607. return polygonData;
  608. }
  609.  
  610. PutUsePoint(new Vector2(tempI, tempJ));
  611. tempJ--;
  612. break;
  613. }
  614. else if (IsWayCell(tileMap.GetCell(tempI - 1, tempJ))) //先向左找
  615. {
  616. dir = 2;
  617.  
  618. points.Add(new Vector2(tempI * size.x, tempJ * size.y) + offset);
  619. var pos = new Vector2(tempI, tempJ);
  620. if (points.Count > 1 && pos == startPos)
  621. {
  622. return polygonData;
  623. }
  624.  
  625. PutUsePoint(pos);
  626.  
  627. tempI--;
  628. break;
  629. }
  630.  
  631. return null;
  632. }
  633. }
  634. }
  635. }
  636.  
  637. private void PutUsePoint(Vector2 pos)
  638. {
  639. if (_usePoints.Contains(pos))
  640. {
  641. throw new Exception("生成导航多边形发生错误! 点: " + pos + "发生交错!");
  642. }
  643.  
  644. _usePoints.Add(pos);
  645. }
  646.  
  647. private bool IsWayCell(int cellId)
  648. {
  649. return cellId != -1 && _wayIds.Contains(cellId);
  650. }
  651. }