diff --git a/src/Ecctrl.tsx b/src/Ecctrl.tsx index 052552c..328c847 100644 --- a/src/Ecctrl.tsx +++ b/src/Ecctrl.tsx @@ -69,6 +69,10 @@ const Ecctrl: ForwardRefRenderFunction = ({ camTargetPos = { x: 0, y: 0, z: 0 }, camMoveSpeed = 1, camZoomSpeed = 1, + camInvertX = false, + camInvertY = false, + leftJoystickDeadZoneThreshold = 0, + rightJoystickDeadZoneThreshold = 0, camCollision = true, camCollisionOffset = 0.7, camCollisionSpeedMult = 4, @@ -511,10 +515,16 @@ const Ecctrl: ForwardRefRenderFunction = ({ } } + const applyDeadZone = (value: number, threshold: number) => { + return Math.abs(value) > threshold ? value : 0; + } + const handleSticks = (axes: readonly number[]) => { + const adjustedLeftStickX = applyDeadZone(axes[0], leftJoystickDeadZoneThreshold); + const adjustedLeftStickY = applyDeadZone(axes[1], leftJoystickDeadZoneThreshold); // Gamepad first joystick trigger the EcctrlJoystick event to move the character - if (Math.abs(axes[0]) > 0 || Math.abs(axes[1]) > 0) { - gamepadJoystickVec2.set(axes[0], -axes[1]) + if (Math.abs(adjustedLeftStickX) > 0 || Math.abs(adjustedLeftStickY) > 0) { + gamepadJoystickVec2.set(adjustedLeftStickX, -adjustedLeftStickY) gamepadJoystickDis = Math.min(Math.sqrt(Math.pow(gamepadJoystickVec2.x, 2) + Math.pow(gamepadJoystickVec2.y, 2)), 1) gamepadJoystickAng = gamepadJoystickVec2.angle() const runState = gamepadJoystickDis > 0.7 @@ -524,9 +534,11 @@ const Ecctrl: ForwardRefRenderFunction = ({ gamepadJoystickAng = 0 resetJoystick() } + const adjustedRightStickX = applyDeadZone(axes[2], rightJoystickDeadZoneThreshold); + const adjustedRightStickY = applyDeadZone(axes[3], rightJoystickDeadZoneThreshold); // Gamepad second joystick trigger the useFollowCam event to move the camera - if (Math.abs(axes[2]) > 0 || Math.abs(axes[3]) > 0) { - joystickCamMove(axes[2], axes[3]) + if (Math.abs(adjustedRightStickX) > 0 || Math.abs(adjustedRightStickY) > 0) { + joystickCamMove(adjustedRightStickX, adjustedRightStickY); } } @@ -569,6 +581,8 @@ const Ecctrl: ForwardRefRenderFunction = ({ camCollisionOffset, camCollisionSpeedMult, camListenerTarget, + camInvertX, + camInvertY }; /** @@ -1566,6 +1580,10 @@ export interface EcctrlProps extends RigidBodyProps { camTargetPos?: { x: number, y: number, z: number }; camMoveSpeed?: number; camZoomSpeed?: number; + camInvertX?: boolean, + camInvertY?: boolean, + leftJoystickDeadZoneThreshold?: number; + rightJoystickDeadZoneThreshold?: number; camCollision?: boolean; camCollisionOffset?: number; camCollisionSpeedMult?: number; diff --git a/src/hooks/useFollowCam.tsx b/src/hooks/useFollowCam.tsx index 9e2710b..af820f3 100644 --- a/src/hooks/useFollowCam.tsx +++ b/src/hooks/useFollowCam.tsx @@ -16,6 +16,8 @@ export const useFollowCam = function ({ camInitDir = { x: 0, y: 0 }, // in rad camMoveSpeed = 1, camZoomSpeed = 1, + camInvertX = false, + camInvertY = false, camCollisionOffset = 0.7, // percentage camCollisionSpeedMult = 4, camListenerTarget = "domElement", @@ -24,6 +26,14 @@ export const useFollowCam = function ({ const { scene, camera, gl } = useThree(); // const { rapier, world } = useRapier(); + const camInvertXRef = useRef(camInvertX ? -1 : 1); + const camInvertYRef = useRef(camInvertY ? -1 : 1); + + useEffect(() => { + camInvertXRef.current = camInvertX ? -1 : 1; + camInvertYRef.current = camInvertY ? -1 : 1; +}, [camInvertX, camInvertY]); + let isMouseDown = false; let previousTouch1: Touch = null; let previousTouch2: Touch = null; @@ -64,8 +74,8 @@ export const useFollowCam = function ({ // Mouse move event const onDocumentMouseMove = (e: MouseEvent) => { if (document.pointerLockElement || isMouseDown) { - pivot.rotation.y -= e.movementX * 0.002 * camMoveSpeed; - const vy = followCam.rotation.x + e.movementY * 0.002 * camMoveSpeed; + pivot.rotation.y -= e.movementX * 0.002 * camMoveSpeed * camInvertXRef.current; + const vy = followCam.rotation.x + (e.movementY * camInvertYRef.current) * 0.002 * camMoveSpeed; cameraDistance = followCam.position.length(); @@ -114,8 +124,8 @@ export const useFollowCam = function ({ const touch1MovementX = touch1.pageX - previousTouch1.pageX; const touch1MovementY = touch1.pageY - previousTouch1.pageY; - pivot.rotation.y -= touch1MovementX * 0.005 * camMoveSpeed; - const vy = followCam.rotation.x + touch1MovementY * 0.005 * camMoveSpeed; + pivot.rotation.y -= touch1MovementX * 0.005 * camMoveSpeed * camInvertXRef.current; + const vy = followCam.rotation.x + (touch1MovementY * camInvertYRef.current) * 0.005 * camMoveSpeed; cameraDistance = followCam.position.length(); @@ -155,8 +165,8 @@ export const useFollowCam = function ({ * Gamepad second joystick event */ const joystickCamMove = (movementX: number, movementY: number) => { - pivot.rotation.y -= movementX * 0.005 * camMoveSpeed * 5; - const vy = followCam.rotation.x + movementY * 0.005 * camMoveSpeed * 5; + pivot.rotation.y -= movementX * 0.005 * camMoveSpeed * 5 * camInvertXRef.current; + const vy = followCam.rotation.x + (movementY * camInvertYRef.current) * 0.005 * camMoveSpeed * 5; cameraDistance = followCam.position.length(); @@ -327,6 +337,8 @@ export type UseFollowCamProps = { camInitDir?: { x: number, y: number }; camMoveSpeed?: number; camZoomSpeed?: number; + camInvertX?: boolean, + camInvertY?: boolean, camCollisionOffset?: number; camCollisionSpeedMult?: number; camListenerTarget?: camListenerTargetType;