Gamepad is an abstraction of Adobe Air's GameInput API that tries to create a single consistent API with consistent cross-platform events for working with game conrollers. It has a number of advantages over the Adobe API:

  • Control names in GameInput have different names on different controllers and even the same controller on different systems may have different names. Gamepad normalizes these to an idealized gamepad (pictured below).
  • Normalizes the direction of controls (e.g., flipped Y).
  • Emulates digital controls when only analog is available.
  • Emulates analog controls when only digital is available.
  • Can emulate some controls when only keyboard events are available.
  • Lets you register a keyboard map as a controller.
  • Better device index tracking.
  • Support analog deadzone for controllers that drift around zero.
  • Simpler API.
  • Attempts to work around known bugs in GameInput.

And it preserves the nice features already found in GameInput:

  • Controller support for: XBox 360, PS3, PS4, Ouya
  • Platform support for: MAC, PC, Linux, Ouya, and Android
  • Support for multiple controllers

Event controls


  • LSTICK - left stick press (0/1)
  • LSTICK_X - left stick horizonal movement (0..1)
  • LSTICK_Y - left stick vertical movement (0..1)
  • RSTICK - left stick press (0/1)
  • RSTICK_X - left stick horizonal movement (0..1)
  • RSTICK_Y - left stick vertical movement (0..1)
  • D_UP - d-pad up (0/1)
  • D_LEFT - d-pad left (0/1)
  • D_RIGHT - d-pad right (0/1)
  • D_DOWN - d-pad down (0/1)
  • A_UP - action button up (0/1)
  • A_LEFT - action button left (0/1)
  • A_RIGHT - action button right (0/1)
  • A_DOWN - action button down (0/1)
  • LB - left button (0/1)
  • RB - right button (0/1)
  • LT - left trigger (0/1)
  • RT - right trigger (0/1)
  • LT_X - Analog left trigger (0..1)
  • RT_X - Analog right trigger (0..1)


Gamepad must be initialized immediately - preferably in your first class. This is to avoid bugs in Adobe's GameInput.

import bitmasq.Gamepad;



Once initialized, you can register ADDED, REMOVED and CHANGED event handlers.

import bitmasq.Gamepad;
import bitmasq.GamepadEvent;


  Gamepad.get().addEventListener(GamepadEvent.CHANGE, onChange);


private function onChange(event:GamepadEvent):void {
  if (event.control == Gamepad.D_LEFT && event.value == 1) {
     // move something left..

The class also supports a context stack so that you can push event handlers and then pop them off. Only listeners at the top of the stack get events. So you can do something like this:

gamepad.addEventLisener(GamepadEvent.CHANGE, CharacterHandler);


// Later on the character selects a button that activates the menu.
// This should disable the character controls and enable the menu
// controls.  We accomplish this by pushing the context and adding
// the menu handler.
gamepad.addEventListener(GamepadEvent.CHANGE, MenuHandler);


// Then when the character exits the menu.  We pop the context.
// The menu listener gets disconnected and the character listener
// is once again active.

You can also push an empty context to ignore user input and then pop that context when you are ready for user input again (like during an animation). Here's a Starling example that pushes a gamepad context, fades an image out and then restores the gamepad context.

    2.0, {
        alpha: 0.0,
        onComplete: function() {


You can find a full featured demonstration of Gamepad in the OuyaStarter4AS3 repository.


In general, the MENU button is a tricky beast - we can't always say which controller actually pressed it. If in doubt it will register as coming from the first controller. In some configurations we also map the START and/or BACK button to the MENU button.

In Windows 98, the Xbox controller maps LT and RT to a single control and is unreliable.


This work is copyright 2013 and may be redistributed under the terms of the Apache License, Version 2.0 available at: