Today’s guest tutorial is authored by Jason Schroeder, a Corona Ambassador who has been developing mobile apps since 2011. His 2012 app Chungaboo Language Series was a Corona App of the Week and achieved What’s Hot status in several international App Stores. His second collaboration with the Austin, TX-based Chungaboo, Spanish School Bus for Kids, is currently pending approval for Apple’s App Store and will be released for Android later this month. Jason lives in New York city with his wife Leslie and their beautiful 6-month old twins. Follow Jason on Twitter: @schroederapps.
I finally got around to purchasing an OUYA last week, thrilled by the possibility of creating the sort of controller-driven games I enjoyed back in the halcyon days of the NES and Sega Master System. I’ve only had a few hours of hands-on time with the OUYA, but so far I’m impressed. The hardware seems solid, the interface runs smoothly, and of course, since Corona has built-in support for OUYA and its controller using the “key events” API, I’m well-positioned to create the next OUYA runaway hit!
I do all of my development work on a Mac, and the Corona Simulator does not currently support controller input like it does on Windows (OS X is generally not very “joystick-friendly”). So, to properly test changes to my OUYA-targeted games, I’d typically need to create a build, transfer the APK to the OUYA, move from my computer to my TV, and pray that there isn’t some silly little bug in my code that requires me to start the entire process over. One of my favorite things about Corona is that I can see changes in my code reflected instantly in the simulator — but it seems this isn’t possible if I want to use a controller. What to do?
Introducing the “simulatorController” Library
Another thing I like about Corona is that the SDK is flexible enough to allow us to “code around” issues like this controller conundrum. There is a proud tradition in the Corona community of developers sharing libraries to expand the SDK’s functionality — Director Class being one of the most recognized. In that tradition, I sat down and whipped up a simulatorController library that adds Mac Simulator support for USB or Bluetooth controllers with just one line of code!
Before you start using simulatorController, here are a few quick notes:
- If you use Corona for Windows, you don’t even need it!
- You must be a Corona Pro subscriber using a daily build later than #1217, because that’s when keyboard and mouse events were first made available in the Mac Simulator.
- You will need a properly-configured controller mapping application (more on that below).
- It will not work with your controller’s analog sticks (although it will detect when you click them straight down).
- The library should work with any standard HID (Human Interface Device) controller. However, pairing an OUYA controller with a Mac results in your mouse pointer drifting endlessly to one corner of the screen, rendering the mouse somewhat useless. There are unofficial drivers floating around that claim to fix this, but you should use them at your own risk. I personally use a PS3 controller via Bluetooth and it works great.
How it Works
Before we get into the code of the simulatorController library, I recommend that you read the Introduction to Game Controllers tutorial. Not only does it provide a great explanation of how Corona handles controller input, but it features a terrific sample event handler function that plays nice with my simulatorController library.
The way simulatorController works is by capturing keyboard keystrokes and translating them into the same Runtime “key” events generated by a game controller — and those simulated Runtime events are captured by the onKeyEvent() function from the tutorial (or your own controller listener function if you write a custom one). What you do from that point is entirely up to you, but the good news is that if you’re already using the demo listener function to handle controller inputs, all you need to do is drop simulatorController.lua into your project’s root folder and require() it inside main.lua:
simulatorController = require( "simulatorController" )
With this in place, we need a little help from a controller mapping application. There are plenty of them available, but I use Joystick Mapper which does the job nicely and is affordable ($4.99 in the Mac App Store). Joystick Mapper converts controller button presses into keystrokes which are then “intercepted” by simulatorController and passed onward as controller inputs to your simulated Corona app. Remember that your Simulator window must have focus and be the “active” application in OS X, or the keystrokes will not be passed to nor reported by the Simulator.
Configuring Joystick Mapper is a simple process of pressing the buttons on your controller one at a time and assigning a keystroke to each button. I’ve created a handy-dandy preset file which you can download and copy into the Joystick Mapper “Presets” folder, but if you really want to map the buttons yourself, here are the default keystroke configurations for simulatorController:
|Controller Button||Mapped Keystroke|
|Button A (O on OUYA, X on PS3)||a|
|Button B (A on OUYA, circle on PS3)||b|
|Button X (U on OUYA, square on PS3)||x|
|Button Y (Y on OUYA, triangle on PS3)||y|
|Mode (OUYA/PS3 logo button)||0|
|L1 Shoulder Button 1||6|
|L2 Shoulder Button 2||7|
|R1 Shoulder Button 1||8|
|R2 Shoulder Button 2||9|
|L3 Left Analog Click||l|
|R3 Right Analog Click||r|
|Select Button||[ (left bracket)|
|Start Button||] (right bracket)|
Once you require the simulatorController library into your project, it will run silently in the background, capture keystrokes from your keyboard or controller, and translate them into HID key events. In addition, I have included a couple of functions which you can call to adjust things on the fly:
- simulatorController:disable() — this function stops controller input from reaching your app, as if the controller is unplugged.
- simulatorController:enable() — this function restores controller input to your app, as if the controller is plugged in.
- simulatorController:show() — this function puts a visual indicator on the screen whenever you press a controller button so you can confirm that it’s working.
- simulatorController:hide() — this function hides the visual indicator if you had previously turned it on.
The Library Code
You don’t need to delve into the library’s code to use it, but I invite you to open it, pick it apart, or even make improvements to share with the community. It’s not an especially complicated chunk of code and hopefully it’s organized well enough to speak for itself. I’m making the code available under the standard MIT license, so use it as you wish.
I created a very basic sample project so you can see the library at work in the Simulator. This sample is just the library and a main.lua file. It draws a square in the center of the screen that can be moved using the D-Pad. Pressing any other button changes the square’s color at random. It’s not much to look at, but it beats having to build for the device just to test an actual controller.
I hope that some of you can use this library to speed up your development pace while creating apps for the OUYA or other controller-driven environments. As I write this, there are just over 500 games available for OUYA, so now is the time for developers to enter that marketplace — before it becomes as saturated as the larger app stores. Imagine the competitive edge you’ll have!