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