using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using System; using UnityEngine.EventSystems; namespace Snxxz.UI { public class LocalMapFindPath : MonoBehaviour, IPointerClickHandler { const float NODE_SPACEOUT = 3f; [SerializeField] float m_StandardSize = 50f; [SerializeField] BoundedDrag m_BoundDrag; [SerializeField] RectTransform m_LocalMapRect; [SerializeField] Image m_MapImage; [SerializeField] Transform m_ContainerPathNode; [SerializeField] Image m_HeroHead; [SerializeField] LocalMapEventPointInstroduce m_EventPointInstroduce; [SerializeField] Transform m_SelecteEventPointSign; LocalMap mapMatrix; Vector3 heroPrePosition = new Vector3(-999, -8888, 0); private List pathNodeBehaviours = new List(); //寻路点池 List tagBehaviours = new List(); MapModel model { get { return ModelCenter.Instance.GetModel(); } } int mapId = 0; public void Init(int _mapId) { mapId = _mapId; if (mapId != mapMatrix.mapId) { PathPointClear(); } if (mapId == PlayerDatas.Instance.baseData.MapID) { m_HeroHead.gameObject.SetActive(true); var job = PlayerDatas.Instance.baseData.Job; m_HeroHead.SetSprite(GeneralDefine.GetJobHeadPortrait(job, 0)); } else { m_HeroHead.gameObject.SetActive(false); } var dataMapId = MapUtility.GetDataMapId(mapId); var mapResConfig = MapResourcesConfig.GetConfig(dataMapId, 0); 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.SetSprite(mapResConfig.BigMap); m_MapImage.SetNativeSize(); var offsetX = Mathf.Clamp((uiMapWidth - m_BoundDrag.rectTransform.rect.width) * 0.5f, 0, float.MaxValue); var offsetY = Mathf.Clamp((uiMapHeight - m_BoundDrag.rectTransform.rect.height) * 0.5f, 0, float.MaxValue); m_BoundDrag.moveArea = new BoundedDrag.MoveArea(-offsetX, offsetX, offsetY, -offsetY); mapMatrix = new LocalMap(mapId, mapWidth, mapHeight, uiMapWidth, uiMapHeight); DrawWayPoints(); DrawFunctionNPCs(); DrawEventPoints(); m_HeroHead.transform.SetAsLastSibling(); FoucsEventPoint(model.selectedMapEventPoint); m_BoundDrag.onBeginDrag.RemoveAllListeners(); m_BoundDrag.onBeginDrag.AddListener(OnBeginDrag); model.selectMapEventPointEvent += FoucsEventPoint; if (PlayerDatas.Instance.baseData.MapID == mapId) { var hero = PlayerDatas.Instance.hero; if (hero != null) { if (hero.PathFindStatus == GActor.E_PathFindStatus.Moving) { OnHeroStartMove(); } else { OnHeroStopMove(); } hero.OnPathFinding += OnHeroStartMove; hero.OnPathFindStop += OnHeroStopMove; } } } public void UnInit() { var hero = PlayerDatas.Instance.hero; if (hero != null) { hero.OnPathFinding -= OnHeroStartMove; hero.OnPathFindStop -= OnHeroStopMove; } model.selectMapEventPointEvent -= FoucsEventPoint; m_BoundDrag.onBeginDrag.RemoveAllListeners(); for (int i = 0; i < tagBehaviours.Count; i++) { LocalMapTagPool.Recycle(tagBehaviours[i]); } tagBehaviours.Clear(); } void HeroMoveTo(Vector3 _position) { if (mapId != PlayerDatas.Instance.baseData.MapID) { return; } 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 if (RectTransformUtility.RectangleContainsScreenPoint((RectTransform)this.transform, Input.mousePosition, CameraManager.uiCamera) && !RectTransformUtility.RectangleContainsScreenPoint(m_EventPointInstroduce.containerDetails, Input.mousePosition, CameraManager.uiCamera)) { model.selectedMapEventPoint = -1; } } private void LateUpdate() { if (mapId == PlayerDatas.Instance.baseData.MapID) { UpdateHeroPosition(); } } Vector3 ScreenToWorldPosition(Vector3 _sp) { var originalPoint = CameraManager.uiCamera.WorldToViewportPoint(UIUtility.GetMinWorldPosition(m_LocalMapRect)); var spToViewPoint = CameraManager.uiCamera.ScreenToViewportPoint(_sp); var delta = spToViewPoint - originalPoint; var adjustScale = (Screen.width / (float)Screen.height) / (Constants.DESIGN_RESOLUTION.x / Constants.DESIGN_RESOLUTION.y); var adjustX = delta.x * Constants.DESIGN_RESOLUTION.x * (adjustScale > 1f ? adjustScale : 1f) / m_LocalMapRect.rect.width; var adjustY = delta.y * Constants.DESIGN_RESOLUTION.y / (adjustScale < 1f ? adjustScale : 1f) / m_LocalMapRect.rect.height; var adjustedViewPoint = new Vector2(adjustX, adjustY); 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 DrawEventPoints() { var eventPoints = model.GetMapEventPoints(mapId); for (int i = 0; i < eventPoints.Count; i++) { var eventPoint = eventPoints[i]; DrawEventPoint(eventPoint); } } private void DrawEventPoint(int _eventPoint) { var eventPointConfig = MapEventPointConfig.Get(_eventPoint); if (eventPointConfig.ShowInMipMap == 0) { return; } var npcType = LocalMapTag.TagType.Boss; var npcConfig = NPCConfig.Get(eventPointConfig.NPCID); if (eventPointConfig.IsShowInfo == 1) { if (npcConfig.NPCType == (int)E_NpcType.Func) { npcType = LocalMapTag.TagType.Function; } else if (npcConfig.NPCType == (int)E_NpcType.Fight) { switch ((E_MonsterType)npcConfig.IsBoss) { case E_MonsterType.Normal: npcType = LocalMapTag.TagType.Monster; break; default: npcType = LocalMapTag.TagType.Elite; break; } } } else { npcType = LocalMapTag.TagType.Boss; } var monsterRefreshConfig = MonsterRefreshPointConfig.Get(npcConfig.NPCID); var npcPos = new Vector3(monsterRefreshConfig.Position.x * 0.5f, 0, monsterRefreshConfig.Position.y * 0.5f); var behaviour = LocalMapTagPool.Require(npcType); tagBehaviours.Add(behaviour); if (npcType == LocalMapTag.TagType.Boss) { behaviour.Display(eventPointConfig.NPCID, (TextColType)eventPointConfig.Colour, npcPos); } else { behaviour.Display(npcConfig.NPCID, (TextColType)eventPointConfig.Colour); } var pathPointPos = mapMatrix.WorldToLocalPosition(npcPos); behaviour.transform.SetParentEx(m_LocalMapRect, pathPointPos, Quaternion.identity, Vector3.one); behaviour.gameObject.SetActive(true); } private void DrawWayPoints() { var waypoints = maptransportConfig.GetValues(); foreach (var waypoint in waypoints) { if (waypoint.OriginalMapID == this.mapId) { DrawWayPoint(waypoint.TransportID); } } } private void DrawWayPoint(int _wayPoint) { var config = maptransportConfig.Get(_wayPoint.ToString()); var behaviour = LocalMapTagPool.Require(LocalMapTag.TagType.WayPoint); tagBehaviours.Add(behaviour); var position = new Vector3(config.OriginalPosX * 0.5f, 0, config.OriginalPosY * 0.5f); var pathPointPos = mapMatrix.WorldToLocalPosition(position); behaviour.transform.SetParentEx(m_LocalMapRect, pathPointPos, Quaternion.identity, Vector3.one); behaviour.gameObject.SetActive(true); } private void DrawFunctionNPCs() { var npcRefreshIds = model.GetMapNPCRefreshIds(mapId); if (npcRefreshIds != null) { foreach (var item in npcRefreshIds) { var config = mapnpcConfig.Get(item); var npcConfig = NPCConfig.Get(config.NPCID); DrawFunctionNPC(item); } } } private void DrawFunctionNPC(string _refreshId) { var mapNpcConfig = mapnpcConfig.Get(_refreshId); var behaviour = LocalMapTagPool.Require(LocalMapTag.TagType.Function); tagBehaviours.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.gameObject.SetActive(true); behaviour.Display(mapNpcConfig.NPCID, TextColType.White); } private void UpdateHeroPosition() { if (mapId == PlayerDatas.Instance.baseData.MapID) { var heroPos = mapMatrix.WorldToLocalPosition(PlayerDatas.Instance.hero.Pos); if (Vector3.Distance(heroPrePosition, heroPos) > 0.01f) { m_HeroHead.transform.localPosition = heroPos; } } } private void PathPointClear() { for (int i = pathNodeBehaviours.Count - 1; i >= 0; i--) { pathNodeBehaviours[i].SetActive(false); } } private Vector3[] GetWorldPathNodes(Vector3 targetPos) { return PlayerDatas.Instance.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 void FoucsEventPoint(int _eventPoint) { if (model.selectedMapEventPoint != -1) { var config = MapEventPointConfig.Get(_eventPoint); var monsterRefreshConfig = MonsterRefreshPointConfig.Get(config.NPCID); var position = new Vector3(monsterRefreshConfig.Position.x * 0.5f, 0, monsterRefreshConfig.Position.y * 0.5f); var localPosition = mapMatrix.WorldToLocalPosition(position); m_BoundDrag.destPosition = -1 * localPosition; if (localPosition.y >= 0f) { m_SelecteEventPointSign.localPosition = localPosition.SetY(localPosition.y - 15); } else { m_SelecteEventPointSign.localPosition = localPosition.SetY(localPosition.y + 15); } m_EventPointInstroduce.gameObject.SetActive(true); m_EventPointInstroduce.Display(model.selectedMapEventPoint, m_SelecteEventPointSign); } else { m_EventPointInstroduce.gameObject.SetActive(false); } } 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() { if (PlayerDatas.Instance.hero == null) { return; } GeneratePathNodes(PlayerDatas.Instance.hero.DestPos); } private void OnHeroStopMove() { if (PlayerDatas.Instance.hero == null) { return; } PathPointClear(); } private void OnBeginDrag() { model.selectedMapEventPoint = -1; } public struct LocalMap { public int mapId; public float worldMapWidth; public float worldMapHeight; public float localMapWidth; public float localMapHeight; public LocalMap(int mId, float mWidth, float mHeigth, float mSpriteWidth, float mSpriteHeight) { mapId = mId; worldMapWidth = mWidth; worldMapHeight = mHeigth; localMapWidth = mSpriteWidth; localMapHeight = mSpriteHeight; } public Vector3 WorldToLocalPosition(Vector3 _worldPosition) { var x = ((_worldPosition.x - worldMapWidth * 0.5f) / worldMapWidth) * localMapWidth; var y = ((_worldPosition.z - worldMapHeight * 0.5f) / worldMapHeight) * localMapHeight; return new Vector3(x, y, 0); } } } }