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