Last active
December 2, 2017 13:17
-
-
Save Bradshaw/24553c2a82543f2016dc52e88d2202a8 to your computer and use it in GitHub Desktop.
How to have nice dead-zoning for joystick input
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Nice deadzoning | |
// raw contains the x and y of the joystick | |
// dead is the threshold (0.2 for good results) | |
function deadZoner(raw, dead) { | |
// d2 is the square of the magnitude of raw | |
var d2 = raw.x*raw.x + raw.y*raw.y; | |
// If d2 is lower than the deadzone squared, then we're inside the deadzone | |
// (Also check against zero, in case we're given a zero deadzone) | |
if (d2<dead*dead || d2<0){ | |
// We're inside the deadzone, return zero | |
return {x: 0, y:0}; | |
} else { | |
// We're out of the deadzone, let's smooth out that janky threshold | |
// d2 is squarerooted to get actual distance from zero | |
var d = Math.sqrt(d2); | |
// Normalise raw input | |
var nx = raw.x/d; | |
var ny = raw.y/d; | |
// Rescaled so (dead->1) becomes (0->1) | |
d = (d-dead)/(1-dead); | |
// and clamped down so we get 0 <= d <= 1 | |
d = Math.min(d,1); | |
// Apply a curve for a smoother feel (as suggested by (Gibgezr)[https://github.com/Gibgezr] | |
// Uncomment the following line and see if your game feels better | |
// d = d*d | |
// Scale normalised input and return | |
return { | |
x: nx*d, | |
y: ny*d | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Nice deadzoning | |
-- raw contains the x and y of the joystick | |
-- dead is the threshold (0.2 for good results) | |
function deadZoner(raw, dead) | |
-- d2 is the square of the magnitude of raw | |
local d2 = raw.x*raw.x + raw.y*raw.y | |
-- If d2 is lower than the deadzone squared, then we're inside the deadzone | |
-- (Also check against zero, in case we're given a zero deadzone) | |
if d2<dead*dead or d2<0 then | |
-- We're inside the deadzone, return zero | |
return {x = 0, y = 0} | |
else | |
-- We're out of the deadzone, let's smooth out that janky threshold | |
-- d2 is squarerooted to get actual distance from zero | |
local d = math.sqrt(d2) | |
-- Normalise raw input | |
local nx = raw.x/d | |
local ny = raw.y/d | |
-- Rescaled so (dead->1) becomes (0->1) | |
d = (d-dead)/(1-dead) | |
-- and clamped down so we get 0 <= d <= 1 | |
d = math.min(d,1) | |
-- Apply a curve for a smoother feel (as suggested by (Gibgezr)[https://github.com/Gibgezr] | |
-- Uncomment the following line and see if your game feels better | |
-- d = d*d | |
-- Scale normalised input and return | |
return { | |
x = nx*d, | |
y = ny*d | |
} | |
end | |
end |
Thanks (Gibgezr)[https://github.com/Gibgezr] for the suggestion!
It's not entirely part of the problem that deadzoning tries to fix, but it's useful and does tend to make thing feel better
I added it commented, and users are encouraged to uncomment the line to see if their controls feels better
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Since this is aimed at beginning game programmers, I’ll mention this: this is great if all you need is a linear response, but for things like player and camera movement/rotation, a pronounced response curve is normally used, so we’d do something like squaring the deadzoned x,y pair before using it. Offhand I can’t think of anytime I’d require a linear response, even adjusting UI sliders is easier with a curved response, so if folks try dropping this into their projects and find it feels clunky, try squaring those values AFTER deadzoning.