using System.Collections.Generic; using System.Linq; using Godot; using UI.RoomUI; namespace UI.RoomMap; /// <summary> /// 房间的小地图 /// </summary> public partial class RoomMapPanel : RoomMap { private EventFactory _factory = EventManager.CreateEventFactory(); //需要刷新的问号的房间队列 private List<RoomDoorInfo> _needRefresh = new List<RoomDoorInfo>(); //正在使用的敌人标记列表 private List<Sprite2D> _aiSpriteList = new List<Sprite2D>(); //已经回收的敌人标记 private Stack<Sprite2D> _spriteStack = new Stack<Sprite2D>(); //是否放大地图 private bool _isMagnifyMap = false; private UiEventBinder _dragBinder; //放大地图后拖拽的偏移 private Vector2 _mapOffset; //放大地图后鼠标悬停的房间 private RoomInfo _mouseHoverRoom; private Color _originOutlineColor; //是否展开地图 private bool _pressMapFlag = false; private Tween _transmissionTween; public override void OnCreateUi() { _ = S_Mark; S_Bg.Instance.Visible = false; S_MagnifyMapBar.Instance.Visible = false; InitMap(); _factory.AddEventListener(EventEnum.OnPlayerFirstEnterRoom, OnPlayerFirstEnterRoom); _factory.AddEventListener(EventEnum.OnPlayerFirstEnterAisle, OnPlayerFirstEnterAisle); S_DrawContainer.Instance.Resized += OnDrawContainerResized; } public override void OnDestroyUi() { _factory.RemoveAllEventListener(); if (_transmissionTween != null) { _transmissionTween.Dispose(); } } public override void Process(float delta) { var player = World.Current.Player; if (_transmissionTween == null) //不在传送过程中 { if (!InputManager.Map) { _pressMapFlag = false; } //按下地图按键 if (InputManager.Map && !_isMagnifyMap && !_pressMapFlag) //展开小地图 { if (UiManager.GetUiInstanceCount(UiManager.UiNames.PauseMenu) == 0 && !InputManager.Roulette) { ExpandMap(); } } else if (!InputManager.Map && _isMagnifyMap) //还原小地图 { ShrinkMap(); } } //更新敌人位置 { var aiList = World.Current.Role_InstanceList.Where(role => role != player).ToArray(); if (aiList.Length == 0) //没有敌人 { foreach (var sprite in _aiSpriteList) { S_Root.RemoveChild(sprite); _spriteStack.Push(sprite); } _aiSpriteList.Clear(); } else //更新位置 { var count = 0; //绘制数量 for (var i = 0; i < aiList.Length; i++) { var role = aiList[i]; if (role is AiRole aiRole && !aiRole.IsDestroyed && !aiRole.IsDie && aiRole.AffiliationArea != null && aiRole.AffiliationArea.RoomInfo.RoomFogMask.IsExplored) { count++; Sprite2D sprite; if (i >= _aiSpriteList.Count) { if (_spriteStack.Count > 0) { sprite = _spriteStack.Pop(); } else { sprite = new Sprite2D(); sprite.Texture = ResourceManager.LoadTexture2D(ResourcePath.resource_sprite_ui_commonIcon_Block_png); sprite.Modulate = new Color(1, 0, 0); } _aiSpriteList.Add(sprite); S_Root.AddChild(sprite); } else { sprite = _aiSpriteList[i]; } //更新标记位置 sprite.Position = aiRole.GetCenterPosition() / 16; } } //回收多余的标记 while (_aiSpriteList.Count > count) { var index = _aiSpriteList.Count - 1; var sprite = _aiSpriteList[index]; S_Root.RemoveChild(sprite); _spriteStack.Push(sprite); _aiSpriteList.RemoveAt(index); } } } //更新预览图标 if (_needRefresh.Count > 0) { foreach (var roomDoorInfo in _needRefresh) { HandlerRefreshUnknownSprite(roomDoorInfo); } _needRefresh.Clear(); } if (player != null) { //更新地图中心点位置 var playPosition = player.GetCenterPosition(); if (!_isMagnifyMap) { S_Root.Instance.Position = CalcRootPosition(playPosition); } else { S_Root.Instance.Position = CalcRootPosition(playPosition) + _mapOffset; S_Mark.Instance.Position = S_DrawContainer.Instance.Size / 2 + _mapOffset; } var area = player.AffiliationArea; //传送 if (_pressMapFlag && _mouseHoverRoom != null && area != null && !area.RoomInfo.IsSeclusion && Input.IsMouseButtonPressed(MouseButton.Right)) { //执行传送操作 DoTransmission((_mouseHoverRoom.Waypoints + new Vector2(0.5f, 0.5f)) * GameConfig.TileCellSize); ResetMap(); _isMagnifyMap = false; World.Current.Pause = false; } } } /// <summary> /// 执行展开地图 /// </summary> public void ExpandMap() { World.Current.Pause = true; _pressMapFlag = true; _isMagnifyMap = true; MagnifyMap(); } /// <summary> /// 执行收起地图 /// </summary> public void ShrinkMap() { ResetMap(); _isMagnifyMap = false; World.Current.Pause = false; } private void OnDrawContainerResized() { S_Mark.Instance.Position = S_DrawContainer.Instance.Size / 2; } //放大小地图 private void MagnifyMap() { GameApplication.Instance.Cursor.SetGuiMode(true); S_DrawContainer.Reparent(S_MagnifyMapBar); S_DrawContainer.Instance.Position = new Vector2(1, 1); S_Bg.Instance.Visible = true; S_MagnifyMapBar.Instance.Visible = true; S_MapBar.Instance.Visible = false; _mapOffset = Vector2.Zero; _dragBinder = S_DrawContainer.Instance.AddDragListener((state, delta) => { if (state == DragState.DragMove) { _mapOffset += delta; } }); } //还原小地图 private void ResetMap() { GameApplication.Instance.Cursor.SetGuiMode(false); S_DrawContainer.Reparent(S_MapBar); S_DrawContainer.Instance.Position = new Vector2(1, 1); S_Bg.Instance.Visible = false; S_MagnifyMapBar.Instance.Visible = false; S_MapBar.Instance.Visible = true; ResetOutlineColor(); if (_dragBinder != null) { _dragBinder.UnBind(); _dragBinder = null; } } private void ResetOutlineColor() { if (_mouseHoverRoom != null) { ((ShaderMaterial)_mouseHoverRoom.PreviewSprite.Material).SetShaderParameter("outline_color", _originOutlineColor); _mouseHoverRoom = null; } } //初始化小地图 private void InitMap() { var startRoom = GameApplication.Instance.DungeonManager.StartRoomInfo; if (startRoom == null) { HideUi(); return; } startRoom.EachRoom(roomInfo => { //房间 roomInfo.PreviewSprite.Visible = false; S_Root.AddChild(roomInfo.PreviewSprite); roomInfo.PreviewSprite.MouseEntered += () => { if (!_pressMapFlag) { return; } ResetOutlineColor(); _mouseHoverRoom = roomInfo; var shaderMaterial = (ShaderMaterial)roomInfo.PreviewSprite.Material; _originOutlineColor = shaderMaterial.GetShaderParameter("outline_color").AsColor(); //玩家所在的房间门是否打开 var area = World.Current.Player.AffiliationArea; if (area != null) { var isOpen = !area.RoomInfo.IsSeclusion; if (isOpen) { shaderMaterial.SetShaderParameter("outline_color", new Color(0, 1, 0, 0.9f)); } else { shaderMaterial.SetShaderParameter("outline_color", new Color(1, 0, 0, 0.9f)); } } }; roomInfo.PreviewSprite.MouseExited += () => { if (!_pressMapFlag) { return; } ResetOutlineColor(); }; //过道 if (roomInfo.Doors != null) { foreach (var roomInfoDoor in roomInfo.Doors) { if (roomInfoDoor.IsForward) { roomInfoDoor.AislePreviewSprite.Visible = false; S_Root.AddChild(roomInfoDoor.AislePreviewSprite); } } } }); } private void OnPlayerFirstEnterRoom(object data) { var roomInfo = (RoomInfo)data; if (roomInfo.PreviewSprite != null) { roomInfo.PreviewSprite.Visible = true; } if (roomInfo.Doors!= null) { foreach (var roomDoor in roomInfo.Doors) { RefreshUnknownSprite(roomDoor); } } } private void OnPlayerFirstEnterAisle(object data) { var roomDoorInfo = (RoomDoorInfo)data; roomDoorInfo.AislePreviewSprite.Visible = true; RefreshUnknownSprite(roomDoorInfo); RefreshUnknownSprite(roomDoorInfo.ConnectDoor); } //进入刷新问号队列 private void RefreshUnknownSprite(RoomDoorInfo roomDoorInfo) { if (!_needRefresh.Contains(roomDoorInfo)) { _needRefresh.Add(roomDoorInfo); } } //刷新问号 private void HandlerRefreshUnknownSprite(RoomDoorInfo roomDoorInfo) { //是否探索房间 var flag1 = roomDoorInfo.RoomInfo.RoomFogMask.IsExplored; //是否探索过道 var flag2 = roomDoorInfo.AisleFogMask.IsExplored; if (flag1 == flag2) //不显示问号 { if (roomDoorInfo.UnknownSprite != null) { roomDoorInfo.UnknownSprite.QueueFree(); roomDoorInfo.UnknownSprite = null; } } else { var unknownSprite = roomDoorInfo.UnknownSprite ?? CreateUnknownSprite(roomDoorInfo); var pos = (roomDoorInfo.OriginPosition + roomDoorInfo.GetEndPosition()) / 2; if (!flag2) //偏向过道 { if (roomDoorInfo.Direction == DoorDirection.N) pos += new Vector2I(0, -1); else if (roomDoorInfo.Direction == DoorDirection.S) pos += new Vector2I(0, 3); else if (roomDoorInfo.Direction == DoorDirection.E) pos += new Vector2I(2, 1); else if (roomDoorInfo.Direction == DoorDirection.W) pos += new Vector2I(-2, 1); } else //偏向房间 { if (roomDoorInfo.Direction == DoorDirection.N) pos -= new Vector2I(0, -4); else if (roomDoorInfo.Direction == DoorDirection.S) pos -= new Vector2I(0, 1); else if (roomDoorInfo.Direction == DoorDirection.E) pos -= new Vector2I(3, -1); else if (roomDoorInfo.Direction == DoorDirection.W) pos -= new Vector2I(-3, -1); } unknownSprite.Position = pos; } } private Sprite2D CreateUnknownSprite(RoomDoorInfo roomInfoDoor) { var unknownSprite = new Sprite2D(); unknownSprite.Texture = ResourceManager.LoadTexture2D(ResourcePath.resource_sprite_ui_commonIcon_Unknown_png); unknownSprite.Scale = new Vector2(0.25f, 0.25f); roomInfoDoor.UnknownSprite = unknownSprite; S_Root.AddChild(unknownSprite); return unknownSprite; } private Vector2 CalcRootPosition(Vector2 pos) { return S_DrawContainer.Instance.Size / 2 - pos / 16 * S_Root.Instance.Scale; } private void DoTransmission(Vector2 position) { var roomUI = (RoomUIPanel)ParentUi; roomUI.S_Mask.Instance.Visible = true; roomUI.S_Mask.Instance.Color = new Color(0, 0, 0, 0); _transmissionTween = CreateTween(); _transmissionTween.TweenProperty(roomUI.S_Mask.Instance, "color", new Color(0, 0, 0), 0.3f); _transmissionTween.TweenCallback(Callable.From(() => { World.Current.Player.Position = position; })); _transmissionTween.TweenInterval(0.2f); _transmissionTween.TweenProperty(roomUI.S_Mask.Instance, "color", new Color(0, 0, 0, 0), 0.3f); _transmissionTween.TweenCallback(Callable.From(() => { _transmissionTween = null; })); _transmissionTween.Play(); } }