Files
Main/Assets/Code/Logic/_Required/Input/Handler/JoystickHandler.cs
2025-01-25 04:38:09 +08:00

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
}
}