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