# How can I setup a controller in the BGE?

Is it possible to get a DS4 controller to work in the BGE?

I've tried this project from Blend Swap, but only the buttons seem to work, not the axes. Is there any way to fix this?

If it's relevant, I'm using Xubuntu, with the builtin kernel driver, but I've also tried it with the old Ds4drv but it won't work at all.

In fairness, that file from blendswap did not work for me either. However making a controller's axes work is pretty easy.

There are two ways to access a controller in the BGE, that is with the joystick sensor or the joystick class through python. They are both very much the same.

The notable difference is in the way it reports the input from the axes. Using the logic brick you will get a rather arbitrary range between -32767 and 32767 (if this is the horizontal axis,-32767 is left, 0 is no moment, and 32767 is full right.)
Now getting the input through the python class normalizes the values: between -1.0 and 1.0, again 0 is no movement.

For the remainder of the answer I will be using the just the python class, but everything is easily adaptable to the logic brick.

Trouble is there are no event handlers for controllers (buttons, hats, or axes), so we have to make our own.

# The buttons

For the button, using the python class, all you get is a list of the active buttons. They are listed by id 0-12. As an example button 0 is the Square Button on a DS4, and the blue X button on the xbox layout.

To turn the list in to something useful for input you will need a few lines like these:

joystick = bge.logic.joysticks[0]
btns = joystick.activeButtons
if 0 in btns and len(btns) == 1:
doSomething()


The top line gets the controller, the second line gets the button list. Then it is just checking if the button we are targeting (button 0) is in the list. I have the len(btns) == 1 part in there so that it is only triggered by an exclusive button press (there are no other buttons held down).

# The hats

Similarly the active hat is expressed in a list. However there will only ever be one active "direction" in this hat list. There are eight directions on the hat:

0:None
1:Up
2:Right
4:Down
8:Left
3:Up - Right
6:Down - Right
12:Down - Left
9:Up - Left

from the api

Now if there is no active direction (the hat is not being pressed) then the list will be 0, not an empty list.

This is one way you can use the input from the hats:

up = 1
down = 4
left = 8
right = 2
upLeft =9
upRight = 3
downLeft = 12
downRight = 6

hats = joystick.hatValues
if up in hats:
player.applyMovement([0.01, 0, 0], True)
elif left in hats:
player.applyMovement([0, 0.01, 0], True)


# The axes

As mentioned above the axis values are in a list axisValues, which is different for the logic brick and the python class. Also, I do not have a DS controller, I have a "Logitech Dual Action" controller, so the axes may be (probably are) different.

At least for a xbox style controller the axes are in this order: left analog stick X, left analog stick Y, then right analog stick X and right analog stick Y.

So some (overly simplified) code to use this would be:

av = joystick.axisValues
left_analog_x = av[0]
left_analog_y = av[1]
right_analog_x = av[2]
right_analog_y = av[3]

Note the dead zone there, if that is not done the player will always drift, even when there is not input.) Now I have done this on two different computers, and both have had wildly different amounts of initial drift. So what I do is just print(joystick.axisValues) and then add or subtract those values to each value in the axisValues list. It is not an ideal solution, but if the values are small it works.