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