Gamepads and joysticks

So i went toying around with my old sixaxis gamepad on my pc and decided to add gamepad support to one of my apps, turns out it’s not that hard so i thought i would add a quick tutorial about it.

First of all it’s worth noting that a gamepad and a joystick is the same thing from a technical perspective. secondly the specific setup is using windows own built in joystick interface which means that we are limited to 6 analog axis and 32 buttons, which is plenty as the classic playstation dualshock controller (which almost every other controller is based on in some way) only has 4 analog axis and 17 buttons (gyros and accelerometers does not count as we can’t use them).

So first step as always is some setup, first the defines we are going to use to locate our buttons, i also included what they bind to on the dualshock, but it should be the same for most other gamepads.

[stextbox id=”grey”]#define JOY_BUTTON_1    0x00001 //triangle
#define JOY_BUTTON_2    0x00002 //circle
#define JOY_BUTTON_3    0x00004 //cross
#define JOY_BUTTON_4    0x00008 //square
#define JOY_BUTTON_5    0x00010 //l2
#define JOY_BUTTON_6    0x00020 //r2
#define JOY_BUTTON_7    0x00040 //l1
#define JOY_BUTTON_8    0x00080 //r1
#define JOY_BUTTON_9    0x00100 //select
#define JOY_BUTTON_10    0x00200 //start
#define JOY_BUTTON_11    0x00400 //l3
#define JOY_BUTTON_12    0x00800 //r3
#define JOY_BUTTON_13    0x01000 //ps home
#define JOY_BUTTON_14    0x02000 //dpad-up
#define JOY_BUTTON_15    0x04000 //dpad-right
#define JOY_BUTTON_16    0x08000 //dpad-down
#define JOY_BUTTON_17    0x10000 //dpad-left[/stextbox]

Then we add some variables

[stextbox id=”grey”]BOOL JoyPresent=false;
JOYCAPS   joyCaps;[/stextbox]


step 2 is to initialize the joystick, all of this is only called once in the init function.

[stextbox id=”grey”]JOYINFOEX joyInfoEx;
joyInfoEx.dwSize = sizeof(joyInfoEx);
joyGetDevCaps(JOYSTICKID1, &joyCaps, sizeof(joyCaps));
JoyPresent = (joyGetPosEx(JOYSTICKID1, &joyInfoEx) == JOYERR_NOERROR);[/stextbox]

now joyCaps is where we list all the capabilities of the joystick, though in particular we are going to need the max values of all the axis on the analog sticks as that value can vary depending on calibration and gamepad.


Third step is to read the current state of the joystick, this is done for every frame you want to read the input.

[stextbox id=”grey”]JOYINFOEX joyInfoEx;
if (JoyPresent)
joyInfoEx.dwSize = sizeof(joyInfoEx);
joyInfoEx.dwFlags = JOY_RETURNALL;
joyGetPosEx(JOYSTICKID1, &joyInfoEx);

First we check if there actually is a gamepad attached, then we set JOY_RETURNALL as a flag in joyInfoEx, this will cause the next function joyGetPosEx to return all values, it can be set to only return some values or to return raw data, but for our purposes we want it all, if you would like more then consult MSDN.


The last step is to read the data which is also sort of simple, however all the buttons are clumped together in the same integer  (technically unsigned long) so to read a single one we call something like this

[stextbox id=”grey”]if (joyInfoEx.dwButtons & JOY_BUTTON_1) //then do whatever[/stextbox]

Secondly the analog sticks are also integers (again unsigned long) that range from 0 to the max of that axis, and the centered stick is usually in the middle (though if you want it’s possible to get the actual center by setting another flag in joyGetPosEx).
This data is pretty useless in this form, especially if you use floats which are centered at 0.0f and has a much more sensible range at lets say -30.0f to +30.0f, in that case i use this formula.

[stextbox id=”grey”]x=(float)(joyInfoEx.dwXpos/(joyCaps.wXmax/2.0f)-1.0f)*30;

Pretty straightforward IMO.
A small advice though, some gamepads are pretty sensitive and they do degrade with use which makes them unable to stay centered, and that can cause the stick to start drifting slightly even though it’s properly calibrated, so add a bit of deadzone with this formula.

[stextbox id=”grey”]float dzx=abs(x*5.0f); //this value depends on your setup
if (dzx>1.0) dzx=1.0f;

That’s it for this time, have fun coding.

No Comments

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

WordPress Themes