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