MULTIMEDIA

Programming with DirectX : Game Input - XInput

9/19/2012 12:57:37 AM
XInput is an API that is now part of the DirectX and XNA SDKs and allows Windows and Xbox 360-based applications to detect input from Xbox 360 controllers. These controllers include any device available now or in the future that can be used on the Xbox 360. Such devices are game pads, guitars, big-button controllers, drums, and so forth. XInput also supports controller vibrations (force-feedback) and voice input and output using the Xbox 360 headset.

All Xbox 360 controllers are compatible with Windows XP and Vista and are USB devices. These devices can be used like traditional game controllers (such as in DirectInput), or they can be used using XInput, which is the recommended API for these controllers.

XInput is the replacement for DirectInput when it comes to game controllers. XInput has several benefits over DirectInput, including the following.

  • XInput is easier to use.

  • XInput is faster to set up and detect input from.

  • XInput can be used on both Windows PCs and Xbox 360 consoles.

  • The vibration functionality of Xbox controllers can only be set using XInput.

  • Future Xbox controllers that are released will work with the API.

No real setup code is necessary for getting XInput running in a gaming application. The only requirement is that the USB controller is plugged into the machine and a call to XInputGetState() is made. (The XInputGetState() function will be discussed in the next section.) You can, however, enable XInput’s reporting state by calling the function XInputEnable(). By default, XInput’s reporting state is set to true, which means that calls to XInputGetState() will return the state of the device. If the reporting state is set to false, only natural data is sent. In other words, XInput will ignore the state of the device, which can be useful, for example, when the window is minimized but the game is still technically running. The XInputEnable() function is as follows.

void XInputEnable(BOOL enable);

You can use DirectInput to detect input from Xbox controllers, but DirectInput will not be able to access the vibration functionality. It will treat the left and right triggers as a single button instead of separately, and you cannot access audio from the Xbox 360 headset using DirectInput.

Setting Up Xbox 360 Controllers

All of the devices have buttons and so on. You can think of, for example, the guitar controller as a game pad in the shape of a guitar without the left and right analog sticks or the left and right triggers. A game pad has four face buttons, two triggers, two bumper buttons (buttons in front of the triggers), two analog sticks, each with a digital button (accessed by pushing the stick inward), a guide button, a directional pad, and start and back buttons.

The XInput function XInputGetState() is used to get the state of an Xbox controller. The function takes as parameters the index of the player and the address of an XINPUT_STATE object that stores the state information. The player index can be between 0 and 3 for players one through four. The return value for the XInputGetState() function can be either ERROR_SUCCESS if a controller is connected to the machine at that player index or ERROR_FAIL if no device is connected. The function prototype for the XInputGetState() function is as follows.

DWORD XInputGetState(DWORD dwUserIndex, XINPUT_STATE* pState);

The XINPUT_STATE structure has fields that store the state of the controller’s various buttons, sticks, and so on. The information in this structure is the state of the device when the XInputGetState() function was called. The structure has the following definition, where wButtons is a flag that can store all information of the buttons, which includes face buttons, bumpers, and the start and back buttons.

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

XInput has flags that correspond to the various input states of an Xbox controller. These flags are as follows.

  • XINPUT_GAMEPAD_DPAD_UP

  • XINPUT_GAMEPAD_DPAD_DOWN

  • XINPUT_GAMEPAD_DPAD_LEFT

  • XINPUT_GAMEPAD_DPAD_RIGHT

  • XINPUT_GAMEPAD_START

  • XINPUT_GAMEPAD_BACK

  • XINPUT_GAMEPAD_LEFT_THUMB

  • XINPUT_GAMEPAD_RIGHT_THUMB

  • XINPUT_GAMEPAD_LEFT_SHOULDER

  • XINPUT_GAMEPAD_RIGHT_SHOULDER

  • XINPUT_GAMEPAD_A

  • XINPUT_GAMEPAD_B

  • XINPUT_GAMEPAD_X

  • XINPUT_GAMEPAD_Y

Detecting Button Presses

Once you have the controller’s state, you can test the individual buttons to see if they are being pressed or not. The state for each button is stored in the XINPUT_STATE object’s GamePad.wButtons field. The wButtons field is a short integer whose bits represent each button. You can use the button flags mentioned in the previous section and the logical AND operator (&) to test if a bit is set. If a bit is set, this means the button is being pressed. An example of obtaining the current input state and testing if the left and right bumper buttons are being pressed follows.

XINPUT_STATE state;
XInputGetState(0, &state);

if(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER)
   // Do Something…

if(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER)
   // Do Something…

If the conditional statements equal true, the button is currently being pressed. You can test if the back, start, and face buttons are being pressed by using their corresponding button flags as shown in the following.

// Back and start.
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK)
   // Do Something…

if(state.Gamepad.wButtons & XINPUT_GAMEPAD_START)
   // Do Something…

// Face buttons (a, b, x, y).
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_A)
   // Do Something…

if(state.Gamepad.wButtons & XINPUT_GAMEPAD_B)
   // Do Something…

if(state.Gamepad.wButtons & XINPUT_GAMEPAD_X)
   // Do Something…

if(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y)
   // Do Something…

The game pad controllers along with a few other controller types (e.g., the guitar) also have a directional pad on them. These directional pads are considered buttons, where you can press the up, down, left, and right arrow buttons independently or at the same time. An example of testing the controller state for these button presses is shown in the following.

// Arrow pad.
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
   // Do Something…

if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
   // Do Something…

if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
   // Do Something…

if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
   // Do Something…

The last remaining buttons are the left and right thumb stick’s digital buttons. These buttons are pressed by pushing the thumb stick in. You can test if these thumb stick digital buttons are pressed independently of testing for thumb stick movement. An example of testing the thumb stick digital buttons is as follows.

// Thumb buttons (pushing in left and right joysticks).
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB)
   // Do Something…

if(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB)
   // Do Something…

Detecting Triggers

Triggers are not buttons in the traditional sense. A trigger is more of a pressure-sensitive button, and XInput allows you to detect just how much pressure is being applied to these triggers. Currently, there are two triggers on an Xbox 360 controller on the top of the game pad device.

To test if a trigger is being pressed, you test the XINPUT_STATE object’s Gamepad.bLeftTrigger for the left trigger and Gamepad.bRightTrigger for the right trigger. These values are represented by unsigned char variables and if their value is over 0, the trigger is being pressed. If these trigger values are 255, the trigger is being held all the way down, while anything in between 0 (0%) and 255 (100%) determines the amount of pressure being applied to the trigger. The trigger values are obtained as follows.

unsigned char lt = state.Gamepad.bLeftTrigger;
unsigned char rt = state.Gamepad.bRightTrigger;

Detecting Thumb Stick Movements

The Xbox 360 game pad has two thumb sticks. The X and Y position information of the left thumb stick is stored in Gamepad.sThumbLX and Gamepad.sThumbLY, while the right thumb stick information is stored in Gamepad.sThumbRX and Gamepad.sThumbRY.

If the X and Y value of a thumb stick is equal to 0, the stick is centered along that axis. Therefore, an X and Y value of 0 for each means the thumb stick has not moved. The minimum value the thumb stick’s axes can have is –32768, and its maximum value is 32768. This means that if you are looking at the X axis, a value of –32768 indicates that the thumb stick is being moved all the way to the left, while a value of 32768 indicates that the stick is being moved all the way to the right. For the Y axis, a value of –32768 means the stick is being moved all the way down, while a value of 32768 means the stick is being moved all the way up. Keep in mind that a value of 0 (or near 0 since the sticks are highly sensitive) means the stick is not being moved at all. An example of reading the thumb stick information is shown as follows, where the values themselves are represented by short integers.

short lx = state.Gamepad.sThumbLX;
short ly = state.Gamepad.sThumbLY;
short rx = state.Gamepad.sThumbRX;
short ry = state.Gamepad.sThumbRY;

Not all joysticks will read zero when centered, especially for game pads that have been used frequently over time. One way of accounting for this is to use what is known as a dead zone. A dead zone is just a range of values that you will ignore and consider zero. For example, if the joystick reads a value between –20 and 20 then you can clamp any value between that range of dead zone values to 0. The same can be done to account for micro joystick changes from the center where the user might not be moving the thumb stick intentionally but movement is being registered.


Controller Vibrations

The Xbox controller can have two vibration modes. Some controllers, like the guitar, do not have vibration support, so setting this would not result in anything happening when using some non-game pad controllers. Each game pad controller has a left motor and a right motor. The differences between the motors are that the left motor is for low frequency vibrations (such as footsteps) while the right motor is stronger and used for higher frequency vibrations (such as explosions).

Setting the controller’s vibration is easy. You first create an XINPUT_VIBRATION object and set its left and right motor speeds from 0 to 65,535. If 0 is used, the controller does not vibrate. If 65,535 is used, the controller vibrates at 100% of its maximum power. Anything within that range will be a percentage between no vibration and maximum power. The XINPUT_VIBRATION structure is as follows.

typedef struct _XINPUT_VIBRATION {
    WORD wLeftMotorSpeed;
    WORD wRightMotorSpeed;
} XINPUT_VIBRATION, *PXINPUT_VIBRATION;

Once you’ve created an XINPUT_VIBRATION object and specified the left and right motor speeds, you are ready to apply it to any controller attached to the machine. To set the vibration, you can use XInputSetState(), and you pass to it the index of the controller to set the vibration state and the address to the vibration state object. This sets the motor speed for the specified controller. If you want to turn the vibration off, you have to call this function again and set both the left and right motors to 0. The function prototype for the XInputSetState() function is as follows.

DWORD XInputSetState(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration);

Controller Capabilities

You can obtain the capabilities of the controller (i.e., features) by calling the XInputGetCapabilities() function. This function takes the player index, input flags that can only be XINPUT_FLAG_GAMEPAD at this time, and the output address to the XINPUT_CAPABILITIES object that will store the features of the controller. The function prototype for the XInputGetCapabilities() function is as follows.

DWORD XInputGetCapabilities(DWORD dwUserIndex, DWORD dwFlags,
XINPUT_CAPABILITIES* pCapabilities);

The XINPUT_CAPABILITIES structure is as follows.

typedef struct _XINPUT_CAPABILITIES {
    BYTE Type;
    BYTE SubType;
    WORD Flags;
    XINPUT_GAMEPAD Gamepad;
    XINPUT_VIBRATION Vibration;
} XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES;

The Type can only be XINPUT_DEVTYPE_GAMEPAD.

The SubType can be XINPUT_DEVSUBTYPE_ARCADE_STICK if it is an arcade stick controller, XINPUT_DEVSUBTYPE_GAMEPAD if it is a game pad controller, or XINPUT_DEVSUBTYPE_WHEEL if it is a steering wheel. Other controllers such as guitars and so on fall under the game pad type.

The Flags can only be XINPUT_CAPS_VOICE_SUPPORTED. The XINPUT_GAMEPAD stores the controller button/thumb stick and other states for the device, while the XINPUT_VIBRATION stores the current vibration state for the device.

Other  
  •  Programming with DirectX : Game Input - Win32 Input
  •  Adobe Illustrator CS5 : Proofing and Printing Documents - Setting Advanced Options, Setting Color Management Options
  •  Adobe Illustrator CS5 : Setting Graphics Options, Previewing Color Separations, Setting Output Options
  •  Adobe Illustrator CS5 : Setting General Print Options, Setting Marks and Bleed Options
  •  AC-1 Ammoclip for Xbox 360 - Keep Shooting!
  •  Buyer's Guide: 3D Monitors (Part 3) - BenQ XL2420T, Samsung SyncMaster S23A750D, Asus VG278H
  •  Buyer's Guide: 3D Monitors (Part 2) - ViewSonic V3D231, LG DM2350D, HP 2311GT
  •  Buyer's Guide: 3D Monitors (Part 1) - LG D2342P, AOC e2352PHz
  •  Aperion Audio Zona Wireless Speaker System
  •  TX-2 Throat Mic - Covert Ops
  •  Philips Sound Tower DCM5090 - Elegant and Versatile
  •  EX-05 Multi-Format Wireless Headset - In The Army
  •  Gioteck HF-2 Controller - Different Strokes
  •  VX-1 Wireless Controller for PS3 – Big Improvement
  •  Sennheiser HD700 - Welcome To Audio Heaven
  •  Adobe Photoshop CS5 : Working with Automate Commands - Merging Images to HDR
  •  Adobe Photoshop CS5 : Working with Automate Commands - Using Photomerge
  •  Vive La Resolution
  •  Belkin ScreenCast AV4
  •  Has Google Sold SketchUp Down The River?
  •  
    Video
    Top 10
    Nikon 1 J2 With Stylish Design And Dependable Image And Video Quality
    Canon Powershot D20 - Super-Durable Waterproof Camera
    Fujifilm Finepix F800EXR – Another Excellent EXR
    Sony NEX-6 – The Best Compact Camera
    Teufel Cubycon 2 – An Excellent All-In-One For Films
    Dell S2740L - A Beautifully Crafted 27-inch IPS Monitor
    Philips 55PFL6007T With Fantastic Picture Quality
    Philips Gioco 278G4 – An Excellent 27-inch Screen
    Sony VPL-HW50ES – Sony’s Best Home Cinema Projector
    Windows Vista : Installing and Running Applications - Launching Applications
    Most View
    Bamboo Splash - Powerful Specs And Friendly Interface
    Powered By Windows (Part 2) - Toshiba Satellite U840 Series, Philips E248C3 MODA Lightframe Monitor & HP Envy Spectre 14
    MSI X79A-GD65 8D - Power without the Cost
    Canon EOS M With Wonderful Touchscreen Interface (Part 1)
    Windows Server 2003 : Building an Active Directory Structure (part 1) - The First Domain
    Personalize Your iPhone Case
    Speed ​​up browsing with a faster DNS
    Using and Configuring Public Folder Sharing
    Extending the Real-Time Communications Functionality of Exchange Server 2007 : Installing OCS 2007 (part 1)
    Google, privacy & you (Part 1)
    iPhone Application Development : Making Multivalue Choices with Pickers - Understanding Pickers
    Microsoft Surface With Windows RT - Truly A Unique Tablet
    Network Configuration & Troubleshooting (Part 1)
    Panasonic Lumix GH3 – The Fastest Touchscreen-Camera (Part 2)
    Programming Microsoft SQL Server 2005 : FOR XML Commands (part 3) - OPENXML Enhancements in SQL Server 2005
    Exchange Server 2010 : Track Exchange Performance (part 2) - Test the Performance Limitations in a Lab
    Extra Network Hardware Round-Up (Part 2) - NAS Drives, Media Center Extenders & Games Consoles
    Windows Server 2003 : Planning a Host Name Resolution Strategy - Understanding Name Resolution Requirements
    Google’s Data Liberation Front (Part 2)
    Datacolor SpyderLensCal (Part 1)