pyPad360 v1.0 Available

Rabid Squirrel Games is proud to announce our first contribution to the game development community!
pyPad360 is a Python class that provides an easy to use interface for Xbox 360 controllers for the Panda3D game engine. pyPad360 achieves its magic by translating the joystick input messages from the pygame library and mapping them to Xbox360 buttons, axes, etc.

Please visit for the latest version.

Comments and code improvements are welcome! :slight_smile:

Special thanks goes to those who posted here to solve the final problem:


Looks cool! :slight_smile: Unfortunately I don’t have such controller :frowning:

For me the dpad, xbox button, and triggers weren’t working. I imagine this is due to changes in SDL and/or pygame. I’m working with with pygame 1.9.1 and SDL 1.2.15.

I’ve fixed these issues, and also changed how pypad360 works as a whole. Whereas before it used a large number of if statements to determine the state of the controller, it now constructs the message string based on a reduced number of if statements instead.

Note that due to how pypad360 receives dpad events, the dpad messages it produces have changed.
The dpad now works like other button events; you get UP and DOWN events, rather than an a load of events for as long as it is pressed down.
Also the message string has changed. Before it used to produce a string with the format of
Now that string looks like

I’ve also removed the limit on the number of controllers.

I changed the version number up to v2.0 because of the breaking changes in the dpad message string. You can grab it from here:

Please note that I am not part of Rabid Squirrel Games! Just a user of pypad360 who wanted to share the love :wink:

Nice timing. I just recently ordered an xbox 360 controller. I’ll try it out when it arrives.

Now that I’ve finished the project that I was using this for I thought I’d post the final version we used. It’s available here:

It no longer uses pygame but uses pysdl2 instead. It also supports rumbling!
Message strings are no longer appended with the controller number, it’s sent as an argument with the message instead. So they are now of the form “A_DOWN” and “LSTICK_H” instead of “C1_A_DOWN” or “C1_LSTICK_HORZ”.
We were using these like this:

self.accept("LSTICK_H", self.move, [PyPad360.LSTICK_H])

def move(self, axis_num, controller_num)
   amount = self.controllers.axes_states[axis_num]
   # Do move stuff

All of the axis values are normalised to between -1 and 1, and are kept track of in self.axes_states. The LSTICK_H, LSTICK_V, etc class variables relate to the index that that axis is in axes_states. So self.axes_states[self.LSTICK_H] will get you the axes state of the horizontal movement of the left stick.

The controllers are rumbled using messenger.send(“rumble-controller”, [controllerId, strength, duration]), where controllerId is the number of the controller to rumble, strength is a number between 0 and 1, and duration is the amount of time to rumble for in milliseconds. (strength and duration documentation is here:

It doesn’t support hot plugging controllers but it should be possible because an unexpected event type (e.type) occurs when one is plugged in. No checks are done on array indexes but they probably should be. Annoyingly the button and axis mappings for the default kernel driver in Linux and for xboxdrv differ so I’d recommend allowing the user to change those. Also this is untested on Mac.