Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / ui / roomMap / RoomMapPanel.cs
  1. using System.Collections.Generic;
  2. using Godot;
  3. using UI.RoomUI;
  4.  
  5. namespace UI.RoomMap;
  6.  
  7. /// <summary>
  8. /// 房间的小地图
  9. /// </summary>
  10. public partial class RoomMapPanel : RoomMap
  11. {
  12. private EventFactory _factory = EventManager.CreateEventFactory();
  13. //需要刷新的问号的房间队列
  14. private List<RoomDoorInfo> _needRefresh = new List<RoomDoorInfo>();
  15. //正在使用的敌人标记列表
  16. private List<Sprite2D> _enemySpriteList = new List<Sprite2D>();
  17. //已经回收的敌人标记
  18. private Stack<Sprite2D> _spriteStack = new Stack<Sprite2D>();
  19. //是否放大地图
  20. private bool _isMagnifyMap = false;
  21.  
  22. private UiEventBinder _dragBinder;
  23. //放大地图后拖拽的偏移
  24. private Vector2 _mapOffset;
  25. //放大地图后鼠标悬停的房间
  26. private RoomInfo _mouseHoverRoom;
  27. private Color _originOutlineColor;
  28. //是否展开地图
  29. private bool _pressMapFlag = false;
  30. private Tween _transmissionTween;
  31. public override void OnCreateUi()
  32. {
  33. _ = S_Mark;
  34. S_Bg.Instance.Visible = false;
  35. S_MagnifyMapBar.Instance.Visible = false;
  36. InitMap();
  37. _factory.AddEventListener(EventEnum.OnPlayerFirstEnterRoom, OnPlayerFirstEnterRoom);
  38. _factory.AddEventListener(EventEnum.OnPlayerFirstEnterAisle, OnPlayerFirstEnterAisle);
  39.  
  40. S_DrawContainer.Instance.Resized += OnDrawContainerResized;
  41. }
  42.  
  43. public override void OnDestroyUi()
  44. {
  45. _factory.RemoveAllEventListener();
  46.  
  47. if (_transmissionTween != null)
  48. {
  49. _transmissionTween.Dispose();
  50. }
  51. }
  52.  
  53. public override void Process(float delta)
  54. {
  55. if (_transmissionTween == null) //不在传送过程中
  56. {
  57. if (!InputManager.Map)
  58. {
  59. _pressMapFlag = false;
  60. }
  61. //按下地图按键
  62. if (InputManager.Map && !_isMagnifyMap && !_pressMapFlag) //展开小地图
  63. {
  64. if (UiManager.GetUiInstanceCount(UiManager.UiNames.PauseMenu) == 0 && !InputManager.Roulette)
  65. {
  66. ExpandMap();
  67. }
  68. }
  69. else if (!InputManager.Map && _isMagnifyMap) //还原小地图
  70. {
  71. ShrinkMap();
  72. }
  73. }
  74. //更新敌人位置
  75. {
  76. var enemyList = World.Current.Enemy_InstanceList;
  77. if (enemyList.Count == 0) //没有敌人
  78. {
  79. foreach (var sprite in _enemySpriteList)
  80. {
  81. S_Root.RemoveChild(sprite);
  82. _spriteStack.Push(sprite);
  83. }
  84. _enemySpriteList.Clear();
  85. }
  86. else //更新位置
  87. {
  88. var count = 0; //绘制数量
  89. for (var i = 0; i < enemyList.Count; i++)
  90. {
  91. var enemy = enemyList[i];
  92. if (!enemy.IsDestroyed && !enemy.IsDie && enemy.AffiliationArea != null && enemy.AffiliationArea.RoomInfo.RoomFogMask.IsExplored)
  93. {
  94. count++;
  95. Sprite2D sprite;
  96. if (i >= _enemySpriteList.Count)
  97. {
  98. if (_spriteStack.Count > 0)
  99. {
  100. sprite = _spriteStack.Pop();
  101. }
  102. else
  103. {
  104. sprite = new Sprite2D();
  105. sprite.Texture = ResourceManager.LoadTexture2D(ResourcePath.resource_sprite_ui_commonIcon_Block_png);
  106. sprite.Modulate = new Color(1, 0, 0);
  107. }
  108. _enemySpriteList.Add(sprite);
  109. S_Root.AddChild(sprite);
  110. }
  111. else
  112. {
  113. sprite = _enemySpriteList[i];
  114. }
  115. //更新标记位置
  116. sprite.Position = enemy.GetCenterPosition() / 16;
  117. }
  118. }
  119. //回收多余的标记
  120. while (_enemySpriteList.Count > count)
  121. {
  122. var index = _enemySpriteList.Count - 1;
  123. var sprite = _enemySpriteList[index];
  124. S_Root.RemoveChild(sprite);
  125. _spriteStack.Push(sprite);
  126. _enemySpriteList.RemoveAt(index);
  127. }
  128. }
  129. }
  130. //更新预览图标
  131. if (_needRefresh.Count > 0)
  132. {
  133. foreach (var roomDoorInfo in _needRefresh)
  134. {
  135. HandlerRefreshUnknownSprite(roomDoorInfo);
  136. }
  137. _needRefresh.Clear();
  138. }
  139.  
  140. var player = World.Current.Player;
  141. if (player != null)
  142. {
  143. //更新地图中心点位置
  144. var playPosition = player.GetCenterPosition();
  145. if (!_isMagnifyMap)
  146. {
  147. S_Root.Instance.Position = CalcRootPosition(playPosition);
  148. }
  149. else
  150. {
  151. S_Root.Instance.Position = CalcRootPosition(playPosition) + _mapOffset;
  152. S_Mark.Instance.Position = S_DrawContainer.Instance.Size / 2 + _mapOffset;
  153. }
  154.  
  155. var area = player.AffiliationArea;
  156. //传送
  157. if (_pressMapFlag && _mouseHoverRoom != null &&
  158. area != null && !area.RoomInfo.IsSeclusion &&
  159. Input.IsMouseButtonPressed(MouseButton.Right))
  160. {
  161. //执行传送操作
  162. DoTransmission((_mouseHoverRoom.Waypoints + new Vector2(0.5f, 0.5f)) * GameConfig.TileCellSize);
  163. ResetMap();
  164. _isMagnifyMap = false;
  165. World.Current.Pause = false;
  166. }
  167. }
  168. }
  169.  
  170. /// <summary>
  171. /// 执行展开地图
  172. /// </summary>
  173. public void ExpandMap()
  174. {
  175. World.Current.Pause = true;
  176. _pressMapFlag = true;
  177. _isMagnifyMap = true;
  178. MagnifyMap();
  179. }
  180. /// <summary>
  181. /// 执行收起地图
  182. /// </summary>
  183. public void ShrinkMap()
  184. {
  185. ResetMap();
  186. _isMagnifyMap = false;
  187. World.Current.Pause = false;
  188. }
  189. private void OnDrawContainerResized()
  190. {
  191. S_Mark.Instance.Position = S_DrawContainer.Instance.Size / 2;
  192. }
  193.  
  194. //放大小地图
  195. private void MagnifyMap()
  196. {
  197. GameApplication.Instance.Cursor.SetGuiMode(true);
  198. S_DrawContainer.Reparent(S_MagnifyMapBar);
  199. S_DrawContainer.Instance.Position = new Vector2(1, 1);
  200. S_Bg.Instance.Visible = true;
  201. S_MagnifyMapBar.Instance.Visible = true;
  202. S_MapBar.Instance.Visible = false;
  203. _mapOffset = Vector2.Zero;
  204.  
  205. _dragBinder = S_DrawContainer.Instance.AddDragListener((state, delta) =>
  206. {
  207. if (state == DragState.DragMove)
  208. {
  209. _mapOffset += delta;
  210. }
  211. });
  212. }
  213.  
  214. //还原小地图
  215. private void ResetMap()
  216. {
  217. GameApplication.Instance.Cursor.SetGuiMode(false);
  218. S_DrawContainer.Reparent(S_MapBar);
  219. S_DrawContainer.Instance.Position = new Vector2(1, 1);
  220. S_Bg.Instance.Visible = false;
  221. S_MagnifyMapBar.Instance.Visible = false;
  222. S_MapBar.Instance.Visible = true;
  223. ResetOutlineColor();
  224.  
  225. if (_dragBinder != null)
  226. {
  227. _dragBinder.UnBind();
  228. _dragBinder = null;
  229. }
  230. }
  231.  
  232. private void ResetOutlineColor()
  233. {
  234. if (_mouseHoverRoom != null)
  235. {
  236. ((ShaderMaterial)_mouseHoverRoom.PreviewSprite.Material).SetShaderParameter("outline_color", _originOutlineColor);
  237. _mouseHoverRoom = null;
  238. }
  239. }
  240. //初始化小地图
  241. private void InitMap()
  242. {
  243. var startRoom = GameApplication.Instance.DungeonManager.StartRoomInfo;
  244. if (startRoom == null)
  245. {
  246. HideUi();
  247. return;
  248. }
  249. startRoom.EachRoom(roomInfo =>
  250. {
  251. //房间
  252. roomInfo.PreviewSprite.Visible = false;
  253. S_Root.AddChild(roomInfo.PreviewSprite);
  254.  
  255. roomInfo.PreviewSprite.MouseEntered += () =>
  256. {
  257. if (!_pressMapFlag)
  258. {
  259. return;
  260. }
  261. ResetOutlineColor();
  262. _mouseHoverRoom = roomInfo;
  263. var shaderMaterial = (ShaderMaterial)roomInfo.PreviewSprite.Material;
  264. _originOutlineColor = shaderMaterial.GetShaderParameter("outline_color").AsColor();
  265. //玩家所在的房间门是否打开
  266. var area = World.Current.Player.AffiliationArea;
  267. if (area != null)
  268. {
  269. var isOpen = !area.RoomInfo.IsSeclusion;
  270. if (isOpen)
  271. {
  272. shaderMaterial.SetShaderParameter("outline_color", new Color(0, 1, 0, 0.9f));
  273. }
  274. else
  275. {
  276. shaderMaterial.SetShaderParameter("outline_color", new Color(1, 0, 0, 0.9f));
  277. }
  278. }
  279. };
  280. roomInfo.PreviewSprite.MouseExited += () =>
  281. {
  282. if (!_pressMapFlag)
  283. {
  284. return;
  285. }
  286. ResetOutlineColor();
  287. };
  288. //过道
  289. if (roomInfo.Doors != null)
  290. {
  291. foreach (var roomInfoDoor in roomInfo.Doors)
  292. {
  293. if (roomInfoDoor.IsForward)
  294. {
  295. roomInfoDoor.AislePreviewSprite.Visible = false;
  296. S_Root.AddChild(roomInfoDoor.AislePreviewSprite);
  297. }
  298. }
  299. }
  300. });
  301. }
  302. private void OnPlayerFirstEnterRoom(object data)
  303. {
  304. var roomInfo = (RoomInfo)data;
  305. if (roomInfo.PreviewSprite != null)
  306. {
  307. roomInfo.PreviewSprite.Visible = true;
  308. }
  309.  
  310. if (roomInfo.Doors!= null)
  311. {
  312. foreach (var roomDoor in roomInfo.Doors)
  313. {
  314. RefreshUnknownSprite(roomDoor);
  315. }
  316. }
  317. }
  318. private void OnPlayerFirstEnterAisle(object data)
  319. {
  320. var roomDoorInfo = (RoomDoorInfo)data;
  321. roomDoorInfo.AislePreviewSprite.Visible = true;
  322.  
  323. RefreshUnknownSprite(roomDoorInfo);
  324. RefreshUnknownSprite(roomDoorInfo.ConnectDoor);
  325. }
  326.  
  327. //进入刷新问号队列
  328. private void RefreshUnknownSprite(RoomDoorInfo roomDoorInfo)
  329. {
  330. if (!_needRefresh.Contains(roomDoorInfo))
  331. {
  332. _needRefresh.Add(roomDoorInfo);
  333. }
  334. }
  335.  
  336. //刷新问号
  337. private void HandlerRefreshUnknownSprite(RoomDoorInfo roomDoorInfo)
  338. {
  339. //是否探索房间
  340. var flag1 = roomDoorInfo.RoomInfo.RoomFogMask.IsExplored;
  341. //是否探索过道
  342. var flag2 = roomDoorInfo.AisleFogMask.IsExplored;
  343. if (flag1 == flag2) //不显示问号
  344. {
  345. if (roomDoorInfo.UnknownSprite != null)
  346. {
  347. roomDoorInfo.UnknownSprite.QueueFree();
  348. roomDoorInfo.UnknownSprite = null;
  349. }
  350. }
  351. else
  352. {
  353. var unknownSprite = roomDoorInfo.UnknownSprite ?? CreateUnknownSprite(roomDoorInfo);
  354. var pos = (roomDoorInfo.OriginPosition + roomDoorInfo.GetEndPosition()) / 2;
  355. if (!flag2) //偏向过道
  356. {
  357. if (roomDoorInfo.Direction == DoorDirection.N)
  358. pos += new Vector2I(0, -1);
  359. else if (roomDoorInfo.Direction == DoorDirection.S)
  360. pos += new Vector2I(0, 3);
  361. else if (roomDoorInfo.Direction == DoorDirection.E)
  362. pos += new Vector2I(2, 1);
  363. else if (roomDoorInfo.Direction == DoorDirection.W)
  364. pos += new Vector2I(-2, 1);
  365. }
  366. else //偏向房间
  367. {
  368. if (roomDoorInfo.Direction == DoorDirection.N)
  369. pos -= new Vector2I(0, -4);
  370. else if (roomDoorInfo.Direction == DoorDirection.S)
  371. pos -= new Vector2I(0, 1);
  372. else if (roomDoorInfo.Direction == DoorDirection.E)
  373. pos -= new Vector2I(3, -1);
  374. else if (roomDoorInfo.Direction == DoorDirection.W)
  375. pos -= new Vector2I(-3, -1);
  376. }
  377. unknownSprite.Position = pos;
  378. }
  379. }
  380.  
  381. private Sprite2D CreateUnknownSprite(RoomDoorInfo roomInfoDoor)
  382. {
  383. var unknownSprite = new Sprite2D();
  384. unknownSprite.Texture = ResourceManager.LoadTexture2D(ResourcePath.resource_sprite_ui_commonIcon_Unknown_png);
  385. unknownSprite.Scale = new Vector2(0.25f, 0.25f);
  386. roomInfoDoor.UnknownSprite = unknownSprite;
  387. S_Root.AddChild(unknownSprite);
  388. return unknownSprite;
  389. }
  390.  
  391. private Vector2 CalcRootPosition(Vector2 pos)
  392. {
  393. return S_DrawContainer.Instance.Size / 2 - pos / 16 * S_Root.Instance.Scale;
  394. }
  395. private void DoTransmission(Vector2 position)
  396. {
  397. var roomUI = (RoomUIPanel)ParentUi;
  398. roomUI.S_Mask.Instance.Visible = true;
  399. roomUI.S_Mask.Instance.Color = new Color(0, 0, 0, 0);
  400. _transmissionTween = CreateTween();
  401. _transmissionTween.TweenProperty(roomUI.S_Mask.Instance, "color", new Color(0, 0, 0), 0.3f);
  402. _transmissionTween.TweenCallback(Callable.From(() =>
  403. {
  404. World.Current.Player.Position = position;
  405. }));
  406. _transmissionTween.TweenInterval(0.2f);
  407. _transmissionTween.TweenProperty(roomUI.S_Mask.Instance, "color", new Color(0, 0, 0, 0), 0.3f);
  408. _transmissionTween.TweenCallback(Callable.From(() =>
  409. {
  410. _transmissionTween = null;
  411. }));
  412. _transmissionTween.Play();
  413. }
  414. }