Click here to Skip to main content
11,487,401 members (72,522 online)
Click here to Skip to main content

Xbox 360 Controller Input in C++ with XInput

, 13 Jun 2008 CPOL 105K 4.8K 26
Rate this:
Please Sign up or sign in to vote.
A small tutorial on how to use XInput (requires the DX SDK) to handle input from an Xbox 360 Controller for Windows.

Introduction

By the end of this tutorial, you should understand the basics of how to implement the Xbox 360 Controller for Windows in your C++ program, whether it be a game or some other random project that requires the use of the controller.

Class Definition (CXBOXController)

This is our class definition code for the Xbox Controller:

#ifndef _XBOX_CONTROLLER_H_
#define _XBOX_CONTROLLER_H_

// No MFC
#define WIN32_LEAN_AND_MEAN

// We need the Windows Header and the XInput Header
#include <span class="code-keyword"><windows.h></span>
#include <span class="code-keyword"><XInput.h></span>

// Now, the XInput Library
// NOTE: COMMENT THIS OUT IF YOU ARE NOT USING
// A COMPILER THAT SUPPORTS THIS METHOD OF LINKING LIBRARIES
#pragma comment(lib, "XInput.lib")

// XBOX Controller Class Definition
class CXBOXController
{
private:
    XINPUT_STATE _controllerState;
    int _controllerNum;
public:
    CXBOXController(int playerNumber);
    XINPUT_STATE GetState();
    bool IsConnected();
    void Vibrate(int leftVal = 0, int rightVal = 0);
};

#endif

Code Breakdown

This defines a simple C++ class that manages an Xbox 360 Controller.

_controllerState holds the state of the Xbox 360 Controller, _controllerNum holds a reference to which controller (0-3) is being stored by the class. GetState() updates the Controller's state and returns the state information to the caller so that checks can be made on the input (which will be done later when we flesh out the program). IsConnected() checks to ensure that the controller is connected, and will return ERROR_SUCCESS if successful. The Vibrate() function simply provides us with a quick and easy method for vibrating the controller.

Fleshing It Out

#include <span class="code-string">"CXBOXController.h"</span>

CXBOXController::CXBOXController(int playerNumber)
{
    // Set the Controller Number
    _controllerNum = playerNumber - 1;
}

XINPUT_STATE CXBOXController::GetState()
{
    // Zeroise the state
    ZeroMemory(&_controllerState, sizeof(XINPUT_STATE));

    // Get the state
    XInputGetState(_controllerNum, &_controllerState);

    return _controllerState;
}

bool CXBOXController::IsConnected()
{
    // Zeroise the state
    ZeroMemory(&_controllerState, sizeof(XINPUT_STATE));

    // Get the state
    DWORD Result = XInputGetState(_controllerNum, &_controllerState);

    if(Result == ERROR_SUCCESS)
    {
        return true;
    }
    else
    {
        return false;
    }
}

void CXBOXController::Vibrate(int leftVal, int rightVal)
{
    // Create a Vibraton State
    XINPUT_VIBRATION Vibration;

    // Zeroise the Vibration
    ZeroMemory(&Vibration, sizeof(XINPUT_VIBRATION));

    // Set the Vibration Values
    Vibration.wLeftMotorSpeed = leftVal;
    Vibration.wRightMotorSpeed = rightVal;

    // Vibrate the controller
    XInputSetState(_controllerNum, &Vibration);
}

Code Breakdown

This is where the CXBOXController class is fleshed out and given life.

First, the CXBOXController constructor assigns the controller number based on the player number (player 1 = 0, player 2 = 1, player 3 = 2, player 4 = 3).

Next, we flesh out the function that gets the state of the controller. First, we must zero-out the pointer to the game state, so that we can ensure no artifacts exist, by way of which the input is checked. We then make a call to XInputGetState, and pass the controller number and the address of the controller state variable to store the state of the controller into. This will ensure that _controllerState is always up-to-date. We then return the state of the controller.

After this, we implement IsConnected(), which returns true if the controller is connected and has no errors, or false if something is wrong. As in the GetState() function, we need to zero-out the memory and update the state, so that we can keep on top of the controller's state in case of a sudden disconnection. If the controller is connected and has no problems, XInputGetState() will return ERROR_SUCCESS, stating that everything is okay.

And finally, we implement a feature to allow for vibration. The Xbox 360 has two vibration motors in it; one on the left, and one on the right. We take this into account by allowing a value for the left motor and a value for the right motor. Each of these can range from 0 to 65535, indicating the strength of the motor's vibration, 65535 being the strongest. We first define an instance of the XINPUT_VIBRATION struct, which allows us to store the vibration speeds into one structure. Just as a precaution, we zero-out this memory, then set the vibration speeds, and finally set the vibration state with XInputSetState. Due to our use of 0 as the default values for leftVal and rightVal, we can call controller->Vibrate() alone to stop all vibration on the controller.

Test Application

This small bit will allow us to test the controller class:

#include <span class="code-string">"CXBOXController.h"</span>
#include <span class="code-keyword"><iostream></span>

CXBOXController* Player1;
int main(int argc, char* argv[])
{
    Player1 = new CXBOXController(1);

    std::cout << "Instructions:\n";
    std::cout << "[A] Vibrate Left Only\n";
    std::cout << "[B] Vibrate Right Only\n";
    std::cout << "[X] Vibrate Both\n";
    std::cout << "[Y] Vibrate Neither\n";
    std::cout << "[BACK] Exit\n";

    while(true)
    {
        if(Player1->IsConnected())
        {
            if(Player1->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_A)
            {
                Player1->Vibrate(65535, 0);
            }

            if(Player1->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_B)
            {
                Player1->Vibrate(0, 65535);
            }

            if(Player1->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_X)
            {
                Player1->Vibrate(65535, 65535);
            }

            if(Player1->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_Y)
            {
                Player1->Vibrate();
            }

            if(Player1->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_BACK)
            {
                break;
            }
        }
        else
        {
            std::cout << "\n\tERROR! PLAYER 1 - XBOX 360 Controller Not Found!\n";
            std::cout << "Press Any Key To Exit.";
            std::cin.get();
            break;
        }
    }

    delete(Player1);

    return( 0 );
}

I'm not going to go into details over most of the contents of this last chunk of code, because it should be quite obvious what it does.

I will, however, go over the following points of interest:

CXBOXController* Player1;
...
Player1 = new CXBOXController(1);

I chose to define it this way because I like pointers when it comes to things such as controllers. It allows me to easily pass them if I want to send them in a form other than as global variables. The 1 in the constructor indicates that it will be player 1's controller (or controller #0, according to XInput).

if(Player1->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_A)

This is the code that checks for the gamepad state. To check for button inputs, you must use a logical AND to check if the button was pressed.

Hex Values for Controller State Buttons Checking

(Note: Obtained from the MSDN website)

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

You can also use GetState() to get the values of the Thumbstick Positions and right and left triggers through bLeftTrigger, bRightTrigger, sThumbLX, sThumbLY, sThumbRX, and sThumbRY. More information can be found on MSDN.

XINPUT_GAMEPAD Struct

(Note: Obtained from the MSDN website)

typedef struct _XINPUT_GAMEPAD {
    WORD wButtons;
    BYTE bLeftTrigger;
    BYTE bRightTrigger;
    SHORT sThumbLX;
    SHORT sThumbLY;
    SHORT sThumbRX;
    SHORT sThumbRY;
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;

History

  • June 13, 2008: Tutorial written.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Minalien
Student
United States United States
No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 Pin
Member 109205792-May-15 13:54
memberMember 109205792-May-15 13:54 
QuestionXbox in C Pin
matt00013-Mar-13 20:44
membermatt00013-Mar-13 20:44 
QuestionXINPUT1_4.dll is missing Pin
jllowrey16-Sep-12 18:07
memberjllowrey16-Sep-12 18:07 
AnswerRe: XINPUT1_4.dll is missing Pin
b1tzz24-Jan-13 15:46
memberb1tzz24-Jan-13 15:46 
Questionbuffered input Pin
redcometdiekun1-Dec-11 10:32
memberredcometdiekun1-Dec-11 10:32 
Questionlogitech momo Pin
ivanovici mihai2-Nov-11 9:53
memberivanovici mihai2-Nov-11 9:53 
QuestionAnalog sticks? Pin
LollerSauce20-Dec-10 14:13
memberLollerSauce20-Dec-10 14:13 
QuestionRelease? Pin
Tyler DeVos8-Mar-10 13:41
memberTyler DeVos8-Mar-10 13:41 
AnswerRe: Release? Pin
Michel Gerritse29-Mar-10 2:14
memberMichel Gerritse29-Mar-10 2:14 
QuestionHow to catch the xbox-button Pin
Kazoeja21-Feb-10 14:30
memberKazoeja21-Feb-10 14:30 
AnswerRe: How to catch the xbox-button Pin
Michel Gerritse29-Mar-10 2:20
memberMichel Gerritse29-Mar-10 2:20 
AnswerRe: How to catch the xbox-button Pin
v00d00m4n5-Nov-14 23:28
memberv00d00m4n5-Nov-14 23:28 
Generallinker error in dev-C++ Pin
azispn9911-Aug-09 15:02
memberazispn9911-Aug-09 15:02 
GeneralRe: linker error in dev-C++ Pin
Minalien23-Jan-10 15:50
memberMinalien23-Jan-10 15:50 
GeneralMultiple controllers Pin
GieltjE14-Jun-09 2:35
memberGieltjE14-Jun-09 2:35 
GeneralRe: Multiple controllers Pin
Minalien23-Jan-10 15:46
memberMinalien23-Jan-10 15:46 
GeneralPlease detail in about how to compile Pin
jdgosalia1-Jun-09 15:48
memberjdgosalia1-Jun-09 15:48 
GeneralRe: Please detail in about how to compile Pin
Minalien23-Jan-10 15:43
memberMinalien23-Jan-10 15:43 
GeneralXBOX controller not found Pin
Austrian_Programmer28-Jun-08 6:20
memberAustrian_Programmer28-Jun-08 6:20 
GeneralRe: XBOX controller not found Pin
Minalien3-Jul-08 0:13
memberMinalien3-Jul-08 0:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150520.1 | Last Updated 14 Jun 2008
Article Copyright 2008 by Minalien
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid