using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace vnxbqy.UI { public class FairyLeagueMap : MonoBehaviour, IPointerClickHandler { const float NODE_SPACEOUT = 3f; [SerializeField] float m_StandardSize = 50f; [SerializeField] RectTransform m_LocalMapRect; [SerializeField] Image m_MapImage; [SerializeField] Transform m_ContainerPathNode; [SerializeField] AvatarCell m_AvatarCell; [SerializeField] RectTransform m_AvatarRect; LocalMapFindPath.LocalMap mapMatrix; Vector3 heroPrePosition = new Vector3(-999, -8888, 0); private List pathNodeBehaviours = new List(); //寻路点池 List crystalBehaviours = new List(); List buffBehaviours = new List(); MapModel m_Model; MapModel model { get { return m_Model ?? (m_Model = ModelCenter.Instance.GetModel()); } } FairyLeagueModel m_FairyLeagueModel; FairyLeagueModel fairyLeagueModel { get { return m_FairyLeagueModel ?? (m_FairyLeagueModel = ModelCenter.Instance.GetModel()); } } private List fairyCrystalCfgs = new List(); int mapId = 0; public void Init(int _mapId) { if (_mapId != mapMatrix.mapId) { PathPointClear(); } m_AvatarCell.InitUI(AvatarHelper.GetMyAvatarModel()); if (fairyCrystalCfgs.Count == 0) { var _refreshNpcs = ModelCenter.Instance.GetModel().GetMapCollectNPCRefreshIds(FairyLeagueModel.FAIRY_LEAGUE_DUNGEON); if (_refreshNpcs != null) { for (int i = 0; i < _refreshNpcs.Count; i++) { fairyCrystalCfgs.Add(mapnpcConfig.Get(_refreshNpcs[i])); } } } mapId = _mapId; var dataMapId = MapUtility.GetDataMapId(); var lineId = MapUtility.GetLineId(); var mapResConfig = MapResourcesConfig.GetConfig(dataMapId,lineId); var tagChinMap = MapConfig.Get(mapId); var mapWidth = mapResConfig.MapScale.x; var mapHeight = mapResConfig.MapScale.y; m_StandardSize = mapResConfig.MapShowScale; var uiMapWidth = mapWidth * m_StandardSize; var uiMapHeight = mapHeight * m_StandardSize; m_LocalMapRect.sizeDelta = new Vector2(uiMapWidth, uiMapHeight); m_MapImage.rectTransform.sizeDelta = new Vector2(uiMapWidth, uiMapHeight); m_MapImage.SetSprite(mapResConfig.BigMap); m_MapImage.SetNativeSize(); mapMatrix = new LocalMapFindPath.LocalMap(mapId, mapWidth, mapHeight, uiMapWidth, uiMapHeight); m_AvatarRect.transform.SetAsLastSibling(); var hero = PlayerDatas.Instance.hero; DrawFairyLeagueCrystal(); DrawFairyLeagueBuffs(); if (hero != null) { if (hero.PathFindStatus == GActor.E_PathFindStatus.Moving) { OnHeroStartMove(); } else { OnHeroStopMove(); } hero.OnPathFindStart += OnHeroStartMove; hero.OnPathFindStop += OnHeroStopMove; } fairyLeagueModel.UpdateWarBuffEvent += DrawFairyLeagueBuffs; } public void UnInit() { fairyLeagueModel.UpdateWarBuffEvent -= DrawFairyLeagueBuffs; var hero = PlayerDatas.Instance.hero; if (hero != null) { hero.OnPathFindStart -= OnHeroStartMove; hero.OnPathFindStop -= OnHeroStopMove; } for (int i = 0; i < crystalBehaviours.Count; i++) { LocalMapTagPool.Recycle(crystalBehaviours[i]); } crystalBehaviours.Clear(); ClearWarBuffs(); } private void LateUpdate() { UpdateHeroPosition(); } #region 地图相关 void HeroMoveTo(Vector3 _position) { if (PlayerDatas.Instance.hero == null) { return; } var position = GetGroundPosition(_position); PlayerDatas.Instance.hero.Behaviour.StopHandupAI(); PlayerDatas.Instance.hero.IdleImmediate(); PlayerDatas.Instance.hero.MoveToPosition(position); } public void OnPointerClick(PointerEventData eventData) { #if UNITY_EDITOR if (RectTransformUtility.RectangleContainsScreenPoint(m_LocalMapRect, Input.mousePosition, CameraManager.uiCamera)) { HeroMoveTo(ScreenToWorldPosition(Input.mousePosition)); } #else if (RectTransformUtility.RectangleContainsScreenPoint(m_LocalMapRect, Input.mousePosition,CameraManager.uiCamera)) { HeroMoveTo( ScreenToWorldPosition(Input.touches[0].position)); } #endif } Vector3 ScreenToWorldPosition(Vector3 _sp) { var originalPoint = CameraManager.uiCamera.WorldToViewportPoint(UIUtility.GetMinWorldPosition(m_LocalMapRect)); var spToViewPoint = CameraManager.uiCamera.ScreenToViewportPoint(_sp); var delta = spToViewPoint - originalPoint; var adjustedViewPoint = new Vector2(delta.x * Constants.DESIGN_RESOLUTION.x / m_LocalMapRect.rect.width, delta.y * Constants.DESIGN_RESOLUTION.y / m_LocalMapRect.rect.height); return new Vector3(mapMatrix.worldMapWidth * adjustedViewPoint.x, 0, mapMatrix.worldMapHeight * adjustedViewPoint.y); } private void GeneratePathNodes(Vector3 targetPos) { var pathVertexArray = GetWorldPathNodes(targetPos); if (pathVertexArray == null) { return; } PathPointClear(); var nodes = NodeLerp(pathVertexArray); if (nodes == null) { return; } InstantiateNodeBehaviours(nodes.Count); for (int i = 0; i < nodes.Count; i++) { var position = mapMatrix.WorldToLocalPosition(nodes[i]); pathNodeBehaviours[i].transform.localPosition = position; pathNodeBehaviours[i].SetActive(true); } } private void UpdateHeroPosition() { if (mapId == PlayerDatas.Instance.baseData.MapID) { if (PlayerDatas.Instance.hero == null) { return; } var heroPos = mapMatrix.WorldToLocalPosition(PlayerDatas.Instance.hero.Pos); if (Vector3.Distance(heroPrePosition, heroPos) > 0.01f) { m_AvatarRect.transform.localPosition = heroPos; } } } private void PathPointClear() { for (int i = pathNodeBehaviours.Count - 1; i >= 0; i--) { pathNodeBehaviours[i].SetActive(false); } } private Vector3[] GetWorldPathNodes(Vector3 targetPos) { var hero = PlayerDatas.Instance.hero; if (null == hero) { return null; } return hero.GetCorners(); } List NodeLerp(Vector3[] _originalNodes) { if (_originalNodes == null || _originalNodes.Length < 2) { return null; } var nodes = new List(); nodes.Add(_originalNodes[0]); var acclength = 0f; for (int i = 0; i < _originalNodes.Length - 1; i++) { var node1 = _originalNodes[i]; var node2 = _originalNodes[i + 1]; var direction = Vector3.Normalize(node2 - node1); var distance = Vector3.Distance(node1, node2); while (acclength < distance) { nodes.Add(node1 + direction * acclength); acclength += NODE_SPACEOUT; } acclength = acclength - distance; } if (Vector3.Distance(nodes[nodes.Count - 1], _originalNodes[_originalNodes.Length - 1]) > NODE_SPACEOUT * 0.5f) { nodes.Add(_originalNodes[_originalNodes.Length - 1]); } return nodes; } void InstantiateNodeBehaviours(int _count) { var now = pathNodeBehaviours.Count; var dif = _count - now; if (dif > 0) { var prefab = UILoader.LoadPrefab("LocalMap_PathNode"); for (int i = 0; i < dif; i++) { var instance = Instantiate(prefab); pathNodeBehaviours.Add(instance); instance.transform.SetParentEx(m_ContainerPathNode, Vector3.zero, Quaternion.identity, Vector3.one); } } } private Vector3 GetGroundPosition(Vector3 _xzPosition) { RaycastHit hit; var ray = new Ray(_xzPosition.SetY(50f), Vector3.down); if (Physics.Raycast(ray, out hit, 100f, LayerUtility.WalkbleMask)) { return hit.point; } else { return _xzPosition; } } private void OnHeroStartMove() { var hero = PlayerDatas.Instance.hero; if (hero == null) { return; } GeneratePathNodes(hero.DestPos); } private void OnHeroStopMove() { var hero = PlayerDatas.Instance.hero; if (hero == null) { return; } PathPointClear(); } #endregion private void DrawFairyLeagueCrystal() { for (int i = 0; i < fairyLeagueModel.fairyLeagueCrystals.Length; i++) { var _crystalNpc = fairyLeagueModel.fairyLeagueCrystals[i]; var _index = fairyCrystalCfgs.FindIndex((x) => { return x.NPCID == _crystalNpc; }); if (_index == -1) { return; } var mapNpcConfig = fairyCrystalCfgs[_index]; var behaviour = LocalMapTagPool.Require(LocalMapTag.TagType.Crystal); crystalBehaviours.Add(behaviour); var originalPosition = GAStaticDefine.GetClientPostionFromHex(mapNpcConfig.HexPosNPCRefreshAreaChaseArea); var position = new Vector3(originalPosition.x, 0, originalPosition.y); var pathPointPos = mapMatrix.WorldToLocalPosition(position); behaviour.transform.SetParentEx(m_LocalMapRect, pathPointPos, Quaternion.identity, Vector3.one); behaviour.SetActive(true); behaviour.Display(mapNpcConfig.NPCID, TextColType.White); } } private void DrawFairyLeagueBuffs() { var _help = fairyLeagueModel.fairyLeagueHelp; ClearWarBuffs(); if (_help.fairyWarBuffs == null || _help.fairyWarBuffs.Length == 0) { return; } for (int i = 0; i < _help.fairyWarBuffs.Length; i++) { var _buffIndex = _help.fairyWarBuffs[i].PosIndex; var behaviour = LocalMapTagPool.Require(LocalMapTag.TagType.FairyLeagueBuff); buffBehaviours.Add(behaviour); Vector2 _buffPos = fairyLeagueModel.crystalPosList[_buffIndex]; var position = new Vector3(_buffPos.x, 0, _buffPos.y); var pathPointPos = mapMatrix.WorldToLocalPosition(position); behaviour.transform.SetParentEx(m_LocalMapRect, pathPointPos, Quaternion.identity, Vector3.one); behaviour.SetActive(true); behaviour.Display(_buffIndex); } } private void ClearWarBuffs() { for (int i = 0; i < buffBehaviours.Count; i++) { LocalMapTagPool.Recycle(buffBehaviours[i]); } } } }