Date: February 1, 2006

By: Ken McGrail

Topic: Using XInput for XBOX 360 Controller support.



Programming in C++ to add support for the XBOX 360 in your games isn’t as hard as you might thing. After reading this tutorial you will hopefully understand, and be able to implement full XBOX 360 controller functionality into your games and applications.



Things you need:

XBOX 360 Controller (Wired)

Microsoft DirectX SDK (October or newer)

http://www.microsoft.com/downloads/d...displaylang=en



I am writing this tutorial using C++ and Microsoft Visual Studio 2003.



I will assume you have some working application you would like to add 360 controller support to, otherwise you wouldn’t be here. I am also assuming you have a new version of the DirectX SDK downloaded and installed, I have provided the link to the December version above.



The first thing you need to do to add the support to your application is to include the files that contain all the functionality and information for the functions we will be using. The files we need are “XInput.h” and “Xinput.lib”.

Code:
#include <XInput.h>                       // Defines XBOX controller API

#pragma comment(lib, “XInput.lib”)        // Library containing necessary 360
                                          // functions
These lines add the functionality to the application, that’s all there is to getting ready to start coding your input reader. I chose to write a separate function for mine so I can call it whenever I need to, but you could check the controller for input any time you like.



Code:
void CheckControllerStatus()

{

            DWORD dwResult;         // Used to store if a controller is connected

            XINPUT_STATE state;     // Data type that stores all the current states
                        // of a controller.

 

      ZeroMemory( &state, sizeof(XINPUT_STATE) ); // Zeros out the states of
                                                  // the controller.

 

      // Get all the current states of controller 1

      dwResult = XInputGetState( 0, &state );

 

      if( dwResult == ERROR_SUCCESS )

      {

            // Controller is connected.

            // -----------INSERT BUTTON CHECKS HERE----------

}

else

{

      // Controller is disconnected.

}

}
Let’s just walk through the code above real quick, the comments pretty much say everything that needs to be said so if you understand the above code section, please just skip this paragraph. Ok we started off creating a DWORD to store if our controller is connected or not. We also created an XINPUT_STATE variable, this is the variable that will be automatically filled in for us when we poll the controller to see which buttons are pressed. Next we zero out the memory, this is done to insure that there is no junk in the variable we just defined, that way we know we will have accurate key presses when we check them. XInputGetState(0 &state); is what is actually polling the controller, this function checks which buttons or joysticks are being used on the controller and fills in the XINPUT_STATE object we made previously. The function also returns a DWORD telling if an error has occurred when polling the device. Since the DWORD tells us about errors, we can check if it is equal to ERROR_SUCCESS, which means it has found a controller and there is no problem, if it is not an ERROR_SUCCESS, then we know there was no connection to the controller.



The XINPUT_STATE struct is defined as follows:



Code:
typedef struct _XINPUT_STATE 

{

    DWORD dwPacketNumber;

    XINPUT_GAMEPAD Gamepad;

} XINPUT_STATE, *PXINPUT_STATE;

 

            And an XINPUT_GAMEPAD is:

           

typedef struct _XINPUT_GAMEPAD 

{

    WORD wButtons;

    BYTE bLeftTrigger;

    BYTE bRightTrigger;

    SHORT sThumbLX;

    SHORT sThumbLY;

    SHORT sThumbRX;

    SHORT sThumbRY;

} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
This next section would all be written instead of the place holder I put in the code.

Code:
//-----------INSERT BUTTON CHECKS HERE----------
Checking Button Presses

Checking which buttons are pressed is as simple as comparing the wButtons variable to some simple typdefs that are already defined by Microsoft for us. For example if I wanted to check to see if the A button was pressed, and then if it was, add 5 to my speed.



Code:
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_A)

{

        fSpeed += 4;

}
Using a simple & operator we can check the predefined bit for the button press. The table of the possible buttons is below.



Code:
#define XINPUT_GAMEPAD_DPAD_UP          0x00000001

#define XINPUT_GAMEPAD_DPAD_DOWN        0x00000002

#define XINPUT_GAMEPAD_DPAD_LEFT        0x00000004

#define XINPUT_GAMEPAD_DPAD_RIGHT       0x00000008

#define XINPUT_GAMEPAD_START            0x00000010

#define XINPUT_GAMEPAD_BACK             0x00000020

#define XINPUT_GAMEPAD_LEFT_THUMB       0x00000040

#define XINPUT_GAMEPAD_RIGHT_THUMB      0x00000080

#define XINPUT_GAMEPAD_LEFT_SHOULDER    0x0100

#define XINPUT_GAMEPAD_RIGHT_SHOULDER   0x0200

#define XINPUT_GAMEPAD_A                0x1000

#define XINPUT_GAMEPAD_B                0x2000

#define XINPUT_GAMEPAD_X                0x4000

#define XINPUT_GAMEPAD_Y                0x8000
Checking Trigger Presses

The triggers on the XBOX 360 controller are very sensitive and can be used as single value buttons, or as an analog button that can be read as pressed, not pressed, or anywhere in between. The value in the trigger variables is a BYTE between 0-255, checking this value is as easy as looking it up in the state struct we created.





Code:
   if(state.Gamepad.bRightTrigger &&

state.Gamepad.bRightTrigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD)

      {

            // Do whatever you want to happen when a trigger is used here

            // the value stored in state.Gamepad.bRightTrigger is the amount

            // that the trigger is being pressed. Between 0-255.

      }
One thing to note is the XINPUT_GAMEPAD_TRIGGER_THRESHOLD, this value is used to cover the dead zone that the controller has in the button, the button is not 100% accurate so you need to account for that small amount of error the trigger might have.



Checking Thumbstick Movement and Presses

Checking the thumbsticks is done with a combination of the button check, and the trigger style check. If you want to know if the thumbstick is being clicked down then you can just check the wButtons variable against XINPUT_GAMEPAD_LEFT_THUMB or XINPUT_GAMEPA-D_RIGHT_THUMB, depending on which thumbstick you wish to test against. The direction and amount of the Thumbstick movement is a little bit different than the triggers but is along the same lines. The main difference is the Thumbstick has two directions you need to check, the X and the Y. In my example I store the values into a temporary variable first to help clarify that I am using that value and scaling it down. The values that the thumstick will return is a number between -32768 and 32767, depending on how far it is pressed.


Code:
      // Check left thumbStick

      float leftThumbY = state.Gamepad.sThumbLY;

      if(leftThumbY)

      {

            Position.Y += (leftThumbY / 500000.0f);

      }          

     

float leftThumbX = state.Gamepad.sThumbLX;

      if(leftThumbX)

      {

            Position.X += (leftThumbX / 500000.0f);

      }
You can see here that I have to check both the X and Y direction, and handle them both separately. The number state.Gamepad.sThumbLY; returns is the amount that the left Thumbstick is pressed in the Y direction.



Vibrations

Vibration of the controller can be set at any time, and turned off at any time as well. This is done by setting how much the controller needs to vibrate, and then changing the state of the controller to that vibration state.



Code:
      XINPUT_VIBRATION vibration;

      ZeroMemory( &vibration, sizeof(XINPUT_VIBRATION) );

      vibration.wLeftMotorSpeed = 0;      // use any value between 0-65535

      vibration.wRightMotorSpeed = 65535; // use any value between 0-65535

      XInputSetState( 0, &vibration );
The first thing that we do is create the vibration state itself, in this case I just named it vibration. Next we clear out the memory the same way that we did before to make sure there is no left over junk sitting in our new state. Something to note is that the two motors in the XBOX 360 controller are different, the left most motor handles low frequency vibrations while the right most motor deals with higher frequency vibrations. Each of these values can be set separately to get the desired effect you are looking for by just changing vibration.wLeftMotorSpeed and vibration.wRightMotorSpeed. The values can be anywhere within the range of 0-65535. And the last step is to set the controllers state to the new vibrations state we created. The first time I did this I had both left and right motors maxed out, and the controller just continued to vibrate wildly until I closed my program. To fix this you can just create another state that has both motors set to 0.


Code:
      XINPUT_VIBRATION stopVibration;

      ZeroMemory( &vibration, sizeof(XINPUT_VIBRATION) );

      vibration.wLeftMotorSpeed = 0; // use any value between 0-65535

      vibration.wRightMotorSpeed = 0; // use any value between 0-65535

      XInputSetState( 0, & stopVibration);
Checking Thumbstick Deadzone

Most of the time you want to make sure that your thumsticks have some area that will not be read into your application, this is due to small error amounts in the accuracy of the Thumbstick. Working the deadzone into your application is fairly simple, Microsoft even supplies a variable predefined deadzone for us.



Code:
      // Controller is connected

      // Check to make sure we are not moving during the dead zone

      if( (state.Gamepad.sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&

            state.Gamepad.sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) &&

            (state.Gamepad.sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&

            state.Gamepad.sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) )

            {    

                  state.Gamepad.sThumbLX = 0;

                  state.Gamepad.sThumbLY = 0;

            }

 

      if( (state.Gamepad.sThumbRX < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&

            state.Gamepad.sThumbRX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) &&

            (state.Gamepad.sThumbRY < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&

            state.Gamepad.sThumbRY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) )

            {

                  state.Gamepad.sThumbRX = 0;

                  state.Gamepad.sThumbRY = 0;

            }
All this does is check to make sure the value read on the thumbstick is more than the amount we consider to be useless, and then if it is a useless value, we just set it to zero to make sure we don’t try to use it.



This was my first tutorial so hopefully you found it useful and easy to follow. I think by adding the support for the new XBOX 360 controller into your application you are able to not only immerse your players into the experience more, but even get those console gamers to play some games on the pc. All of the information in this tutorial is directly from me, but I learned myself from the MSDN article on XInput, so if you have questions, feel free to check that article out, or even email me Ken@tcsnh.com.


This is a great Programming TUT n this forum needs a xbox360 proramming part as some user mite know a think or 2 n it would help with homebrew n other stuff