C++ Win32 Using XBox Controller For Input With Windows Messages

Started by
12 comments, last by BennettSteele 12 years, 2 months ago
Oh, ok. So i thought the ports the controllers were on were the actual usb ports, but its just the player # of the controller, and so forth. I created a new thread for capturing the controller input because it really bottle-necked the application in the WindowMessage handler. I also created a class for the controller. Here is the code:

XBox.h
class XBOXController
{
public:
HANDLE mThread;
unsigned int ThreadKillState;
bool InUse;
POINT LAnol,RAnol;
unsigned int LTrig,RTrig;
bool A,B,C,X,Y;
bool Start,Select;
void Init();
void StartChecking();
void StopChecking();
void Check();
};
DWORD WINAPI HandleXBOX(void* nID);


Xbox.cpp
extern myApp APP;
void XBOXController::Init()
{
this->ThreadKillState=0;//started
this->InUse=false;
this->LAnol.x=0;this->LAnol.y=0;this->RAnol.x=0;this->RAnol.y=0;
this->LTrig=0;this->RTrig=0;
this->A=false;this->B=false;this->X=false;this->Y=false;
this->Start=false;this->Select=false;
}
void XBOXController::Check()
{
DWORD isController;//Is it connected?
_XINPUT_STATE ConState;//all states of controller
ZeroMemory(&ConState,sizeof(_XINPUT_STATE));
isController=XInputGetState(0,&ConState);
if(isController==ERROR_SUCCESS)
{
if(!this->InUse)
{
this->InUse=true;
std::stringstream ConRep;ConRep<<"Switched To Using Xbox Controller";
APP.Log.Write(ConRep.str().c_str());
}
if(ConState.Gamepad.bLeftTrigger!=0)
{
this->LTrig=ConState.Gamepad.bLeftTrigger;
}
if(ConState.Gamepad.bRightTrigger!=0)
{
this->RTrig=ConState.Gamepad.bRightTrigger;
}
if(ConState.Gamepad.sThumbLX!=this->LAnol.x)
{
this->LAnol.x=ConState.Gamepad.sThumbLX;
}
if(ConState.Gamepad.sThumbLY!=this->LAnol.y)
{
this->LAnol.y=ConState.Gamepad.sThumbLY;
}
if(ConState.Gamepad.sThumbRX!=this->RAnol.x)
{
this->RAnol.x=ConState.Gamepad.sThumbRX;
}
if(ConState.Gamepad.sThumbRY!=this->RAnol.y)
{
this->RAnol.y=ConState.Gamepad.sThumbRY;
}
if(ConState.Gamepad.wButtons & XINPUT_GAMEPAD_A){this->A=true;APP.KeyLog.Write("XBox A Pressed");}else{this->A=false;APP.KeyLog.Write("XBox A Released");}
if(ConState.Gamepad.wButtons & XINPUT_GAMEPAD_B){this->B=true;APP.KeyLog.Write("XBox B Pressed");}else{this->B=false;APP.KeyLog.Write("XBox B Released");}
if(ConState.Gamepad.wButtons & XINPUT_GAMEPAD_X){this->X=true;APP.KeyLog.Write("XBox X Pressed");}else{this->X=false;APP.KeyLog.Write("XBox X Released");}
if(ConState.Gamepad.wButtons & XINPUT_GAMEPAD_Y){this->Y=true;APP.KeyLog.Write("XBox Y Pressed");}else{this->Y=false;APP.KeyLog.Write("XBox Y Released");}
}
else if(this->InUse)
{
this->InUse=false;
std::stringstream ConRep;ConRep<<"NOT Using Xbox Controller";
APP.Log.Write(ConRep.str().c_str());
}
}
void XBOXController::StartChecking()
{
this->mThread=CreateThread(NULL,0,HandleXBOX,(void*)NULL,0,NULL);
}
void XBOXController::StopChecking()
{
this->ThreadKillState=1;
//while(this->ThreadKillState<2)
//{
//}
TerminateThread(this->mThread,0);
}
DWORD WINAPI HandleXBOX(void* nID)
{
while(APP.XBOX.ThreadKillState==0)
{
APP.XBOX.Check();
}
APP.XBOX.ThreadKillState=2;//Done with thread
while(APP.XBOX.ThreadKillState==1)
{
APP.XBOX.ThreadKillState=2;
}
ExitThread(0);
}


Just make sure to call XBox.Init(), then after creating the window call XBox.StartListening(), then when youre done, call XBox.StopListening()

I have the XBox class in a App class... so this is how i handled it. ;)
Advertisement
Well, except i cant get the button presses, like A,B,Start... but i can get the analog sticks and triggers. Do any of you know why i might not be getting the button presses?

EDIT:

I can get the A buttons and such working, but this code:

if(ConState.Gamepad.wButtons & XINPUT_GAMEPAD_Y && !this->Y)
{
this->Y=true;
APP.KeyLog.Write("XBox Y Pressed");
}
else if(this->Y){
this->Y=false;
APP.KeyLog.Write("XBox Y Released");
}


Keeps repeating, so lets say im holding it down, it repeats it being pressed and then released...
Think through your code or step through it with a debugger to see what happens. Long story short, you're not maintaining the state between subsequent polling.

What happens when I hold the A button down for 2 seconds? Your program will poll the gamepad, find that A is down and print out "A pressed," furthermore, the next time through (I'm still holding the button down), then your code will see that it's down but since your "flag" is set, it will jump to the else block and print "A released," ad infinitum.

How do you only detect presses? Maintain a last state and the current state. A button is pressed only when it is down in the current state, but up in the last state. A button is released only when it is down in the last state, but up in the current state.

Example Pseudo-code:
while 1:
lastState = currentState
currentState = PollControllerState()

if (lastState.ButtonA is up) and (currentState.ButtonA is down):
pressed = True
else if (lastState.ButtonA is down) and (currentState.ButtonA is up):
released = True
else
// It's in the same state as the last time
Denzel Morris (@drdizzy) :: Software Engineer :: SkyTech Enterprises, Inc.
"When men are most sure and arrogant they are commonly most mistaken, giving views to passion without that proper deliberation which alone can secure them from the grossest absurdities." - David Hume
Thanks... Im trying to switch to Microsoft Visual C++ 2010, but i get so many errors... and when i tried using the new version of XInput with DirectX, Code::Blocks complained about '__in'... so i dunno... the new version of XInput allows to check if the buttons are repeated, pressed, or released. DX

This topic is closed to new replies.

Advertisement