Gamepad Module
#Gamepads, Axis & Button IDs

Both gamepads and buttons start with an index of 1. That is, the first detected gamepad had an ID of 1, and the first button on that gamepad has a button ID of 1.

Up to 16 gamepads are supported. Up to 32 buttons and 6 axis per gamepad are supported. Any gamepads you wish to read input from should be plugged in before starting a script in which you intend to use it for.

#Global variables

To make working with the POV hat (aka D-pad) a bit easier, a few variables have been added to global scope:

Global variableDescription
JOY_POVBACKWARDThe "Down" button; A value of 180
JOY_POVFORWARDThe "Up" button; A value of 0
JOY_POVCENTEREDNo direction; A value of 655
JOY_POVLEFTThe "Left" button; A value of 270
JOY_POVRIGHTThe "Right" button; A value of 90
#Controller Layouts

Every gamepa model will have it's own unique button & axis map. In modern times, Xbox and PlayStation controllers have become a bit of a standard for PC gaming, however there are thousands of USB gamepads that do not conform to any standard.

Unfortunately, this means that you will likely need to discover how buttons & axis are mapped for your gamepad if they are not a common and well-recognized controller. You may do this by conecting the gamepad and running the included 'keytest.lua' script. Once the script has been run, it will continue to dump information on any keys, mouse buttons, or gamepad inputs that it can detect.

For your convenience, details on a few gamepads will be detailed below.

XBox 360

Xbox 360 controller button map

XBox 360 controllers have a few quirks to them. First and foremost, it needs to be noted that the "Guide" button (that big round button in the center that usually as an XBox logo on it) does not actually trigger a gamepad button press, but rather a normal virtual key as if from a keyboard. Pressing the Guide button sends a vk up/down event for VK 0x07; according to Microsoft's documentation this VK code is "undefined."

The controller only has one POV-hat and responds with a number value that is consistent with gamepad.getPOV()'s documentation. The POV-hat will only give data at 45° resolution meaning it is only 8-directional.

The two analog sticks each have 2 axis while the left and right triggers share an axis. The left analog stick uses Axis 1 in the horizontal direction (0.0 = left, 100.0 = right) and Axis 2 in the vertical direction (0.0 = up, 100.0 = down) while the right analog stick uses Axis 5 for the horizontal direction and Axis 4 in the vertical direction. LT (left trigger) and RT (right trigger) share an axis (Axis 3) such that the right trigger only provides data in the 50.0 (unpressed state) to 0.0 (fully pressed state) range and the left trigger only provides data in the 50.0 (unpressed state) to 100.0 (fully pressed state) range.

NameIDValue(s)
POV-hat0-360 in 45° increments, or 655 (centered)
A10/1
B20/1
X30/1
Y40/1
LB50/1
RB60/1
Back/menu70/1
Start80/1
Left Analog (pressed)90/1
Right Analog (pressed)100/1
Left Analog - HorizontalAxis 10.0 - 100.0, left to right
Left Analog - VerticalAxis 20.0 - 100.0, top to bottom
LTAxis 350.0 - 100.0, unpressed to pressed
RTAxis 350.0 - 0.0, unpressed to pressed
Right Analog - HorizontalAxis 50.0 - 100.0, left to right
Right Analog - VerticalAxis 40.0 - 100.0, top to bottom
Guide0x070/1

Generic USB PS2-like

Note: Your specific generic USB PS2 gamepad may use different mappings.
You may test this using the keytest.lua script provided with MicroMacro.
PlayStation 2 controller button map

While a PS2-style gamepad may be more straight-forward than XBox 360 controllers, there is one slightly unusual thing: the analog toggle button. When this toggle is off, both analog sticks instead behave more like digital inputs and will instead result in values 0.0, ~50.0 (centered) or 100.0 rather than a linear progression from 0.0 to 100.0. They will act more like a POV-hat than analog input, however, it is important to note that they still output analog, dual-axis values. The analog button itself will not expose any output or be readable, therefor you will not receive any events for this button.

The controller only has one POV-hat and responds with a number value that is consistent with gamepad.getPOV()'s documentation. The POV-hat will only give data at 45° resolution meaning it is only 8-directional.

NameIDValue(s)
POV-hat0-360 in 45° increments, or 655 (centered)
Triangle10/1
Circle20/1
X30/1
Square40/1
L150/1
R160/1
L270/1
R280/1
Select90/1
Start100/1
Left Analog (pressed)110/1
Right Analog (pressed)120/1
Left Analog - HorizontalAxis 10.0 - 100.0, left to right
Left Analog - VerticalAxis 20.0 - 100.0, top to bottom
Right Analog - HorizontalAxis 30.0 - 100.0, left to right
Right Analog - VerticalAxis 40.0 - 100.0, top to bottom

Nintendo Switch JoyCons

There are a number of limitations in place due to the default Windows driver. Using an alternative driver, such as mfosse's JoyCon-Driver will allow more advanced controls (accelerometer data, precise joystick data, etc.) as well as pairing both joycons as a single device. The documentation provided here will be for the joycon behavior under the default Windows driver.

Known Quirks

  • When paired via Bluetooth to a PC, the joycon lights still flash rather than represent controller order.
  • Joysticks act more like 8-directional POV-hats rather than dual-axis controls.
  • Left and Right joycons will not combine to a singular device but instead behave as two separate controllers.
  • No accelerometer/gyro data is provided.
Switch JoyCon joystick diagram

Each JoyCon has a joystick, however, please note that it acts like an 8-directional POV-hat. The orientation for each JoyCon depends on whether it is a Left (L) or Right (R) JoyCon. Both follow a 0° to 315° range in the clockwise direction and both begin (0°) pointing towards the "inside" (where the Switch would be if they were directly connected) and are therefore opposite to each other. See the diagram for clarity.

Button Layout

Switch JoyCon layout diagram
Left JoyConRight JoyCon
NameIDValue(s)
POV-hat0-360 in 45° increments, or 655 (centered)
10/1
20/1
30/1
40/1
SL50/1
SR60/1
90/1
POV-hat (pressed)110/1
Capture140/1
L150/1
ZL160/1
NameIDValue(s)
POV-hat0-360 in 45° increments, or 655 (centered)
A10/1
X20/1
B30/1
Y40/1
SL50/1
SR60/1
+100/1
POV-hat (pressed)120/1
Home130/1
R150/1
ZR160/1
#gamepad.pressed boolean gamepad.pressed(number gamepadId, number buttonId)

If the given gamepad has had its button pressed since last polling, returns true. If the button has not been pressed since the last polling, this instead returns false.

You would only use this function to determine the initial impulse of a button being pressed. Use gamepad.isDown() to check if the button is currently in the "down" state (either the initial press or being held down).

While you may use this function in your main loop, it is probably better to rely on capturing the gamepadpressed event.

Example: if( gamepad.pressed(1, 2) ) then print("Button 2 on Gamepad 1 was pressed."); end
#gamepad.released boolean gamepad.released(number gamepadId, number buttonId)

This function works exactly like gamepad.pressed() except that it checks if the button has just been released.

While you may use this function in your main loop, it is probably better to rely on capturing the gamepadreleased event.

#gamepad.isDown boolean gamepad.isDown(number gamepadId, number buttonId)

If the given gamepad currently has the given button held down (as of last polling), this returns true. Otherwise, it returns false.

A button is considered "down" if this is the initial pressing of the button or if the button is still being held down.

#gamepad.getPOV number gamepad.getPOV(number gamepadId)

Returns the angle of the POV hat (D-pad). If centered, returns JOY_POVCENTERED(655°). This angle is in degrees with "up" being 0° and rotating in a clockwise fashion.

POV hat directional diagram
#gamepad.getAxis number gamepad.getAxis(number gamepadId, number axisId)

Returns the axis value for a given gamepad. The value will be between 0.0 (minimum) and 100.0(maximum). If centered, the value will be ~50.0.

This will not always be exact! Due to calibration, floating-point inaccuracies, and physical defects, you may receive a value that is a fraction off the intended value. I.e. ~49.0 - 51.0 while centered.

#gamepad.getCount number gamepad.getCount()

Returns the number of connected & detected gamepads. If your gamepad was not plugged-in when starting the script, it may not be detected and you should restart the script.

Page last updated at 2018-09-25 20:47:35


Copyright 2018