Gamepads, like keyboards, are not perfect. They are designed to be cheap, sturdy, and nice to hold: accuracy comes second.
Specifically, the analog thumbsticks are not very precise at reporting their absolute position (although they are good at measuring relative movements, so the returned values will change if you twitch the stick even a small amount). The main way you notice this lack of precision is that when you let go of the stick it never goes back exactly to zero, just to some kind of smallish value roughly nearish to zero.
Thumbsticks that don't return exactly to zero are a bad thing. This makes game characters twitch around or sidle across the screen when they should be sitting still, and it makes menu systems randomly change selection even when you didn't move the stick.
So why have you never noticed this problem? Because XNA takes care of it for you!
Most likely you are reading input by calling GamePad.GetState(PlayerIndex.One). Internally this is just a wrapper around a more powerful overload of GetState:
public static GamePadState GetState(PlayerIndex playerIndex) { return GetState(playerIndex, GamePadDeadZone.IndependentAxes); }
A GamePadDeadZone enum, huh? Try changing your GamePad.GetState calls to pass in GamePadDeadZone.None, which will disable our deadzone computations, and you'll see the raw input values that never quite reach zero. Not very useful, unless you don't like our deadzone implementation and want to do something different of your own.
The default mode, GamePadDeadZone.IndependentAxes, applies this response curve to both the X and Y components of the stick position:
In other words, if the position of either axis is close to zero, it clamps that axis to be exactly zero. There is no feedback from one axis to the other, so if you are holding the stick straight up we will return a large positive Y value but still clamp your nearly-zero X input.
In addition to IndependentAxes and None, we implemented a third mode: GamePadDeadZone.Circular. This examines the position of both axes together, and only clamps to zero if the combined stick position is close to the origin.
These plots show the effect of the two deadzone modes on the X component of the input position (IndependentAxes on the left, Circular on the right):
And here they are applied to the Y input:
Finally, here are both axes combined:
Notice how the IndependentAxes deadzone stays active all the way out to the ends of the vertical and horizontal axes, while the Circular mode is more subtle and only affects the center location.
You will generally want to use IndependentAxes mode for things where the X and Y stick positions control unrelated game values. For instance steering a car is independent of accelerating and braking, or moving up and down through a menu is independent of moving left and right. The Circular mode works better for things where the stick input is used to choose a location on a 2D plane, such as aiming a weapon or moving the character in a Mario64 style platformer.
Choosing the right deadzone mode can make a big difference to how responsive your game feels, so try them both to see which one is right for you.