Tutorial: Introduction to game controllers

hid-feat
Share on Facebook0Share on Google+1Tweet about this on TwitterShare on LinkedIn0

It’s an exciting time to be a mobile app developer. Through the magic of mobile and Bluetooth support on devices, it’s now possible to use HID (Human Interface Device) controllers to play games, in addition to the standard touchscreen and accelerometer. While this isn’t yet “utopia,” you can do some really cool things with your wireless device and modern technology.

Key event framework

For HID controllers, we decided to build upon the existing key event framework. Thus, programming for controllers won’t be too much different — no plugins are required for HID-compliant controllers, nor do you need to require() anything special.

Of course, we haven’t provided any code other than returning true because it all depends on what you want to do. The button names may also vary from controller to controller — for example, they may not always be called "buttonA" or "buttonX", so if you are working with a new controller, it’s useful to check the value of the buttons that are pressed.

Button phases

Note that buttons/keys produce two phases, much like touch handlers. Those two phases are "up" and "down", where "down" means the user has pressed the button and "up" means they have released it. Like touch handlers, you do not “continuously” get events — once you press the button and get the "down" phase, you will not get another event until the button is released, thus dispatching the "up" phase.

Similar to touch events, it’s generally best practice to use the "down" state for time-sensitive actions like movement or firing weapons. However, for UI elements that typically respond like a mouse click, or touch events that trigger when the touch is complete, the "up" state may be warranted.

Putting it together

Let’s look at an example movePlayer() function using event-based buttons:

Detecting controllers

Most likely, you will also need to know if the controller is attached and also know when it’s detached, or if a new controller comes into play. This is handled using the inputDevice type.

Here are a few notes regarding controller detection:

  • For multiplayer apps, the event.descriptor (i.e. "Joystick 1", "Joystick 2") can be used as a unique key that binds a particular controller to a player. This will scan for active devices and set up a table of devices that are currently connected.
  • You should watch for connections and disconnections during gameplay and handle “losing” a controller or adding a controller. You may also want to pause the game if a controller drops out.
  • You might want to hide any UI elements that are specific to one controller, or hide “touchscreen” features when there are controllers present.

And here’s some sample code to handle this:

Note that these status changes will not register if the app is suspended. It’s your responsibility to poll the controllers if you’re resuming back to gameplay state.

Conclusion

Most game controllers offer both digital inputs (buttons) and analog inputs called sticks or joysticks. Because the typical joystick moves both up and down and left and right, we measure the movement based on which “axis” it’s moving on. An analog stick moving up and down will be measured along its Y axis, while side-to-side movement is measured on the X axis.

Axis input will be covered in a future blog post, but it’s important to know that many game controllers will map the left analog stick to the D-Pad. As such, moving the left stick will frequently generate "up", "down", "left" and "right" events. Also, the bottom shoulder buttons are considered “analog” inputs, but they will generate “button” events when they are squeezed past a certain threshold. If your app needs to know precisely what value those triggers are producing, you would use the axis method of measuring things, for fine-tuned control.


Share on Facebook0Share on Google+1Tweet about this on TwitterShare on LinkedIn0
Rob Miracle

Rob Miracle creates mobile apps for his own enjoyment and the amusement of others. He serves the Corona Community in the forums, on the blog, and at local events.

This entry has 14 replies

  1. Kohan Ikin says:

    This is awesome news, but will HID controller support also come to the Simulator as well soon? (ie So we can plug a gamepad into our Mac and use it to test our game in the Simulator, without having to build for the device every time we make a change?)

  2. Chris says:

    Sounds fantastic.
    What about Analog Sticks?
    Do we have a way to return the x/y (so we can calculate the angle that it’s facing)?

    • Dave Cheng says:

      Also curious about analog stick support. That would be awesome for the game I’m working on.

      • Rob Miracle says:

        Chris & Dave as we mentioned above, we will be covering axis support (analog stick, x, y, etc.) in a future post. This was was rather long as it was and I’ve just had my OUYA for a few days, so I’ve got to get a few more ducks in a row before I can write that up. The features are there in the Daily Build API docs

        http://docs.coronalabs.com/daily/api/

        These features should be rolling into the public build pretty soon as such the regular docs will be updated with the info. If you want to take a peek before we blog about it, you can look for “axis” under the Event’s section.

  3. Andrew says:

    This is FANTASTIC NEWS! Been looking forward to when Corona can build out to OUYA. Rob – this does mean that we’ll be looking forward to an update to your ultimate config and device detection code to include the configs/etc for OUYA. Do you happen to know when the next public release will be?

    • Rob Miracle says:

      Actually the existing Ultimate config.lua should handle the OUYA and GameStick just fine as is.

  4. Andrew says:

    Downloaded the Stable build today, and tried connecting my PS3 controller to my Mac to test this out, seemed like I had my controller connected to the Mac successfully, but couldn’t figure out how to get it working with Corona. Has anyone else done this successfully? If so how did you get it to work?

    • Rob Miracle says:

      Key/Axis support is unavaialble on the Mac simulator as well as iOS. You have to test it on an Android device that supports the controllers or from the Windows simulator.

      http://docs.coronalabs.com/api/event/key/index.html

      • Andrew says:

        Thanks Rob! Somewhat dampens the excitement of being able to test with a controller in the Simulator in Mac/Windows. Do you know if this is in the plan to support this in a future release? If not can you direct me to the feature request page, and I’ll submit the request.

        • Rob Miracle says:

          The Windows simulator does support it. This is not something supported in iOS and I’m unsure of why Mac support isn’t there. I’m pretty ignorant of the Mac OS-X SDK and what is or is not possible with it or how difficult it is to add in.

  5. Anton says:

    When will add support for keyboard control for mac simulator? Now it is very inconvenient to develop an application for android, ouya.

    Back in iOS 7 appeared maintain joysticks, whether you plan to add support?

  6. Philip Dijkstra says:

    How can i get this to work with the iCade (Core) ?

    • Rob Miracle says:

      Anton, we do support limited keyboard functionality on the OS-X simulator now. In fact there was a blog post last Tuesday about a way to use a Mac App to convert HID controller input to keystrokes that were compatible with code you might write for an OUYA.

      Philip, I looked up the iCade and it appears to just need Keyboard control. I don’t know if we have keyboard support for iOS yet or not.

      Rob

  7. Nick says:

    Does anyone else experience really bad frame rate drops when using OnKeyEvent heavily? I’m building an OUYA game and everytime a button is pressed, even if it doesn’t do anything, framerate drops to 10 or so. 🙁

Leave a reply

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">