From ed18290f28fd0c6689d5b055f21ef581f480bbc5 Mon Sep 17 00:00:00 2001 From: steotto <203615411+steotto@users.noreply.github.com> Date: Wed, 18 Feb 2026 05:35:54 +0100 Subject: [PATCH] [Controller] improve character joystick movement (#8449) --- Source/controls/controller_motion.cpp | 47 ++++++++++++++++++++++----- Source/controls/controller_motion.h | 3 ++ Source/controls/plrctrls.cpp | 7 ++-- 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/Source/controls/controller_motion.cpp b/Source/controls/controller_motion.cpp index 692c25057..51039198c 100644 --- a/Source/controls/controller_motion.cpp +++ b/Source/controls/controller_motion.cpp @@ -207,17 +207,48 @@ void ProcessControllerMotion(const SDL_Event &event) } } -AxisDirection GetLeftStickOrDpadDirection(bool usePadmapper) +AxisDirection GetAnalogStickDirection(float stickX, float stickY) { - const float stickX = leftStickX; - const float stickY = leftStickY; - + // avoid sqrt() by comparing squared magnitudes + const float magnitudeSquared = stickX * stickX + stickY * stickY; + const float thresholdSquared = StickDirectionThreshold * StickDirectionThreshold; + if (magnitudeSquared < thresholdSquared) + return { AxisDirectionX_NONE, AxisDirectionY_NONE }; + + const float absX = std::fabs(stickX); + const float absY = std::fabs(stickY); AxisDirection result { AxisDirectionX_NONE, AxisDirectionY_NONE }; - bool isUpPressed = stickY >= 0.5; - bool isDownPressed = stickY <= -0.5; - bool isLeftPressed = stickX <= -0.5; - bool isRightPressed = stickX >= 0.5; + // 8-way sectoring with 22.5° cutoffs + constexpr float DiagonalCutoff = 0.41421356F; // tan(22.5°) + if (absX == 0.0F) { + result.y = stickY > 0 ? AxisDirectionY_UP : AxisDirectionY_DOWN; + return result; + } + + const float ratio = absY / absX; + if (ratio <= DiagonalCutoff) { + result.x = stickX > 0 ? AxisDirectionX_RIGHT : AxisDirectionX_LEFT; + return result; + } + if (ratio >= 1.0F / DiagonalCutoff) { + result.y = stickY > 0 ? AxisDirectionY_UP : AxisDirectionY_DOWN; + return result; + } + + result.x = stickX > 0 ? AxisDirectionX_RIGHT : AxisDirectionX_LEFT; + result.y = stickY > 0 ? AxisDirectionY_UP : AxisDirectionY_DOWN; + return result; +} + +AxisDirection GetLeftStickOrDpadDirection(bool usePadmapper) +{ + AxisDirection result = GetAnalogStickDirection(leftStickX, leftStickY); + + bool isUpPressed = false; + bool isDownPressed = false; + bool isLeftPressed = false; + bool isRightPressed = false; if (usePadmapper) { isUpPressed |= PadmapperIsActionActive("MoveUp"); diff --git a/Source/controls/controller_motion.h b/Source/controls/controller_motion.h index 317f22795..fe507c09a 100644 --- a/Source/controls/controller_motion.h +++ b/Source/controls/controller_motion.h @@ -25,6 +25,9 @@ extern float leftStickX, leftStickY, rightStickX, rightStickY; // Whether stick positions have been updated and need rescaling. extern bool leftStickNeedsScaling, rightStickNeedsScaling; +// Minimum scaled stick magnitude to register a direction. +constexpr float StickDirectionThreshold = 0.4F; + // Updates motion state for mouse and joystick sticks. void ProcessControllerMotion(const SDL_Event &event); diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 7a54aba31..c4ec5092f 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -1594,8 +1594,11 @@ struct RightStickAccumulator { bool IsStickMovementSignificant() { - return leftStickX >= 0.5 || leftStickX <= -0.5 - || leftStickY >= 0.5 || leftStickY <= -0.5 + // avoid sqrt() by comparing squared magnitudes + const float leftStickMagnitudeSquared = leftStickX * leftStickX + leftStickY * leftStickY; + const float thresholdSquared = StickDirectionThreshold * StickDirectionThreshold; + + return leftStickMagnitudeSquared >= thresholdSquared || rightStickX != 0 || rightStickY != 0; }