using System.Collections.Generic; 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> _enemySpriteList = new List<Sprite2D>(); //已经回收的敌人标记 private Stack<Sprite2D> _spriteStack = new Stack<Sprite2D>(); //是否放大地图 private bool _isMagnifyMap = false; private DragBinder _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 (_dragBinder != null) { _dragBinder.UnBind(); } if (_transmissionTween != null) { _transmissionTween.Dispose(); } } public override void Process(float delta) { if (_transmissionTween == null) //不在传送过程中 { if (!InputManager.Map) { _pressMapFlag = false; } //按下地图按键 if (InputManager.Map && !_isMagnifyMap && !_pressMapFlag) //展开小地图 { if (UiManager.GetUiInstanceCount(UiManager.UiName.PauseMenu) == 0) { World.Current.Pause = true; _pressMapFlag = true; _isMagnifyMap = true; MagnifyMap(); } } else if (!InputManager.Map && _isMagnifyMap) //还原小地图 { ResetMap(); _isMagnifyMap = false; World.Current.Pause = false; } } //更新敌人位置 { var enemyList = World.Current.Enemy_InstanceList; if (enemyList.Count == 0) //没有敌人 { foreach (var sprite in _enemySpriteList) { S_Root.RemoveChild(sprite); _spriteStack.Push(sprite); } _enemySpriteList.Clear(); } else //更新位置 { var count = 0; //绘制数量 for (var i = 0; i < enemyList.Count; i++) { var enemy = enemyList[i]; if (!enemy.IsDestroyed && !enemy.IsDie && enemy.AffiliationArea != null && enemy.AffiliationArea.RoomInfo.RoomFogMask.IsExplored) { count++; Sprite2D sprite; if (i >= _enemySpriteList.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); } _enemySpriteList.Add(sprite); S_Root.AddChild(sprite); } else { sprite = _enemySpriteList[i]; } //更新标记位置 sprite.Position = enemy.Position / 16; } } //回收多余的标记 while (_enemySpriteList.Count > count) { var index = _enemySpriteList.Count - 1; var sprite = _enemySpriteList[index]; S_Root.RemoveChild(sprite); _spriteStack.Push(sprite); _enemySpriteList.RemoveAt(index); } } } //更新预览图标 if (_needRefresh.Count > 0) { foreach (var roomDoorInfo in _needRefresh) { HandlerRefreshUnknownSprite(roomDoorInfo); } _needRefresh.Clear(); } //更新地图中心点位置 if (!_isMagnifyMap) { S_Root.Instance.Position = CalcRootPosition(Player.Current.Position); } else { S_Root.Instance.Position = CalcRootPosition(Player.Current.Position) + _mapOffset; S_Mark.Instance.Position = S_DrawContainer.Instance.Size / 2 + _mapOffset; } //传送 if (_pressMapFlag && _mouseHoverRoom != null && !Player.Current.AffiliationArea.RoomInfo.IsSeclusion && Input.IsMouseButtonPressed(MouseButton.Right)) { //执行传送操作 DoTransmission((_mouseHoverRoom.Waypoints + new Vector2(0.5f, 0.5f)) * GameConfig.TileCellSize); 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 = DragUiManager.BindDrag(S_DrawContainer.Instance, (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(); } } 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; 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 isOpen = !Player.Current.AffiliationArea.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; 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, -2); else if (roomDoorInfo.Direction == DoorDirection.S) pos += new Vector2I(0, 2); else if (roomDoorInfo.Direction == DoorDirection.E) pos += new Vector2I(2, 0); else if (roomDoorInfo.Direction == DoorDirection.W) pos += new Vector2I(-2, 0); } else //偏向房间 { if (roomDoorInfo.Direction == DoorDirection.N) pos -= new Vector2I(0, -2); else if (roomDoorInfo.Direction == DoorDirection.S) pos -= new Vector2I(0, 2); else if (roomDoorInfo.Direction == DoorDirection.E) pos -= new Vector2I(2, 0); else if (roomDoorInfo.Direction == DoorDirection.W) pos -= new Vector2I(-2, 0); } 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(() => { Player.Current.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(); } }