From 9aee2396d296616bfb4b8db6996e416ae975a6a5 Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Mon, 27 Jan 2025 22:41:44 +0100 Subject: [PATCH] Improve deadzone algorithm and use it for SDL_GameController, fix #111 --- src/sdl/controller/SdlController.cpp | 18 ++++++++++++++++-- src/test/test.cpp | 6 ++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/sdl/controller/SdlController.cpp b/src/sdl/controller/SdlController.cpp index 3fcb7f89..69e2a7e1 100644 --- a/src/sdl/controller/SdlController.cpp +++ b/src/sdl/controller/SdlController.cpp @@ -122,12 +122,26 @@ float SdlController::stateImpl(controller::Button button) const { otherState *= std::sqrt(1 - 0.5 * state * state); state = static_cast(tmp); } - if (model != Model::XBOX_WIRED && model != Model::XBOX) { + if (!gameController && model != Model::XBOX_WIRED && model != Model::XBOX) { return state; // no deadzone needed } - if (state * state + otherState * otherState < 0.1) { // inside deadzone circle? + const auto lengthSquared = state * state + otherState * otherState; + const float DEADZONE_RADIUS = 0.2; + if (lengthSquared < DEADZONE_RADIUS * DEADZONE_RADIUS) { // inside deadzone circle? return 0; } + + // smooth out transition out of deadzone to 2 * deadzone: + if (lengthSquared < DEADZONE_RADIUS * 2 * DEADZONE_RADIUS * 2) { + float directionVectorInDeadzone = state / std::sqrt(lengthSquared) * DEADZONE_RADIUS; + return (state - directionVectorInDeadzone) * 2; + } + + // not a perfect square, but most controllers are returning coordinates outside of a circle: + if (lengthSquared > 1) { + return state / std::sqrt(lengthSquared); + } + return state; } diff --git a/src/test/test.cpp b/src/test/test.cpp index 64936a63..14ee7554 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -513,8 +513,10 @@ void testKeys() { auto circleModelview = jngl::modelview().translate( { 530, static_cast(-40 + controllerNr * 110) }); jngl::drawEllipse(circleModelview, circleRadius, circleRadius); - jngl::setColor(255, 255, 255, 255); - jngl::drawCircle(circleModelview.translate(circleRadius * stick), 4); + const double length = boost::qvm::mag(stick); + jngl::drawCircle(circleModelview.translate(circleRadius * stick), 4, + length > 1 ? jngl::Rgba(1, 2 - length, 2 - length, 1) + : 0xffffffff_rgba); jngl::translate(0, 2 * circleRadius + 10); }