515 lines
16 KiB
C#
515 lines
16 KiB
C#
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
|
|
{
|
|
/// <summary>
|
|
/// 摇杆操作的处理器
|
|
/// </summary>
|
|
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
|
|
}
|
|
}
|