pub struct Deadzone { /* private fields */ }Expand description
A radial dead region around stick centre, with the scaled response the literature settles on.
Three games on the PSoXide demo disc had grown one of these and they did not
agree. hl-psx tests x*x + y*y against a squared radius. VoXide gates each
axis separately, which makes its dead region a square: a stick pushed gently
along a diagonal clears the threshold on one axis and not the other, so the
input snaps to a cardinal instead of going where it was pushed. Sutphin’s
write-up calls that the axial dead zone and its snapping is the classic
complaint about it.
A stick’s centre drift is radial, so the region that ignores it is a circle,
and Deadzone::scaled is the scaled-radial form: remapped so the first
real reading starts from zero rather than jumping to the boundary magnitude.
That is the recommended default. Deadzone::gate is the plain radial one,
kept because the games being replaced were tuned against it.
This is for two-axis input. A single-axis control is a different question
and a scalar threshold is right for it: NitroXide steers on the left stick’s
X alone, and folding Y into the test there would let noise on an axis it
does not read enable steering. See Deadzone::is_outside_axis.
Implementations§
Source§impl Deadzone
impl Deadzone
Sourcepub const fn new(radius: i16) -> Self
pub const fn new(radius: i16) -> Self
A dead region of radius counts around centre. Typical radii are 12 to
30 of the 127 counts a healthy stick reaches. A negative radius is no
dead region (zero): the squared test would otherwise treat it as its
absolute value while scaled divided by a zero length.
Sourcepub const fn with_outer(self, outer: i16) -> Self
pub const fn with_outer(self, outer: i16) -> Self
Treat any deflection at or beyond outer as full scale.
A worn stick often cannot reach its corners, so without this the player simply never gets full input. Sutphin recommends exposing it as a setting for anything where magnitude matters.
Sourcepub const fn is_outside(self, x: i16, y: i16) -> bool
pub const fn is_outside(self, x: i16, y: i16) -> bool
Is this reading real input rather than centre drift?
Strictly outside, matching the boundary behaviour of the games this replaces.
Sourcepub const fn gate(self, x: i16, y: i16) -> Option<(i16, i16)>
pub const fn gate(self, x: i16, y: i16) -> Option<(i16, i16)>
The reading unchanged if it is real input, or None inside the dead
region. The plain radial form: direction is preserved, but magnitude
jumps from zero to the boundary the moment it is crossed.
Sourcepub fn scaled(self, x: i16, y: i16) -> Option<(i16, i16)>
pub fn scaled(self, x: i16, y: i16) -> Option<(i16, i16)>
Scaled radial: None inside the dead region, otherwise the reading with
its magnitude remapped from the dead edge onto full scale, keeping
direction.
The result is clamped to STICK_FULL per axis. Without that a full
diagonal, which is 179 counts long rather than 127, remaps to 138 on
each axis and hands the game 9% more than it believes the stick can
produce.
Sourcepub const fn is_outside_axis(self, v: i16) -> bool
pub const fn is_outside_axis(self, v: i16) -> bool
The one-axis form, for a control that reads a single axis.
Sourcepub const fn scaled_axis(self, v: i16) -> Option<i16>
pub const fn scaled_axis(self, v: i16) -> Option<i16>
The one-axis form of Deadzone::scaled.
Trait Implementations§
impl Copy for Deadzone
impl Eq for Deadzone
impl StructuralPartialEq for Deadzone
Auto Trait Implementations§
impl Freeze for Deadzone
impl RefUnwindSafe for Deadzone
impl Send for Deadzone
impl Sync for Deadzone
impl Unpin for Deadzone
impl UnsafeUnpin for Deadzone
impl UnwindSafe for Deadzone
Blanket Implementations§
§impl<T> Any for Twhere
T: 'static + ?Sized,
impl<T> Any for Twhere
T: 'static + ?Sized,
§impl<T> Borrow<T> for Twhere
T: ?Sized,
impl<T> Borrow<T> for Twhere
T: ?Sized,
§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§unsafe fn clone_to_uninit(&self, dest: *mut u8)
unsafe fn clone_to_uninit(&self, dest: *mut u8)
clone_to_uninit)