|
| 1 | +--- |
| 2 | +title: Detecting input from a GamePad |
| 3 | +description: The code in this topic describes how to detect input on a GamePad. |
| 4 | +requireMSLicense: true |
| 5 | +--- |
| 6 | + |
| 7 | +## Overview |
| 8 | + |
| 9 | +By using [GamePad.GetState](xref:Microsoft.Xna.Framework.Input.GamePad#Microsoft_Xna_Framework_Input_GamePad_GetState_System_Int32_) a game can determine which buttons are being held down. A game often needs to detect when a user has pressed or released a button. For example, there is the case of an action title that requires users to press and release keys in rapid succession. The example uses a cached [GamePadState](xref:Microsoft.Xna.Framework.Input.GamePadState) object to determine if buttons were pressed or released in a given frame. |
| 10 | + |
| 11 | +Unlike Keyboards however, multiple GamePads can be connected to a computer or console at the same time, so the [GamePad.GetState](xref:Microsoft.Xna.Framework.Input.GamePad#Microsoft_Xna_Framework_Input_GamePad_GetState_System_Int32_) call requires an Index parameter for which controller is being polled. You also need to query the system the game is currently on for its [GamePad.MaximumGamePadCount](xref:Microsoft.Xna.Framework.Input.GamePad#Microsoft_Xna_Framework_Input_GamePad_MaximumGamePadCount) to determine how many controllers are supported and how many need to be polled for each frame. Also unlike GamePads, GamePads can be disconnected (especially if the battery dies) at any time and most consoles require you to validate this to avoid player issues. |
| 12 | + |
| 13 | +> [!NOTE] |
| 14 | +> It is also worth noting, that when maintaining the state of connected gamepads, most console vendors **REQUIRE** your game to mange GamePad disconnection states (because it was unplugged, lost power, etc), ensuring the user experience is managed when the user CANNOT play. |
| 15 | +
|
| 16 | +Depending on game design, there may be times when checking for a button press needs to occur more frequently, and other times it does not. It is possible in the case of very fast button presses that more than one key press could occur within one frame. In such a case, the last button press is returned. Writing code that checks as often as possible for button presses is the best way to handle this case. |
| 17 | + |
| 18 | +## Types of GamePad input |
| 19 | + |
| 20 | +Most GamePads include a variety of different input options, including (but not limited to) |
| 21 | + |
| 22 | +- Thumbsticks - providing ranged motion in two axis. |
| 23 | +- Buttons (including buttons on the Thumbsticks) - Digital on/off buttons (similar to keyboard keys) |
| 24 | +- Triggers - providing ranged motion in a singular axis. |
| 25 | +- Touchpads - in some advanced controllers (such as the PlayStation Dual Shock controller) include a small touchpad. |
| 26 | + |
| 27 | +Additionally, most controllers also support haptic feedback (vibration) in the controller, which is different depending on the controller being used and for which system. |
| 28 | + |
| 29 | +> [!NOTE] |
| 30 | +> Joysticks also work the same as GamePads, but use their own [Joystick](xref:Microsoft.Xna.Framework.Input.Joystick) and [JoystickState](xref:Microsoft.Xna.Framework.Input.JoystickState) classes. Operationally however, they work the same as GamePads. |
| 31 | +
|
| 32 | +## Detecting input changes on a GamePad |
| 33 | + |
| 34 | +1. Declare a [GamePadState](xref:Microsoft.Xna.Framework.Input.GamePadState) object to hold the last known GamePad state (in this example, the **oldState** object). |
| 35 | + |
| 36 | +2. Assign this object a value in your constructor. |
| 37 | + |
| 38 | +3. Call [GamePad.GetState](xref:Microsoft.Xna.Framework.Input.GamePad#Microsoft_Xna_Framework_Input_GamePad_GetState_System_Int32_) to retrieve the current GamePad state (in this example, the **newState** object). |
| 39 | + |
| 40 | +4. Compare the values in your **newState** object to the values in the **oldState** object. |
| 41 | + |
| 42 | + Buttons pressed in the **newState** object that were not pressed in the **oldState** object were pressed during this frame. Conversely, buttons pressed in the **oldState** object that are not pressed in the **newState** object were released during this frame. |
| 43 | + |
| 44 | + > For Thumbsticks and Triggers, it is not necessary to compare to the previous value unless you also need to calculate the difference, e.g. Was the variable controller moved fast or slow. Reading just the current value is usually enough. |
| 45 | +
|
| 46 | +5. Update **oldState** object to the **newState** object before leaving **Update**. |
| 47 | + |
| 48 | +```csharp |
| 49 | +using Microsoft.Xna.Framework; |
| 50 | +using Microsoft.Xna.Framework.Input; |
| 51 | + |
| 52 | +namespace GamePadInput |
| 53 | +{ |
| 54 | + public class Game1 : Microsoft.Xna.Framework.Game |
| 55 | + { |
| 56 | + GraphicsDeviceManager graphics; |
| 57 | + GamePadState oldState; |
| 58 | + |
| 59 | + public Game1() |
| 60 | + { |
| 61 | + graphics = new GraphicsDeviceManager(this); |
| 62 | + } |
| 63 | + |
| 64 | + protected override void Initialize() |
| 65 | + { |
| 66 | + base.Initialize(); |
| 67 | + oldState = GamePad.GetState(PlayerIndex.One); |
| 68 | + } |
| 69 | + |
| 70 | + protected override void Update(GameTime gameTime) |
| 71 | + { |
| 72 | + // Allows the game to exit |
| 73 | + if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) |
| 74 | + { |
| 75 | + this.Exit(); |
| 76 | + } |
| 77 | + |
| 78 | + UpdateInput(); |
| 79 | + |
| 80 | + base.Update(gameTime); |
| 81 | + } |
| 82 | + |
| 83 | + private void UpdateInput() |
| 84 | + { |
| 85 | + GamePadState newState = GamePad.GetState(PlayerIndex.One); |
| 86 | + |
| 87 | + // Is the A Button down? |
| 88 | + if (newState.IsButtonDown(Buttons.A)) |
| 89 | + { |
| 90 | + if (!oldState.IsButtonDown(Buttons.A)) |
| 91 | + { |
| 92 | + // If not down last update, the button has just been pressed. |
| 93 | + } |
| 94 | + } |
| 95 | + else if (oldState.IsButtonDown(Buttons.A)) |
| 96 | + { |
| 97 | + // Button was down last update, but not down now, so it has just been released. |
| 98 | + } |
| 99 | + |
| 100 | + // Which direction is the right thumbstick being moved? |
| 101 | + Vector2 direction = newState.ThumbSticks.Right; |
| 102 | + |
| 103 | + // How much is the left trigger being squeezed? |
| 104 | + float leftTriggerAmount = newState.Triggers.Left; |
| 105 | + |
| 106 | + // Update saved state. |
| 107 | + oldState = newState; |
| 108 | + } |
| 109 | + |
| 110 | + protected override void Draw(GameTime gameTime) |
| 111 | + { |
| 112 | + base.Draw(gameTime); |
| 113 | + } |
| 114 | + } |
| 115 | +} |
| 116 | +``` |
| 117 | + |
| 118 | +The above sample demonstrates sampling just the first connected controller, to support multiple controllers, you will need to sample from all connected controllers (as well as managing their connected state in case one is disconnected) and use an array of [GamePadState](xref:Microsoft.Xna.Framework.Input.GamePadState) to maintain the cache of all controllers. |
| 119 | + |
| 120 | +> [!NOTE] |
| 121 | +> P.S. Most mobiles these days can support Bluetooth GamePads, so make sure you also support them if you intend to ship your game on mobile!! |
| 122 | +
|
| 123 | +## See Also |
| 124 | + |
| 125 | +- [Detecting a Key Press](HowTo_DetectKeyPress.md) |
| 126 | +- [Working with Touch Input](HowTo_UseMultiTouchInput.md) |
| 127 | + |
| 128 | +### Reference |
| 129 | + |
| 130 | +- [Microsoft.Xna.Framework.Input](xref:Microsoft.Xna.Framework.Input) |
| 131 | +- [GamePadState](xref:Microsoft.Xna.Framework.Input.GamePadState) |
| 132 | +- [JoystickState](xref:Microsoft.Xna.Framework.Input.JoystickState) |
0 commit comments