using Thousandto.Code.Center; using Thousandto.Code.Global; using Thousandto.Code.Logic.LocalPlayerBT; using Thousandto.Core.Asset; using Thousandto.Core.Base; using Thousandto.Plugins.Common.UniScene; using Thousandto.Plugins.PathGrid; using System; using System.Collections.Generic; using System.Text; using UnityEngine; namespace Thousandto.Code.Logic { /// /// 摇杆操作的处理器 /// public class JoystickHandler { #region //常量定义以及只读静态变量定义 //方向每个方向的角度偏移,180/16 == 11.25 private const float CN_DIR_DEGREE_OFFEST = 11.25f; //16向 //private const float CN_DIR_DEGREE_OFFEST = 22.5f; //8向 private Rect _joystickArea; private int _frontCheckScreenWidth = 0; //定义的X轴的方向 private readonly static Vector3[] CN_DIR_REMAP_X = new Vector3[] { Vector3.right, Vector3.right, Vector3.left, Vector3.left, }; //定义的Z轴的方向 private readonly static Vector3[] CN_DIR_REMAP_Z = new Vector3[] { Vector3.forward, Vector3.back, Vector3.back, Vector3.forward, }; //摇杆区域, public Rect JoystickArea { get { if (_frontCheckScreenWidth != Screen.width) { _joystickArea.x = 0f; _joystickArea.y = 0f; _joystickArea.width = Screen.width / 3f; _joystickArea.height = Screen.height / 2f; _frontCheckScreenWidth = Screen.width; } return _joystickArea; } } #endregion #region //私有变量 //开始的位置 private Vector2 _beginPos = Vector2.zero; //当前位置 private Vector2 _curDragPos = Vector2.zero; //摇杆的方向 private Vector2 _curJoystickDir = Vector2.zero; //是否能够捕捉拖拽处理,并创建摇杆命令 private bool _enableHoldDrag = true; //是否正在拖拽 private bool _draging = false; //当前拖拽的TouchID private int _curTouchID = 0; //当前的摇杆方向 private Vector2 _curWorldJoystickDir2d = Vector2.zero; //当前修正后的摇杆方向 private Vector2 _curAdjustedWorldJoystickDir2d = Vector2.zero; //主摄像机 private Camera _mainCamera = null; //当前场景的地形导航 private PathGridSystem _navigator = null; //角色控制器 private IPlayerInputer _player = null; private bool _isSpaceDown = false; private bool _isUseKeyBoard = false; private bool _isUseMouse = false; //UI检测点击处理 private IUIChecker _checkHitUI = null; #endregion #region //公共接口 //当前摇杆方向 public Vector2 CurWorldJoystickDir2d { get { return _curWorldJoystickDir2d; } } //是否正在拖拽 public bool Draging { get { return _draging; } } public int CurTouchID { get { return _curTouchID; } } //是否能够捕捉拖拽处理,并创建摇杆命令 public bool EnableHoldDrag { get { return _enableHoldDrag; } set { _enableHoldDrag = value; } } //刷新信息 public void Refresh(Camera camera, PathGridSystem navigator, IPlayerInputer player) { _mainCamera = camera; _navigator = navigator; _player = player; } public void Reset() { _mainCamera = null; _navigator = null; _player = null; _draging = false; } //设置UI检测对象 public void SetUIChecker(IUIChecker checker) { _checkHitUI = checker; } //开始摇杆处理 public void DoJoystickDragBegin(Vector2 pos, int touchID = -1) { LocalPlayer lp = GameCenter.GameSceneSystem.GetLocalPlayer(); if (lp == null) { return; } if (!EnableHoldDrag) { return; } _beginPos = pos; _curDragPos = pos; _draging = true; _curWorldJoystickDir2d = Vector2.zero; _curTouchID = touchID; GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_JOYSTICK_DRAGBEGIN, pos); } //摇杆移动 public void DoJoystickDraging(Vector2 pos) { LocalPlayer lp = GameCenter.GameSceneSystem.GetLocalPlayer(); if (lp == null) { return; } if (!EnableHoldDrag) { return; } if (!_draging) { return; } GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_JOYSTICK_DRAGING, pos); _curDragPos = pos; _curJoystickDir = (pos - _beginPos).normalized; _curWorldJoystickDir2d = JoystickDirToWorldDir(_curJoystickDir); Vector2 modDir; Vector2 curPos = _player.Position2d; if (AdjustDraggingAngle(curPos, _curWorldJoystickDir2d, out modDir)) { if (!lp.CanMove()) { lp.Stop_Action(); return; } PlayerBT.ChangeState(PlayerBDState.Default); //停止任务 GameCenter.TaskController.Stop(); if (modDir != _curAdjustedWorldJoystickDir2d) { _curAdjustedWorldJoystickDir2d = modDir; } GameCenter.LuaSystem.Adaptor.MandateOnMove(); GameCenter.LuaSystem.Adaptor.RefreshMandatePos(); lp.Action_DirMove(_curAdjustedWorldJoystickDir2d); } } //摇杆结束 public void DoJoystickDragEnd() { LocalPlayer lp = GameCenter.GameSceneSystem.GetLocalPlayer(); if (lp == null) { return; } if (!EnableHoldDrag) { return; } _curWorldJoystickDir2d = Vector2.zero; _draging = false; lp.Stop_Action(); GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_JOYSTICK_DRAGEND); GameCenter.LuaSystem.Adaptor.ReqCommandTargetPos(); } //摄像机yaw角度改变 public void OnCameraYawChanged() { if (!EnableHoldDrag) return; if (!_draging) return; _curWorldJoystickDir2d = JoystickDirToWorldDir(_curJoystickDir); Vector2 modDir; Vector2 curPos = _player.Position2d; if (AdjustDraggingAngle(curPos, _curWorldJoystickDir2d, out modDir)) { LocalPlayer lp = GameCenter.GameSceneSystem.GetLocalPlayer(); if (lp == null) { return; } if (!lp.CanMove()) { lp.Stop_Action(); return; } PlayerBT.ChangeState(PlayerBDState.Default); if (modDir != _curAdjustedWorldJoystickDir2d) { _curAdjustedWorldJoystickDir2d = modDir; } GameCenter.LuaSystem.Adaptor.MandateOnMove(); GameCenter.LuaSystem.Adaptor.RefreshMandatePos(); lp.Action_DirMove(_curAdjustedWorldJoystickDir2d); } } //摇杆处理器的心跳函数 public void Update() { if (_draging) { if (_curDragPos != _beginPos) { LocalPlayer lp = GameCenter.GameSceneSystem.GetLocalPlayer(); if ((lp != null && !lp.IsXState(EntityStateID.DirMove) && lp.IsTransAble(EntityStateID.DirMove) && lp.CanMove()) || _curAdjustedWorldJoystickDir2d != _curWorldJoystickDir2d) { DoJoystickDraging(_curDragPos); } } } #if USE_PC_MODEL || UNITY_EDITOR if (!_checkHitUI.IsSelectInputField()) { float dis = Input.GetAxis("Mouse ScrollWheel"); if (dis != 0f && GameCenter.InputSystem.CameraAdjustHandler.IsEnableCameraHandle) { var cameraControl = GameCenter.GameSceneSystem.ActivedScene.SceneCameraControl; float curDis = cameraControl.TarDis; curDis -= dis * 10f; if (curDis < 1f) { curDis = 1f; } if (curDis > 30f) { curDis = 30f; } cameraControl.TarDis = curDis; } #if USE_PC_MODEL if (!_isUseKeyBoard) { if (_isUseMouse) { DoJoystickDraging(Input.mousePosition); if (!Input.GetMouseButton(1)) { DoJoystickDragEnd(); _isUseMouse = false; } } else { //判断鼠标右键移动 if (Input.GetMouseButton(1) && !_checkHitUI.IsHitUI(0)) { _isUseMouse = true; DoJoystickDragBegin(new Vector2(Screen.width / 2f, Screen.height / 2f)); } } } else { _isUseMouse = false; } #endif if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.A)) { if (!_draging || _isUseMouse) { DoJoystickDragBegin(Vector2.zero); } else { DoJoystickDraging(new Vector2(-1f, 1f)); } _isUseKeyBoard = true; } else if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.D)) { if (!_draging || _isUseMouse) { DoJoystickDragBegin(Vector2.zero); } else { DoJoystickDraging(new Vector2(1f, 1f)); } _isUseKeyBoard = true; } else if (Input.GetKey(KeyCode.S) && Input.GetKey(KeyCode.A)) { if (!_draging || _isUseMouse) { DoJoystickDragBegin(Vector2.zero); } else { DoJoystickDraging(new Vector2(-1f, -1f)); } _isUseKeyBoard = true; } else if (Input.GetKey(KeyCode.S) && Input.GetKey(KeyCode.D)) { if (!_draging || _isUseMouse) { DoJoystickDragBegin(Vector2.zero); } else { DoJoystickDraging(new Vector2(1f, -1f)); } _isUseKeyBoard = true; } else if (Input.GetKey(KeyCode.W)) { if (!_draging || _isUseMouse) { DoJoystickDragBegin(Vector2.zero); } else { DoJoystickDraging(Vector2.up); } _isUseKeyBoard = true; } else if (Input.GetKey(KeyCode.S)) { if (!_draging || _isUseMouse) { DoJoystickDragBegin(Vector2.zero); } else { DoJoystickDraging(Vector2.down); } _isUseKeyBoard = true; } else if (Input.GetKey(KeyCode.A)) { if (!_draging || _isUseMouse) { DoJoystickDragBegin(Vector2.zero); } else { DoJoystickDraging(Vector2.left); } _isUseKeyBoard = true; } else if (Input.GetKey(KeyCode.D)) { if (!_draging || _isUseMouse) { DoJoystickDragBegin(Vector2.zero); } else { DoJoystickDraging(Vector2.right); } _isUseKeyBoard = true; } else { if (_isUseKeyBoard) { _isUseKeyBoard = false; DoJoystickDragEnd(); } } } #endif } #endregion #region//私有方法 //把摇杆的方向换算成为世界坐标系方向向量 private Vector2 JoystickDirToWorldDir(Vector2 joyDir) { float angle = Mathf.Atan2(joyDir.y, joyDir.x); int degree = (int)Mathf.Round(Mathf.Rad2Deg * angle); degree = (degree + 360) % 360; int degree16 = (int)(degree / CN_DIR_DEGREE_OFFEST); if (degree16 >= 31 || degree16 <= 0) { degree16 = 0; } float degreeReal = degree16 / 2 * CN_DIR_DEGREE_OFFEST * 2; Vector3 cdir = new Vector3(Mathf.Cos(Mathf.Deg2Rad * (-degree)), 0.0f, Mathf.Sin(Mathf.Deg2Rad * (-degree))); var wdir = _mainCamera.cameraToWorldMatrix.MultiplyVector(cdir); float yaw = MathLib.CalculateYaw(wdir); return new Vector2(Mathf.Sin(yaw), Mathf.Cos(yaw)); } //摇杆晃动中时,计算角色面向的新方向 private bool AdjustDraggingAngle(Vector2 curPos, Vector2 dir, out Vector2 newDir) { Vector3 pos = MathLib.ToVector3_XOZ(ref curPos); Vector3 curDir = MathLib.ToVector3_XOZ(ref dir); Vector3 nextStep = pos + curDir * (1.0f + float.Epsilon); if (!IsBlocked(pos, nextStep)) { newDir = dir; return true; } // [0, PI] var yaw = Mathf.Acos(Vector3.Dot(curDir, Vector3.forward)); if (dir.x < 0) { yaw = -yaw; //[-PI, 0] } // yaw: [-PI, PI] => [0, 2PI] yaw = MathLib.NormalizeRadian(yaw); int seg = (int)(yaw / MathLib.PI_Div2); Vector3 newDirX = CN_DIR_REMAP_X[seg]; Vector3 newDirZ = CN_DIR_REMAP_Z[seg]; if (IsBlocked(pos, pos + newDirX) == false) { newDir = MathLib.ToVector2_XOZ(newDirX); } else if (IsBlocked(pos, pos + newDirZ) == false) { newDir = MathLib.ToVector2_XOZ(newDirZ); } else { newDir = dir; return false; } return true; } //判断从开始点到结束点之间是否有阻挡 private bool IsBlocked(Vector3 start, Vector3 end) { var lp = GameCenter.GameSceneSystem.GetLocalPlayer(); if (lp == null) return true; Vector2 hit; return _navigator.Raycast2d(MathLib.ToVector2_XOZ(start), MathLib.ToVector2_XOZ(end), out hit); } #endregion } }