A simplified multi-device input manager tools for HaxeFlixel
Allows you to easily define all possible player actions, whether the action represents digital or analog data and what device inputs each action is mapped to, by default. As shown above, extending FlxControls causes macros to generate handy fields for each action.
Using the "Bare" sample as an example, UP
, DOWN
, LEFT
and RIGHT
are digital actions, as they are tied to things like gamepad buttons or keyboard keys. Digital actions create fields which can be used to check the status of actions, like so:
// same as controls.checkDigital(DOWN, PRESSED);
controls.pressed.DOWN
// same as controls.checkDigital(DOWN, JUST_PRESSED);
controls.justPressed.DOWN
// same as controls.checkDigital(DOWN, RELEASED);
controls.released.DOWN
// same as controls.checkDigital(DOWN, JUST_RELEASED);
controls.justReleased.DOWN
In addition to the typical digital input states, above, there is also a 5th event type called "hold repeat" which behaves similarly to typing. It fires when the action is first pressed, but after 0.5 seconds it will fire every 0.1 seconds. This is common behavior for menu navigation
// same as controls.checkDigital(DOWN, REPEAT);
controls.holdRepeat.DOWN
Actions can be tied to analog inputs as well, such as a joystick, a trigger or the mouse position. Using the "Bare" sample as an example, once again, MOVE
, LEFT_TRIGGER
and RIGHT_TRIGGER
are analog actions. Their values can be accessed like so:
// will be a value from 0.0 to 1.0
controls.TRIGGER_LEFT.value
controls.TRIGGER_RIGHT.value
// will be a value from -1.0 to 1.0 from the gamepad's analog stick,
// but can be higher or lower by moving the mouse fast enough
controls.MOVE.x
controls.MOVE.y
Four digital inputs can be used to create a 2D analog input, allowing keys like W,A,S and D to function similarly to a gamepad's joystick, where pressing them can set the corresponding x and y values to -1
or 1
. Similarly, 2 digital inputs can create a 1D analog input. Check out the "FlxCamera" demo for an example.
Just as 4 digital directional inputs can be used to create a 2D analog action, All 2D analog actions have 4 directional sub-actions. For instance say the action MOVE
is tied to a gamepad's joystick, when the stick is moved forward (making the y
value postive) controls.MOVE.pressed.up
will be true. Similarly, 1D actions will have up
and down
sub-actions.
Just like digital actions, these directional sub-actions have pressed
, released
, justPressed
, justReleased
and holdRepeat
fields
There are two ways to setup your control's default mapping: 1. Add the meta @:inputs([...])
to each value of your enum action. Each with an array of different inputs. Check out the "Bare" sample for an example 2. In your class extending FlxControls, define function getDefaultMappings():ActionMap<MyAction>
and have it return a map that links actions to an array of inputs. Check the "FlxCamera" sample for an example.
The aforementioned input arrays are very flexible, you can list any FlxKey
, FlxGamepadInputID
, FlxMouseButtonID
or FlxVirtualPadInputID
. Here are some examples for each input device:
- Keyboard: Can specify key inputs via
FlxKey.A
, or unique keys likeENTER
orH
can be used, unqualified, since there is no H input on any other device. Using aFlxKey
directly - like above - is short-hand forKeyboard(Lone(A))
, which is also acceptible. 2D multi-key analog inputs can be added viaKeyboard(Multi(W, S, D, A))
, though you can shorten this by using import aliases. There are also helpers for common directional keys, likeWASD
andKeyboard(Arrows)
- Gamepad: Can specify gamepad inputs via
FlxGamepadInputID.A
, or unqique things likeDPAD_UP
can be used, unqualified. Using aFlxGamepadInputID
directly - like above - is short-hand forGamepad(Lone(A))
, which is also acceptible. 2D multi-button analog inputs can be added viaGamepad(Multi(Y, A, B, X))
, though you can shorten this by using import aliases. There are also helpers for common directional buttons, likeDPAD
andFACE
(AKA: ABXY buttons) - Mouse: Can specify button inputs via
FlxMouseButtonID.LEFT
, orMIDDLE
can be used, unqualified. Using aFlxMouseButtonID
directly - like above - is short-hand forMouse(Lone(LEFT))
, which is also acceptible. Analog mouse inputs are specified viaMouse(Position())
,Mouse(Motion())
,Mouse(Drag())
orMouse(Wheel())
. Some of these allow you to specify a single axis (2D is the default) and a scale, in addition to other properties - Virtual Pad: Virtual pad inputs behave identical to Keyboard inputs, but with
FlxVirtualPadInputID
values rather thanFlxKey
. It also has a helper for analogArrows
FlxControls
supports re-mapping inputs using the add
and remove
methods, which take the target action and an input which is specfied the same way they were in the default map. Currently, there is no built-in save system or helper for re-mapped controls. You'll need to make that yourself as well as any UI for allowing the user to remap controls, but both of these are planned.
You can make multiple instances of FlxControls
where each instance uses a different gamepad. By default FlxControls
uses all connected gamepads. Use setGamepadID(FIRST_ACTIVE)
or setGamepadID(myGamepad.id)
to use a single gamepad. Currently, there is no way to make the keyboard and/or mouse only work for one instance without specifically removing each input of that device, though, a per device toggle is planned.
To get a list of strings that represent each input tied to a specific action, use listInputLabelsFor(MyAction)
and if desired, specify a device to limit this list. To get the labels for whichever device is actively being used, use controls.listInputLabelsFor(MyAction, controls.lastActiveDevice)
. For gamepads the label returned will actually be the specific label of that gamepad model, not just the generic gamepad input id. Non-english keyboards will return the label of whatever key is located there on the English equivalent. In the future, it's planned to actually get the label of that key based on your keyboards layout. For multi input analog inputs a string containing all the inputs is returned.
If using Flixel 5.9.0, there is a listMappedInputsFor
method, which, instead of returning labels, it returns an enum containing every possible input from every possible device. For gamepads it will use identifiers such as WII_REMOTE(A)
or PS4(SQUARE)
. For keyboard, The Result looks very similar to the input mappings passed in, for "Multi button" analog inputs like Face
, the result is something like:
Gamepad(Multi([PS4(TRIANGLE), PS4(X), PS4(CIRCLE), PS4(SQUARE)]))
These ids can be used to create custom labels or display a specific image of that input.
Action groups allow you to specify which actions cannot share inputs. This is useful for actions with opposing purposes, like accept vs cancel or up vs down. This can be very important for games that let the user remap controls.
Simply call addGroup
to create a new action group, alternatively you can override the initGroups
method in your extending controls class to set the groups directly. The last and perhaps easiest way to assign groups is to use the @:group("tag-name-here")
tag on your Action enum fields.
To get a list of every conflict in the current setup, use the checkAllGroupConflicts
method, or the checkGroupConflicts
method for checking a single group. If possible conflicts should be prevented before being added via the listConflictingActions
or addIfValid
methods. By design, the add
method does nothing to prevent conflicts, and the default mappings are not checked for validity, but you can use the compile flag FlxControls.checkConflictingDefaults
to enable this, meaning conflicts with the default mapping will throw an error at runtime.
- Schema for saving input mappings
- Example input remapping UI
- Add way to disable keyboard and mouse for specific instances of
FlxControls
- Add way to get key labels for non-english keyboards
- Map each
FlxControlMappedInput
to an image in Kenney's input prompts Add groups- Add custom analog action