Hi everyone, here's a video capture of the experimental gamepad support.
http://www.youtube.com/watch?v=uMx-QJfxGV8
(I know, doesn't look like a game, nothing significant is happening, no hero jumping over ennemies, sorry I didn't want to migrate my experiments to something else yet)
Before explaining, I'll ask for your help.
To include this in the next CE release I will need testers.
'Multi-player' is supported and I was able to plug in two different devices and have my GamepagManager manage them both, applying custom mapping to each one by reading the GameInputDevice name and assuming that if it reads "Xbox 360" it would load up the according map - or else load a default map I can decide. (its unclear if this would work nicely yet. only assumptions.
Anyway please sign up if you'd like to help.
read on if you need more info, or stop there.
This test was made using an xbox controller under windows so I've had no problem figuring things out, the only map I have is like custom made for myself so of course I cannot say if it will work for everyone or not.
I've used this document :
https://docs.google.com/spreadsheet/ccc?key=0AkkprH0hOE5cdGpmeDVTVFQ5M0syOGdXZ0xjVDJkSnc&usp=sharing#gid=1
I can't however test on MAC , linux or ouya.
nor do I have access to these other types of controllers for testing,
So I can implement the mappings mentioned on this spreadsheet - but can only assume that it would work without any proof.
If anyone is willing to help with testing then, please raise your controllers!
creating custom maps or understanding them will be very easy anyway (I tried to make this easy for everyone).
I'm reading Capabilities.version to initialize a map according to the platform Air is running in as that spreadsheet led me to think the windows/xbox360controller map would simply work differently on linux or map anyway.
As the gamepad manager sees a new device is added, it reads all controls, loads up either a default map you specify or fetch it from the CE package - I would very much like the developers to have all possible maps already done for them so that all this gets sorted out automatically.
each button or stick, becomes a custom InputController.
each newly added controller gets the next available input channel - you could set up two Hero, have each listen to a different channel and control them separately, keyboard or gamepad or virtual joystick or anything else you want, the input system after all, was created for just that in mind.
As any InputController, actions that are going to be triggered can be changed at any time for your player to be able to remap however he likes as long as you provide him with a menu to do so.
So here's how a 'map' looks like :
package citrus.input.controllers.gamepad.maps
{
import citrus.input.controllers.gamepad.controls.StickControl;
import citrus.input.controllers.gamepad.Gamepad;
public class Xbox360GamepadMap extends GamePadMap
{
public function Xbox360GamepadMap():void
{
}
override public function setupWIN():void
{
var joy:StickControl;
joy = _gamepad.registerStick(GamePadMap.STICK_LEFT,"AXIS_1", "AXIS_0");
joy.invertY = true; // AXIS_1 is inverted
joy.threshold = 0.2;
joy = _gamepad.registerStick(GamePadMap.STICK_RIGHT,"AXIS_3", "AXIS_2");
joy.invertY = true; // AXIS_3 is inverted
joy.threshold = 0.2;
_gamepad.registerButton(GamePadMap.L1,"BUTTON_8");
_gamepad.registerButton(GamePadMap.R1, "BUTTON_9");
_gamepad.registerButton(GamePadMap.L2, "BUTTON_10");
_gamepad.registerButton(GamePadMap.R2, "BUTTON_11");
_gamepad.registerButton(GamePadMap.L3, "BUTTON_14");
_gamepad.registerButton(GamePadMap.R3, "BUTTON_15");
_gamepad.registerButton(GamePadMap.SELECT, "BUTTON_12");
_gamepad.registerButton(GamePadMap.START, "BUTTON_13");
_gamepad.registerButton(GamePadMap.DPAD_UP,"BUTTON_16","up");
_gamepad.registerButton(GamePadMap.DPAD_DOWN,"BUTTON_17","down");
_gamepad.registerButton(GamePadMap.DPAD_RIGHT,"BUTTON_19","right");
_gamepad.registerButton(GamePadMap.DPAD_LEFT,"BUTTON_18","left");
_gamepad.registerButton(GamePadMap.BUTTON_TOP, "BUTTON_7");
_gamepad.registerButton(GamePadMap.BUTTON_RIGHT, "BUTTON_5");
_gamepad.registerButton(GamePadMap.BUTTON_BOTTOM, "BUTTON_4");
_gamepad.registerButton(GamePadMap.BUTTON_LEFT, "BUTTON_6");
}
}
}
setupWIN is called on a GamepadMap along with the GamePad object, when Capabilities.version 's 3 first chars are WIN of course. - I can add , the same way I do here, the mapping for MAC, LNX, AND by creating setupMAC, setupLNX and so on - I will just need you to test that out.
In my Main.as, before starting my state... I do the following to set up my custom actions for my "game":
var gamePadManager:GamePadManager = new GamePadManager(2, FreeboxGamepadMap); //2 players max, FreeboxGamepadMap will be the default map if nothing else found. this is the map of my other cheap controllers.
gamePadManager.onControllerAdded.add(function(gamepad:Gamepad):void
{
gamepad.setStickActions(GamePadMap.STICK_LEFT, "up", "right", "down", "left");
gamepad.setStickActions(GamePadMap.STICK_RIGHT, "zoomIncam", "rotateCam+", "zoomOutcam", "rotateCam-");
gamepad.setButtonAction(GamePadMap.L1, "rotateCam-");
gamepad.setButtonAction(GamePadMap.R1, "rotateCam+");
gamepad.setButtonAction(GamePadMap.L2, "zoomOutcam");
gamepad.setButtonAction(GamePadMap.R2, "zoomIncam");
gamepad.setButtonAction(GamePadMap.L3, "addPoint");
gamepad.setButtonAction(GamePadMap.BUTTON_BOTTOM, "addPoint");
gamepad.setButtonAction(GamePadMap.BUTTON_RIGHT, "removePoint");
gamepad.setButtonAction(GamePadMap.START, "start");
gamepad.setButtonAction(GamePadMap.SELECT, "select");
gamepad.debug = true;
});
I so easily setup action for button or sticks.
This is done through a signal as there are some time before devices are actually attached (a second or so).
In the video, its mostly about navigation by moving the camera's target, rotating the camera or zooming in/out.
There's also that addPoint/removePoint because the state is a Qtree implementation test.
The gamepad overlay you see on screen has not been edited over. IT IS IN GAME - and I will probably give that system to you as well for debugging or visualizing stuff.
here's the "gamepad debug view hardcore code"; note that the graphic + all the buttons lighting up are in a .swc I'd be glad to share.
//in update
var gamePad:Gamepad = GamePadManager.getInstance().getGamePadAt(0); //trying to get game pad of channel 0 (not available until properly added)
if (!gamePad)
{
gamepadlayout.alpha = 0;
return;
}
gamepadlayout.alpha = 0.7;
gamepadlayout.L1.alpha = gamePad.getButton(GamePadMap.L1).value;
gamepadlayout.R1.alpha = gamePad.getButton(GamePadMap.R1).value;
gamepadlayout.L2.alpha = gamePad.getButton(GamePadMap.L2).value;
gamepadlayout.R2.alpha = gamePad.getButton(GamePadMap.R2).value;
gamepadlayout.L3.alpha = gamePad.getButton(GamePadMap.L3).value;
gamepadlayout.R3.alpha = gamePad.getButton(GamePadMap.R3).value;
gamepadlayout.SELECT.alpha = gamePad.getButton(GamePadMap.SELECT).value;
gamepadlayout.START.alpha = gamePad.getButton(GamePadMap.START).value;
gamepadlayout.BUTTON_TOP.alpha = gamePad.getButton(GamePadMap.BUTTON_TOP).value;
gamepadlayout.BUTTON_BOTTOM.alpha = gamePad.getButton(GamePadMap.BUTTON_BOTTOM).value;
gamepadlayout.BUTTON_LEFT.alpha = gamePad.getButton(GamePadMap.BUTTON_LEFT).value;
gamepadlayout.BUTTON_RIGHT.alpha = gamePad.getButton(GamePadMap.BUTTON_RIGHT).value;
gamepadlayout.DPAD_UP.alpha = gamePad.getButton(GamePadMap.DPAD_UP).value;
gamepadlayout.DPAD_DOWN.alpha = gamePad.getButton(GamePadMap.DPAD_DOWN).value;
gamepadlayout.DPAD_LEFT.alpha = gamePad.getButton(GamePadMap.DPAD_LEFT).value;
gamepadlayout.DPAD_RIGHT.alpha = gamePad.getButton(GamePadMap.DPAD_RIGHT).value;
gamepadlayout.LEFT_STICK_POINTER.alpha = gamePad.getStick(GamePadMap.STICK_LEFT).length;
gamepadlayout.LEFT_STICK_POINTER.rotation = gamePad.getStick(GamePadMap.STICK_LEFT).angle * 180 / Math.PI + 90;
gamepadlayout.RIGHT_STICK_POINTER.alpha = gamePad.getStick(GamePadMap.STICK_RIGHT).length;
gamepadlayout.RIGHT_STICK_POINTER.rotation = gamePad.getStick(GamePadMap.STICK_RIGHT).angle * 180 / Math.PI + 90;
So what you can see from that is the simplicity to get values from controllers using their names - and the sticks provide us with angle and length (they also trigger actions when they are up/down/left/right with analog values of course.
Anyway I hope that's exciting , a bit.
I'll just need people to confirm things are working with other gamepads and platforms I'm not able to test on for the community to have a tool as complete as possible.
I'll provide a full test state source code with the gamepad overlay for debugging, no worries!
Edit 1:
using the latest source code, you can already try :
//Main.as
import citrus.input.controllers.gamepad.GamePadManager;
import citrus.input.controllers.gamepad.Gamepad;
import citrus.input.controllers.gamepad.maps.GamePadMap;
var gamePadManager:GamePadManager = new GamePadManager(2, null);
gamePadManager.onControllerAdded.add(function(gamepad:Gamepad):void
{
gamepad.setStickActions(GamePadMap.STICK_LEFT, "up", "right", "down", "left");
gamepad.setButtonAction(GamePadMap.BUTTON_BOTTOM, "jump");
});
and the first added controller should be able to control your hero.