Adobe AIR/Flash GameInput API (Getting Started)

Update (May 29, 2016):
emmett butler has an even more thorough post on the topic here, NativeJoystick in Bum Rush

I suggest starting with that since his post is a lot more in depth.

I had been emailed about this issue (problems with GameInput) and gave some links that I thought helpful at the time I was working with controllers. Here they are in the event they can help others:

* NativeJoystick: AIR “ANE” extension to support all joysticks that Windows can.
* Topic: NativeJoystick: AIR “ANE” extension to support all joysticks that Windows can.
* Joystick Library for Adobe AIR
* GamePad
* AS3 Controller Input
* Citrus-Engine/src/citrus/input/controllers/
* GameInputDevice Support…

I was also looking into sockets, or something like http://www.bytearray.org/?p=1268

It has been a while since I worked with this, and there are problems (various use cases). It still seems the best to make your own solution (ane)… but good luck. Here’s my post:

Adobe AIR/Flash GameInput API (Getting Started)

For starters I’m on a Mac so getting 2+ Xbox 360 controllers to work is already quite a challenge (I documented how to do this here). Apparently PlayStation is a lot easier, and as this site indicates:

“Note that for modern versions of Mac OS X there is a PS3 driver built into the OS and this driver is not required.”

Once I managed to get multiple 360 controllers hooked up properly (link again), I started digging around for how to do this thing.

Reading the docs and Game controllers on Adobe AIR wasn’t clear enough for me (seemed a bit convoluted, or I just say that because it was late at night).
I couldn’t get it to work at first. I thought it was because I didn’t set up the Xbox controller right (Mac insecurities), but after some digging I found that PC users have some of the same issues.
There is also a wonderful code snippet in this post here that can get you started right away in testing… just so you see another number but 0 for numDevices.
Like the devnet article suggests you have to add the listeners DEVICE_ADDED, DEVICE_REMOVED, DEVICE_UNUSABLE to your GameInput instance for it to work properly.
I had a phase where numDevices was constantly returning 0. Apparently unplugging and re-plugging in the controller can fix this. In my case I restarted the computer and then it worked.
If you’re like me you want some code samples, just to get a general understanding of what needs to be done. Unfortunately these are terribly lacking in Adobe’s documentation, but I found the following to be very helpful.
zehfernando has a wonderful example in plain common english here. Update: The project has been moved here.
This post (here) I also found very helpful (gives you an idea of what you need to do).
And this post here finally eliminated any further confusion for me.
The last two code samples in the .jp sites are very self-explanatory.

I also quickly put this sample together to give anybody (maybe Google-ing) a general idea of all the info you can capture with this…

import flash.ui.GameInput;

//quick through-together copy & paste test

var gameInput = new GameInput();

gameInput.addEventListener(GameInputEvent.DEVICE_ADDED, GIE_added);
gameInput.addEventListener(GameInputEvent.DEVICE_REMOVED, GIE_onRemoved);
gameInput.addEventListener(GameInputEvent.DEVICE_UNUSABLE, GIE_unusable);

var device:GameInputDevice;
var control:GameInputControl;


function GIE_added(gameInputEvent:GameInputEvent) {
	//
	trace("Controller Added! GameInput.numDevices is " + GameInput.numDevices);
	//
	trace("GameInput.getDeviceAt(0): "+GameInput.getDeviceAt(0));
	//Controller #1 - lazy test
	device = GameInput.getDeviceAt(0);
	//get all the buttons (loop through number of controls) and add the on change listener
	//this indicates if a button pressed, and gets the value...
	for(var i:Number = 0; i<device.numControls; ++i){
		control = device.getControlAt(i);
		control.addEventListener(Event.CHANGE, GIE_onChange);//capture change
		//what buttons does it have (names)
		trace("CONTROLS: "+control.id);
	}
	//set to enabled
	device.enabled = true;
	//return info
	trace("device.enabled - " + device.enabled); 
	trace("device.id - " + device.id); 
	trace("device.name - " + device.name); 
	trace("device.numControls - " + device.numControls); 
	trace("device.sampleInterval - " + device.sampleInterval); 
	trace("device.MAX_BUFFER - " + GameInputDevice.MAX_BUFFER_SIZE);
	trace("device.numControls - " + device.numControls);
}

function GIE_onChange(event:Event){
	var control:GameInputControl = event.target as GameInputControl;
	//To get the value of the press you can use .value, or minValue and maxValue for on/off
	//var num_val:Number = control.value;
	//
	//constant stream (Axis is very sensitive)
	//trace("control.id=" + control.id);
	//trace("control.value=" + control.value + " (" + control.minValue+" .. " + control.maxValue+")");
	//
	//trace just on/off to see each button
	if(control.value >= control.maxValue){
		trace("control.id=" + control.id +" has been pressed");
	}
}

function GIE_onRemoved(gameInputEvent: GameInputEvent){
	//detects if you unplugged it
	trace("Controller Removed.");
	trace("GameInput.numDevices: " + GameInput.numDevices);
}

function GIE_unusable(gameInputEvent: GameInputEvent){
	//throw error now...
	trace("Controller Unusable.");
	trace("GameInput.numDevices: " + GameInput.numDevices);
}

Although the GameInputController is not exclusive to AIR anymore, and will “work” (with mixed results) in the browser (from my testing it is perfect in AIR, works in Firefox, but not Crome or Safari).
Also from my reading there are some caveats to running this in the browser, I quote from a helpful answer at stackoverflow:

Not all devices work; some fringe devices may get ignored by Flash.

Sometimes the addition of devices that are supported don’t really work – you may have to disconnect and reconnect them to get them to work.

Sometimes when using multiple controllers of the same type they get mixed up and only one of them will work.

Actual reported control ids vary between the Plugin/ActiveX version of Flash (Firefox/Safari/IE/etc) and Pepper (Chrome).

You usually need to press a button with the proper SWF focused for the GameInputDevice to be detected and reported.

There is also a spreadsheet of known GameInput controls here (not that old too), via this post.

After having found this on github I found zehfernando KeyActionBinder project. It’s a very impressive one, and seems to have solved many of the problems I see I will have.
It will work on Mac/Windows.

There is also Airxbc, but this is Windows only.

I also found James Dean Palmer Gamepad classes.

Although I like zehfernando’s project better from all the others. I recommend that one. His blog posts about his project where a trove of helpful information so I recommend anybody new to this to dive in and start digging at his website.
I got it running in no time, and it was very straightforward.

Update: the as3 version of key-action-binder is here. It is old, so if you intend to use it you will have to update the json file else it will not work with Windows. Alternatively, I have found out that you can use any javascript version with your actionscript project and it will work good too, so this is worth taking into consideration.

Ok… now to start making my 2 player+ game…