So you have that Xbox360 controller laying around and want to connect it to your game?

On XNA this is an out of the box option but if you’re using C++ you have a bit more work to do first.

First of all, you will need the DirecX 9.0+ sdk.

The includes.

#define WIN32_LEAN_AND_MEAN // We don't want the extra stuff like MFC and such #include <windows> #include <XInput.h> // XInput API #pragma comment(lib, "XInput.lib") // Library. If your compiler doesn't support this type of lib include change to the corresponding one #define WIN32_LEAN_AND_MEAN // We don't want the extra stuff like MFC and such #include <windows> #include <XInput.h> // XInput API #pragma comment(lib, "XInput.lib") // Library. If your compiler doesn't support this type of lib include change to the corresponding one

Let’s define the buttons

typedef enum { GamePad_Button_DPAD_UP = 0 , GamePad_Button_DPAD_DOWN = 1 , GamePad_Button_DPAD_LEFT = 2 , GamePad_Button_DPAD_RIGHT = 3 , GamePad_Button_START = 4 , GamePad_Button_BACK = 5 , GamePad_Button_LEFT_THUMB = 6 , GamePad_Button_RIGHT_THUMB = 7 , GamePad_Button_LEFT_SHOULDER = 8 , GamePad_Button_RIGHT_SHOULDER = 9 , GamePad_Button_A = 10 , GamePad_Button_B = 11 , GamePad_Button_X = 12 , GamePad_Button_Y = 13 , GamePadButton_Max = 14 } GamePadButton ; typedef enum { GamePad_Button_DPAD_UP = 0, GamePad_Button_DPAD_DOWN = 1, GamePad_Button_DPAD_LEFT = 2, GamePad_Button_DPAD_RIGHT = 3, GamePad_Button_START = 4, GamePad_Button_BACK = 5, GamePad_Button_LEFT_THUMB = 6, GamePad_Button_RIGHT_THUMB = 7, GamePad_Button_LEFT_SHOULDER = 8, GamePad_Button_RIGHT_SHOULDER = 9, GamePad_Button_A = 10, GamePad_Button_B = 11, GamePad_Button_X = 12, GamePad_Button_Y = 13, GamePadButton_Max = 14 }GamePadButton;

After some digging I don’t think Microsoft exposes access to the Guide button, let me know if you find anything. Anyway it’s not something we need on Windows.

Now the GamePadIndexes

// GamePad Indexes typedef enum { GamePadIndex_One = 0 , GamePadIndex_Two = 1 , GamePadIndex_Three = 2 , GamePadIndex_Four = 3 , } GamePadIndex ; // GamePad Indexes typedef enum { GamePadIndex_One = 0, GamePadIndex_Two = 1, GamePadIndex_Three =2, GamePadIndex_Four = 3, }GamePadIndex;

The GamePadIndex is to define the player position. Like on the Xbox360, this way we can control up to 4 controllers.

We need something to store the GamePad state

// The GamePad State Stuct, were we store the buttons positions struct GamePadState { bool _buttons [ GamePadButton_Max ] ; Vector2 _left_thumbstick ; // <= I'm using a Vector2 (floats) class but you can replaced it with a float X and Y or whatever your Vector2 class is Vector2 _right_thumbstick ; float _left_trigger ; float _right_trigger ; // Just to clear all values to default void reset ( ) { for ( int i = 0 ; i < ( int ) GamePadButton_Max ; ++ i ) _buttons [ i ] = false ; _left_thumbstick. set ( 0.0f ) ; _right_thumbstick. set ( 0.0f ) ; _left_trigger = _right_trigger = 0.0f ; } } ; // The GamePad State Stuct, were we store the buttons positions struct GamePadState { bool _buttons[GamePadButton_Max]; Vector2 _left_thumbstick; // <= I'm using a Vector2 (floats) class but you can replaced it with a float X and Y or whatever your Vector2 class is Vector2 _right_thumbstick; float _left_trigger; float _right_trigger; // Just to clear all values to default void reset() { for (int i=0;i<(int)GamePadButton_Max;++i) _buttons[i] = false; _left_thumbstick.set(0.0f); _right_thumbstick.set(0.0f); _left_trigger = _right_trigger = 0.0f; } };

Now a small class

class GamePadXbox { public : GamePadXbox ( GamePadIndex player ) { _playerIndex = player ; State. reset ( ) ; } virtual ~GamePadXbox ( void ) { // We don't want the controller to be vibrating accidentally when we exit the app if ( is_connected ( ) ) vibrate ( 0.0f , 0.0f ) ; } bool is_connected ( ) ; void vibrate ( float leftmotor = 0.0f , float rightmotor = 0.0f ) ; void update ( ) ; public : GamePadState State ; private : XINPUT_STATE _controllerState ; GamePadIndex _playerIndex ; } ; class GamePadXbox { public: GamePadXbox(GamePadIndex player) { _playerIndex = player; State.reset(); } virtual ~GamePadXbox(void) { // We don't want the controller to be vibrating accidentally when we exit the app if(is_connected()) vibrate(0.0f,0.0f); } bool is_connected(); void vibrate(float leftmotor = 0.0f, float rightmotor = 0.0f); void update(); public: GamePadState State; private: XINPUT_STATE _controllerState; GamePadIndex _playerIndex; };

Now, onto the GamePadXbox::is_connected()

bool is_connected ( ) { // clean the state memset ( & _controllerState, 0 , sizeof ( XINPUT_STATE ) ) ; // Get the state DWORD Result = XInputGetState ( _controllerNum, & _controllerState ) ; if ( Result == ERROR_SUCCESS ) return true ; else return false ; } bool is_connected() { // clean the state memset(&_controllerState,0, sizeof(XINPUT_STATE)); // Get the state DWORD Result = XInputGetState(_controllerNum, &_controllerState); if(Result == ERROR_SUCCESS) return true; else return false; }

Documentation for the XInputGetState is here.

Onto the vibrate function. Now, the Vibration accepts values between 0 and 65535. But we don’t want to be typing that every time so the vibrate accepts from a range of 0.0f (0) to 1.0f (65535);

void vibrate ( float leftmotor = 0.0f , float rightmotor = 0.0f ) { // Create a new Vibraton XINPUT_VIBRATION Vibration ; memset ( & Vibration, 0 , sizeof ( XINPUT_VIBRATION ) ) ; int leftVib = ( int ) ( leftmotor * 65535.0f ) ; int rightVib = ( int ) ( rightmotor * 65535.0f ) ; // Set the Vibration Values Vibration. wLeftMotorSpeed = leftVib ; Vibration. wRightMotorSpeed = rightVib ; // Vibrate the controller XInputSetState ( ( int ) _controllerNum, & Vibration ) ; } void vibrate(float leftmotor = 0.0f, float rightmotor = 0.0f) { // Create a new Vibraton XINPUT_VIBRATION Vibration; memset(&Vibration, 0, sizeof(XINPUT_VIBRATION)); int leftVib = (int)(leftmotor*65535.0f); int rightVib = (int)(rightmotor*65535.0f); // Set the Vibration Values Vibration.wLeftMotorSpeed = leftVib; Vibration.wRightMotorSpeed = rightVib; // Vibrate the controller XInputSetState((int)_controllerNum, &Vibration); }

On the destructor I’ve placed the vibrate at 0.0f otherwise the controller may be left vibrating after your game exits until the user unplugs it.

Finally, the update() function. Now this one is more out of convenience, since you could get the state straight out of XINPUT_STATE but I think this is a more consistent way of doing it. You can decide how you want on yours.

void update ( ) { State. reset ( ) ; // The values of the Left and Right Triggers go from 0 to 255. We just convert them to 0.0f=>1.0f if ( _controllerState. Gamepad . bRightTrigger && _controllerState. Gamepad . bRightTrigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD ) { State._right_trigger = _controllerState. Gamepad . bRightTrigger / 255.0f ; } if ( _controllerState. Gamepad . bLeftTrigger && _controllerState. Gamepad . bLeftTrigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD ) { State._left_trigger = _controllerState. Gamepad . bLeftTrigger / 255.0f ; } // Get the Buttons if ( _controllerState. Gamepad . wButtons & XINPUT_GAMEPAD_A ) State._buttons [ GamePad_Button_A ] = true ; if ( _controllerState. Gamepad . wButtons & XINPUT_GAMEPAD_B ) State._buttons [ GamePad_Button_B ] = true ; if ( _controllerState. Gamepad . wButtons & XINPUT_GAMEPAD_X ) State._buttons [ GamePad_Button_X ] = true ; if ( _controllerState. Gamepad . wButtons & XINPUT_GAMEPAD_Y ) State._buttons [ GamePad_Button_Y ] = true ; if ( _controllerState. Gamepad . wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) State._buttons [ GamePad_Button_DPAD_DOWN ] = true ; // The Rest is missing, you can figure out the rest :) .... ( ThumbSticks code below ) } void update() { State.reset(); // The values of the Left and Right Triggers go from 0 to 255. We just convert them to 0.0f=>1.0f if(_controllerState.Gamepad.bRightTrigger && _controllerState.Gamepad.bRightTrigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD) { State._right_trigger = _controllerState.Gamepad.bRightTrigger/255.0f; } if(_controllerState.Gamepad.bLeftTrigger && _controllerState.Gamepad.bLeftTrigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD) { State._left_trigger = _controllerState.Gamepad.bLeftTrigger/255.0f; } // Get the Buttons if(_controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_A) State._buttons[GamePad_Button_A] = true; if(_controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_B) State._buttons[GamePad_Button_B] = true; if(_controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_X) State._buttons[GamePad_Button_X] = true; if(_controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_Y) State._buttons[GamePad_Button_Y] = true; if(_controllerState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) State._buttons[GamePad_Button_DPAD_DOWN] = true; // The Rest is missing, you can figure out the rest :) .... (ThumbSticks code below) }

For getting all buttons here are the official flags according to msdn

XINPUT_GAMEPAD_DPAD_UP 0x00000001 XINPUT_GAMEPAD_DPAD_DOWN 0x00000002 XINPUT_GAMEPAD_DPAD_LEFT 0x00000004 XINPUT_GAMEPAD_DPAD_RIGHT 0x00000008 XINPUT_GAMEPAD_START 0x00000010 XINPUT_GAMEPAD_BACK 0x00000020 XINPUT_GAMEPAD_LEFT_THUMB 0x00000040 XINPUT_GAMEPAD_RIGHT_THUMB 0x00000080 XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100 XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200 XINPUT_GAMEPAD_A 0x1000 XINPUT_GAMEPAD_B 0x2000 XINPUT_GAMEPAD_X 0x4000 XINPUT_GAMEPAD_Y 0x8000 XINPUT_GAMEPAD_DPAD_UP 0x00000001 XINPUT_GAMEPAD_DPAD_DOWN 0x00000002 XINPUT_GAMEPAD_DPAD_LEFT 0x00000004 XINPUT_GAMEPAD_DPAD_RIGHT 0x00000008 XINPUT_GAMEPAD_START 0x00000010 XINPUT_GAMEPAD_BACK 0x00000020 XINPUT_GAMEPAD_LEFT_THUMB 0x00000040 XINPUT_GAMEPAD_RIGHT_THUMB 0x00000080 XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100 XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200 XINPUT_GAMEPAD_A 0x1000 XINPUT_GAMEPAD_B 0x2000 XINPUT_GAMEPAD_X 0x4000 XINPUT_GAMEPAD_Y 0x8000

The ThumbSticks are a bit more tricky. They return 2 axis each but you have to make sure they are not in the deadzone. The deadzone pretty much are values !=0 but that are not relevant and can lead to errors.

// Check to make sure we are not moving during the dead zone // Let's check the Left DeadZone if ( ( _controllerState. Gamepad . sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && _controllerState. Gamepad . sThumbLX > - XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ) && ( _controllerState. Gamepad . sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && _controllerState. Gamepad . sThumbLY > - XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ) ) { _controllerState. Gamepad . sThumbLX = 0 ; _controllerState. Gamepad . sThumbLY = 0 ; } // Check left thumbStick float leftThumbY = _controllerState. Gamepad . sThumbLY ; if ( leftThumbY ) { State._left_thumbstick. Y = leftThumbY ; } float leftThumbX = _controllerState. Gamepad . sThumbLX ; if ( leftThumbX ) { State._left_thumbstick. X = leftThumbX ; } // For the rightThumbstick it's pretty much the same. // Check to make sure we are not moving during the dead zone // Let's check the Left DeadZone if( (_controllerState.Gamepad.sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && _controllerState.Gamepad.sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) && (_controllerState.Gamepad.sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && _controllerState.Gamepad.sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) ) { _controllerState.Gamepad.sThumbLX = 0; _controllerState.Gamepad.sThumbLY = 0; } // Check left thumbStick float leftThumbY = _controllerState.Gamepad.sThumbLY; if(leftThumbY) { State._left_thumbstick.Y = leftThumbY; } float leftThumbX = _controllerState.Gamepad.sThumbLX; if(leftThumbX) { State._left_thumbstick.X = leftThumbX; } // For the rightThumbstick it's pretty much the same.

So how would we use this then?

int main ( ) { GamePadXbox * pad = new GamePadXbox ( GamePadIndex_One ) ; while ( 1 ) { if ( pad - > is_connected ( ) ) { pad - > update ( ) ; if ( pad - > State._buttons [ GamePad_Button_BACK ] == true ) break ; } } delete pad ; } int main() { GamePadXbox* pad = new GamePadXbox(GamePadIndex_One); while(1) { if(pad->is_connected()) { pad->update(); if(pad->State._buttons[GamePad_Button_BACK]==true) break; } } delete pad; }

Anyway, most of this code is not elegant or “pretty” but it should work, the idea is for you to understand the concept, the rest is up to you.