Hello Guest, please login or register.
Did you miss your activation email?
Login with username, password and session length.

Pages: [1]   Go Down

Author Topic: [C++ Tutorial] XBOX 360 Controller Input  (Read 1992 times)

0 Members and 1 Guest are viewing this topic.
[C++ Tutorial] XBOX 360 Controller Input
« on: June 14, 2008, 04:02:33 am »
  • Minalien
  • *
  • Reputation: +10/-1
  • Offline Offline
  • Gender: Female
  • Posts: 2119
Preface
This is just a short tutorial for using an XBOX 360 Controller in your C++ Application. I assume that you have an intermediate knowledge with C++, because I will not be breaking every step down Barney-style for you. I am writing using Microsoft Visual C++ 2008, and will assume that you are doing the same. If you are not, please add the XInput library (from the Microsoft DirectX SDK) to your project in the manner specific to your development environment, and please overlook the line "#pragma comment(lib, "XInput.lib"). This is also assuming that you are starting with an empty console project, and that it is set up to be able to use windows.h and associated headers, as well as XInput and its' associated headers.

Requirements
Microsoft DirectX SDK (October 2005 or later)
XBOX 360 Controller for Windows (Obviously.)

Download
Win32 Binaries: http://files.minalien.com/XBOX360Test_Bin.rar
Source (Including VC++ 2008 Solution File): http://files.minalien.com/XBOX360Test_Src.rar

Step 1 - Setting Up
To start off, we are going to create two files: CXBOXController.h and CXBOXController.cpp. We'll start by editing XBOXController.h.

Step 2 - Class Definition
Code: C
  1. #ifndef _XBOX_CONTROLLER_H_
  2. #define _XBOX_CONTROLLER_H_
  3.  
  4. // No MFC
  5. #define WIN32_LEAN_AND_MEAN
  6.  
  7. // We need the Windows Header and the XInput Header
  8. #include <windows.h>
  9. #include <XInput.h>
  10.  
  11. // Now, the XInput Library
  12. // NOTE: COMMENT THIS OUT IF YOU ARE NOT USING A COMPILER THAT SUPPORTS THIS METHOD OF LINKING LIBRARIES
  13. #pragma comment(lib, "XInput.lib")
  14.  
  15. // XBOX Controller Class Definition
  16. class CXBOXController
  17. {
  18. private:
  19.         XINPUT_STATE _controllerState;
  20.         int _controllerNum;
  21. public:
  22.         CXBOXController(int playerNumber);
  23.         XINPUT_STATE GetState();
  24.         bool IsConnected();
  25.         void Vibrate(int leftVal = 0, int rightVal = 0);
  26. };
  27.  
  28. #endif

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 (silly Microsoft) if successful. The Vibrate function simply provides us with a quick and easy method of vibrating the controller.

Step 3 - Making it Happen
Code: C
  1. #include "CXBOXController.h"
  2.  
  3. CXBOXController::CXBOXController(int playerNumber)
  4. {
  5.         // Set the Controller Number
  6.         _controllerNum = playerNumber - 1;
  7. }
  8.  
  9. XINPUT_STATE CXBOXController::GetState()
  10. {
  11.         // Zeroise the state
  12.         ZeroMemory(&_controllerState, sizeof(XINPUT_STATE));
  13.  
  14.         // Get the state
  15.         XInputGetState(_controllerNum, &_controllerState);
  16.  
  17.         return _controllerState;
  18. }
  19.  
  20. bool CXBOXController::IsConnected()
  21. {
  22.         // Zeroise the state
  23.         ZeroMemory(&_controllerState, sizeof(XINPUT_STATE));
  24.  
  25.         // Get the state
  26.         DWORD Result = XInputGetState(_controllerNum, &_controllerState);
  27.  
  28.         if(Result == ERROR_SUCCESS)
  29.         {
  30.                 return true;
  31.         }
  32.         else
  33.         {
  34.                 return false;
  35.         }
  36. }
  37.  
  38. void CXBOXController::Vibrate(int leftVal, int rightVal)
  39. {
  40.         // Create a Vibraton State
  41.         XINPUT_VIBRATION Vibration;
  42.  
  43.         // Zeroise the Vibration
  44.         ZeroMemory(&Vibration, sizeof(XINPUT_VIBRATION));
  45.  
  46.         // Set the Vibration Values
  47.         Vibration.wLeftMotorSpeed = leftVal;
  48.         Vibration.wRightMotorSpeed = rightVal;
  49.  
  50.         // Vibrate the controller
  51.         XInputSetState(_controllerNum, &Vibration);
  52. }

Breakdown:
This is where the code is actually fleshed out and provides functionality.

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 zeroise the pointer to the game state, so that we can ensure no artifacts exist, due to how 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 zeroise 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 zeroise 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.

Step 4 - Testing
Now, it's time to write a small program to test this.
Code: C
  1. #include "CXBOXController.h"
  2. #include <iostream>
  3.  
  4. CXBOXController* Player1;
  5. int main(int argc, char* argv[])
  6. {
  7.         Player1 = new CXBOXController(1);
  8.  
  9.         std::cout << "Instructions:\n";
  10.         std::cout << "[A] Vibrate Left Only\n";
  11.         std::cout << "[B] Vibrate Right Only\n";
  12.         std::cout << "[X] Vibrate Both\n";
  13.         std::cout << "[Y] Vibrate Neither\n";
  14.         std::cout << "[BACK] Exit\n";
  15.  
  16.         while(true)
  17.         {
  18.                 if(Player1->IsConnected())
  19.                 {
  20.                         if(Player1->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_A)
  21.                         {
  22.                                 Player1->Vibrate(65535, 0);
  23.                         }
  24.  
  25.                         if(Player1->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_B)
  26.                         {
  27.                                 Player1->Vibrate(0, 65535);
  28.                         }
  29.  
  30.                         if(Player1->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_X)
  31.                         {
  32.                                 Player1->Vibrate(65535, 65535);
  33.                         }
  34.  
  35.                         if(Player1->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_Y)
  36.                         {
  37.                                 Player1->Vibrate();
  38.                         }
  39.  
  40.                         if(Player1->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_BACK)
  41.                         {
  42.                                 break;
  43.                         }
  44.                 }
  45.                 else
  46.                 {
  47.                         std::cout << "\n\tERROR! PLAYER 1 - XBOX 360 Controller Not Found!\n";
  48.                         std::cout << "Press Any Key To Exit.";
  49.                         std::cin.get();
  50.                         break;
  51.                 }
  52.         }
  53.  
  54.         delete(Player1);
  55.  
  56.         return( 0 );
  57. }

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

However, I will go over the following parts:
Code: C
  1. CXBOXController* Player1;
  2. ...
  3. 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).

Code: C
  1. if(Player1->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_A)
This is the code that checks for gamepad state. To check for button inputs, you must use a logical AND to check if the butotn was pressed.

here are the hexadecimal values of the different buttons:
Quote from: XINPUT Gamepad Button Values
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. More information on doing that can be found here: http://msdn.microsoft.com/en-us/library/bb174832(VS.85).aspx

Conclusion
That concludes my XBOX 360 Conroller tutorial. I hope you've learned from it, and perhaps can make some good use of it.
« Last Edit: June 14, 2008, 04:09:06 am by Minalien »
Logged
Quote
There's such a double standard about religion in the modern world. Catholics can gather, wear white robes, and say "In nomine Patris, et Filii, et Spiritus Sancti" and be considered normal.

But if my friends and I gather, wear black robes, and say  "Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn", we're considered cultists.
  • Development Blog
Re: [C++ Tutorial] XBOX 360 Controller Input
« Reply #1 on: June 20, 2008, 12:02:43 am »
  • *
  • Reputation: +0/-0
  • Offline Offline
  • Gender: Male
  • Posts: 266
Nice, thanks for the post here; I'll put it to some good use :D
Logged
Intel P4 3.2 GHZ
2.5GB SDRAM DDR400
350GB SATA
ATI RADEON HD 2600PRO 512MB
Creative Sound Blaster Audigy2 Z
Windows XP SP2

Current Projects: None.
- Trask
Pages: [1]   Go Up

 


Contact Us | Legal | Advertise Here
2013 © ZFGC, All Rights Reserved



Page created in 0.036 seconds with 58 queries.

anything