In Corona, creating apps with gamepad/joystick support is both easy and interactive. This guide outlines how the game controller APIs and events work together.
Game controllers are supported in the Corona Simulator for macOS or Windows, in Win32 desktop apps, and on Android devices.
Supported game controller(s). The Corona Simulator for macOS supports most game controllers, but some controllers require additional setup. Tested controllers include:
This guide accompanies the “Pew Pew!” sample app which utilizes all game controller APIs. You may download it from our GitHub repository.
The initial API to begin with is system.getInputDevices() which returns a list of all detected input devices. Note, however, the following differences between platforms:
Essentially, when an application starts, you can check if key bindings for a device are stored:
local inputDevices = system.getInputDevices() for i = 1,#inputDevices do local device = inputDevices[i] print( device.descriptor ) end
Effectively, each entry in the list returned by system.getInputDevices() is an instance of InputDevice. You can query this for information about the device, for example:
The object.descriptor property indicates the controller identifier during a session/run. If the same device is disconnected and later reconnected, it will have same descriptor
value, however this doesn’t mean that descriptor
will remain unchanged between sessions/runs. In a subsequent session/run, controllers are liable to have different descriptor
values.
The object.displayName of the device is reported by the operating system. You can display this so the user can identify which controller is being used.
You may also query the InputDevice object for its axes via the object:getAxes() method or cause it to vibrate with the object:vibrate() function. Please see the documentation for a complete list of properties and methods.
The inputDeviceStatus event is fired whenever a controller is connected or disconnected. The following example shows how to handle this event:
local function onInputDeviceStatusChanged( event ) if ( event.connectionStateChanged ) then if ( event.device.isConnected ) then -- Device has been connected else -- Connection has been lost end end end Runtime:addEventListener( "inputDeviceStatus", onInputDeviceStatusChanged )
Within the listener function, the event
table contains the following properties pertaining to the device which received a status change:
"inputDeviceStatus"
.Game controllers produce two types of events as a result of input: axis and key.
A key event’s event.device
property will be nil
on both macOS and Windows. It can also be nil
on Android if it came from a virtual input device such as the virtual keyboard.
The following example shows how to detect a specific controller. When either an axis
or key
event is triggered, the setDevice()
function is called which sets the event.device
and InputDevice displayName
.
local controller = { device="", displayName="" } --Predeclare local onKeyEvent local onAxisEvent local function setDevice( device, displayName ) -- Set current controller controller["device"] = device controller["displayName"] = displayName -- Remove event listeners Runtime:removeEventListener( "axis", onAxisEvent ) Runtime:removeEventListener( "key", onKeyEvent ) end function onKeyEvent( event ) setDevice( event.device, event.device.displayName ) end function onAxisEvent( event ) if ( math.abs(event.normalizedValue) > 0.5 ) then setDevice( event.device, event.device.displayName ) end end Runtime:addEventListener( "axis", onAxisEvent ) Runtime:addEventListener( "key", onKeyEvent )
In the above example, event.normalizedValue
for the onAxisEvent()
listener function is compared to 0.5
. This means that the axis is turned by a “readable” amount, or more than halfway through.
Some game controllers produce both axis
and key
events when analog triggers are pressed, so you may wish to conditionally handle this possibility.
Keys are handled with key events. Whenever the user presses a button on a gamepad/joystick or a key on the keyboard, this event is triggered. To identify which button/key was pressed, refer to the event.keyName documentation. Furthermore, when a key
event occurs, event.phase
will equal "down"
when the button/key is pressed down, or "up"
when the button/key is released.
The axis event fires any time the controller’s axis values change. This can result in a large amount of events, so game developers should consider accumulating the axis state. Each event has several useful properties:
axis
field.The usual workflow when dealing with axis
events is to accumulate values. In this approach, event.normalizedValue is typically most useful.
Like devices, an axis can provide useful information about itself. InputAxis tables are returned by object:getAxes() and axis in axis
events. Probably the most useful property is type which attempts to describe the utility of the axis.
Game controllers are supported in the Corona Simulator for macOS or Windows, in Win32 desktop apps, and on Android devices.
Game controller support can be implemented using the following events:
event.phase
of "down"
or "up"
for each button/key press.event.device
.
event.device
may be nil
.To list known game controllers, use the system.getInputDevices() function.
It’s wise to accumulate axis changes and take action later, for instance in the runtime "enterFrame"
listener, similar to the sample app method.