|
ThemsAllTook
|
 |
« on: January 25, 2010, 05:38:23 AM » |
|
Hello all, I've been working on a library for Mac OS X, Windows, and Linux that provides a clean, easy-to-use API for reading input from USB game controllers, to be released as an open source project under the zlib/libpng license. I've built a simple test harness that shows all connected gamepads and the state of their controls. It looks like this:  If any of you have a gamepad, joystick, or other game controller and can spare a minute, could you please try out the test app and let me know how it handles your hardware? Here are builds for each platform: http://sacredsoftware.net/temp/GamepadTestHarness_macosx.zip <- Mac http://sacredsoftware.net/temp/GamepadTestHarness_windows.zip <- Windows http://sacredsoftware.net/temp/GamepadTestHarness_linux.zip <- Linux I have some minor dependency issues to work out before I can make the library itself available, but if you're interested, here's what the API looks like: #ifndef __GAMEPAD_H__ #define __GAMEPAD_H__
#include <stdbool.h> #include "utilities/EventDispatcher.h"
// eventData -> struct Gamepad_device #define GAMEPAD_EVENT_DEVICE_ATTACHED "GAMEPAD_EVENT_DEVICE_ATTACHED" // Only dispatched when Gamepad_init or Gamepad_detectDevices is called #define GAMEPAD_EVENT_DEVICE_REMOVED "GAMEPAD_EVENT_DEVICE_REMOVED" // Can be dispatched at any time
// eventData -> struct Gamepad_buttonEvent #define GAMEPAD_EVENT_BUTTON_DOWN "GAMEPAD_EVENT_BUTTON_DOWN" // Only dispatched when Gamepad_processEvents is called #define GAMEPAD_EVENT_BUTTON_UP "GAMEPAD_EVENT_BUTTON_UP" // Only dispatched when Gamepad_processEvents is called
// eventData -> struct Gamepad_axisEvent #define GAMEPAD_EVENT_AXIS_MOVED "GAMEPAD_EVENT_AXIS_MOVED" // Only dispatched when Gamepad_processEvents is called
struct Gamepad_buttonEvent { // Device that generated the event struct Gamepad_device * device; // Relative time of the event, in seconds. Does not necessarily correspond to values returned from Shell_getCurrentTime(). double timestamp; // Button being pushed or released unsigned int buttonID; // True if button is down bool down; };
struct Gamepad_axisEvent { // Device that generated the event struct Gamepad_device * device; // Relative time of the event, in seconds. Does not necessarily correspond to values returned from Shell_getCurrentTime(). double timestamp; // Axis being moved unsigned int axisID; // Axis position value, in the range [-1..1] float value; };
struct Gamepad_device { // Unique device identifier for application session. If a device is removed and subsequently reattached during the same application session, it will have a new deviceID. unsigned int deviceID; // Human-readable device name const char * description; // USB vendor/product IDs as returned by the driver. Can be used to determine the particular model of device represented. int vendorID; int productID; // Number of axis elements belonging to the device unsigned int numAxes; // Number of button elements belonging to the device unsigned int numButtons; // Array[numAxes] of values representing the current state of each axis, in the range [-1..1] float * axisStates; // Array[numButtons] of values representing the current state of each button bool * buttonStates; // Broadcasts GAMEPAD_EVENT_BUTTON_DOWN, GAMEPAD_EVENT_BUTTON_UP, and GAMEPAD_EVENT_AXIS_MOVED EventDispatcher * eventDispatcher; // Platform-specific device data storage; don't mess with it void * privateData; };
/* Initializes gamepad library and detects initial devices. Call this before any other Gamepad_*() function, EXCEPT Gamepad_eventDispatcher(). In order to get receive GAMEPAD_EVENT_DEVICE_ATTACHED events from devices detected in Gamepad_init(), you must register handlers for those events before calling Gamepad_init(). */ void Gamepad_init();
/* Tears down all data structures created by the gamepad library and releases any memory that was allocated. It is not necessary to call this function at application termination. */ void Gamepad_shutdown();
/* EventDispatcher used by gamepad library to broadcast GAMEPAD_EVENT_DEVICE_ATTACHED and GAMEPAD_EVENT_DEVICE_REMOVED events. */ EventDispatcher * Gamepad_eventDispatcher();
/* Returns the number of currently attached gamepad devices. */ unsigned int Gamepad_numDevices();
/* Returns the specified Gamepad_device struct, or NULL if deviceIndex is out of bounds. */ struct Gamepad_device * Gamepad_deviceAtIndex(unsigned int deviceIndex);
/* Polls for any devices that have been attached since the last call to Gamepad_detectDevices() or Gamepad_init(). If any new devices are found, a GAMEPAD_EVENT_DEVICE_ATTACHED event will be broadcast via Gamepad_eventDispatcher() for each one. */ void Gamepad_detectDevices();
/* Reads pending input from all attached devices and broadcasts GAMEPAD_EVENT_BUTTON_DOWN, GAMEPAD_EVENT_BUTTON_UP, and GAMEPAD_EVENT_AXIS_MOVED events through the eventDispatcher of the device that generated the event. */ void Gamepad_processEvents();
#endif
EDIT: Libraries available: Source, Pre-built binaries
|
|
|
|
« Last Edit: January 31, 2010, 04:35:23 PM by ThemsAllTook »
|
Logged
|
|
|
|
deadeye
First Manbaby Home
Level 10
|
 |
« Reply #1 on: January 25, 2010, 05:58:57 AM » |
|
Tried the windows version with my Logitech Dual Action. Works fine, all buttons and axis...es... light up normally. Your buttons are numbered 0 - 11, and the ones on my controller are numbered 1 - 12, but I'm sure that's of no consequence.
Don't know what kind of hardware info you need, but here: Windows XP SP2, Athlon 64 Dual Core 4200+ 2.21GHz, 2G Ram
|
|
|
|
|
Logged
|
|
|
|
|
Draknek
|
 |
« Reply #2 on: January 25, 2010, 06:42:24 AM » |
|
Tried the Linux version with an Xbox 360 controller and it worked. The axis ordering is maybe a bit weird (left x, left y, left trigger, right x, right y, right trigger), but that has nothing to do with your library.
|
|
|
|
|
Logged
|
|
|
|
Ivan
Owl Country
Level 10
alright, let's see what we can see
|
 |
« Reply #3 on: January 25, 2010, 10:14:12 AM » |
|
Wow, this looks great!! I'm gonna see if i can roll it up into my engine. I'll let you know how it works with my gamepads
|
|
|
|
|
Logged
|
|
|
|
Alex May
...is probably drunk right now.
Level 10
hen hao wan
|
 |
« Reply #4 on: January 25, 2010, 10:27:50 AM » |
|
Great idea.
One thing you could do is detect certain types of commonly-used controllers and have defines or enumerations for their buttons, so that apps could use those in a switch against the controller type.
|
|
|
|
|
Logged
|
|
|
|
|
ThemsAllTook
|
 |
« Reply #5 on: January 25, 2010, 10:43:28 AM » |
|
Cool, glad to hear it's working so far! Great idea.
One thing you could do is detect certain types of commonly-used controllers and have defines or enumerations for their buttons, so that apps could use those in a switch against the controller type.
Yep, I'm definitely thinking about ways to do this nicely... Once I get the low-level parts of this library working well enough (which looks like it might be already), I'd like to build a higher-level device-aware API on top of it. The hope is that the high-level API would be able to consistently tell you which button is which, tell you their names, know the physical layout for displaying configuration screens, etc. This sounds like it might require a large data collection effort to build up a reasonable database of device behaviors, so I'm still thinking about the logistics of that... If I can get it going, though, I feel like this database could be a great asset to the game development community.
|
|
|
|
|
Logged
|
|
|
|
|
iamwhosiam
|
 |
« Reply #6 on: January 25, 2010, 05:05:03 PM » |
|
don't know if your still wondering but the 360 controller works on windows!
perfectly!
I was just wondering how I would do this a couple days ago. Can't wait for this one!
|
|
|
|
|
Logged
|
|
|
|
|
mcc
|
 |
« Reply #7 on: January 25, 2010, 09:36:51 PM » |
|
What would be the difference between this and SDL joystick input?
|
|
|
|
|
Logged
|
|
|
|
|
ThemsAllTook
|
 |
« Reply #8 on: January 26, 2010, 07:01:34 AM » |
|
What would be the difference between this and SDL joystick input?
The two main reasons I wrote this instead of using SDL_joystick: - SDL is licensed under GPL, which I find too restrictive. I prefer permissive licenses like zlib/libpng.
- SDL_joystick doesn't look like it can be used standalone. You have to pull in all of SDL to use it.
If you're already using SDL or if the above two things don't bug you, it'll probably work just as well. I actually used SDL joystick code as a reference/sanity check for a lot of what I did here, so it ends up being reasonably similar.
|
|
|
|
|
Logged
|
|
|
|
|
ThemsAllTook
|
 |
« Reply #9 on: January 28, 2010, 06:54:33 PM » |
|
I think I've finally managed to get this into a releasable state. SourcePre-built binariesHave fun! Please let me know if I've overlooked anything, or if you find bugs, have suggestions for improvements, etc.
|
|
|
|
|
Logged
|
|
|
|
|
d3sphil
|
 |
« Reply #10 on: February 06, 2010, 09:22:35 PM » |
|
this looks sweet =). I typically use SDL, but the SDL_joystick doesn't support any type of attach/detach stuff. From running your example and looking at the code it seems this library can do that stuff, so I will most likely use this over anything else. Detecting when a gamepad is connected or disconnected is like super important in my opinion =).
Thanks!
|
|
|
|
|
Logged
|
|
|
|
|
Mikademus
|
 |
« Reply #11 on: February 07, 2010, 05:58:29 AM » |
|
The two main reasons I wrote this instead of using SDL_joystick: - SDL is licensed under GPL, which I find too restrictive. I prefer permissive licenses like zlib/libpng.
- SDL_joystick doesn't look like it can be used standalone. You have to pull in all of SDL to use it.
I agree with your second point, the less external dependencies I have to include the happier I am! But SDL is not GPL, it is LGPL. Still, I really love your effort and I will absolutely try your library! 
|
|
|
|
|
Logged
|
\\\"There\\\'s a tendency among the press to attribute the creation of a game to a single person,\\\" says Warren Spector, creator of Thief and Deus Ex. --IGN<br />My compilation of game engines for indies
|
|
|
|
ThemsAllTook
|
 |
« Reply #12 on: February 08, 2010, 10:06:01 AM » |
|
Cool, thanks guys. I've done a test integration of this library into one of my own games to experience any integration pains myself. Here's the stuff I'm working on fixing: - The 1.1.0 release posted above was accidentally built with some debug code left in. The effect this will has is that hat switches on some joysticks will give erroneous inputs on Mac OS X.
- I'm tracking down a crash that occurs when I remove a device and plug it back in while running the game, which for some reason works correctly in the test harness. No idea yet what's different about the two cases.
- Axis inputs are a huge pain to manage. The game I'm integrating this with is wired to read keyboard inputs for each of the four directions. In order to determine the equivalent of "key down" and "key up" for each direction, I have to keep the last value of each mapped axis around and compare it with new values that are coming in, and do some fudging and thresholding to make sure it feels stable. I'd like to add an abstracted API that will ease this somewhat (while still allowing you to read raw axis inputs if desired, of course).
- Mapping buttons/axes to game controls and saving those settings between game sessions is a big can of worms, to say the least... There's a lot of complex logic I still need to work out conceptually. Thinking about having multiple gamepads of the same type attached (indistinguishable to my library other than the order in which they were attached), remembering mappings for each gamepad type, what to do when more than one gamepad that has mappings is plugged in... It's a bit of a nightmare, really. Hopefully I'll be able to come up with a nice solution that the API can support. A lot of this will be on the individual application, but I want to consolidate the logic in the library as much as makes sense.
All of the above is still ignoring the additional layer I was talking about that would be aware of physical device layouts and characteristics. Lots to still do here!
|
|
|
|
|
Logged
|
|
|
|
|
Matt Thorson
|
 |
« Reply #13 on: February 09, 2010, 08:33:52 PM » |
|
I'm on Windows 7 with an XB360 controller and it works perfectly 
|
|
|
|
|
Logged
|
|
|
|
|