flixel
flixel copied to clipboard
GamePad input not reset when entering substate
- Haxe version: 4.0.5
- Flixel version: latest
- OpenFL version: latest
- Lime version: latest
- Affected targets: Neko, Windows, HTML5...
Code snippet reproducing the issue:
PlayState.hx
import flixel.FlxSubState;
import flixel.FlxG;
import flixel.FlxState;
class PlayState extends FlxState
{
override public function create():Void
{
super.create();
}
override public function update(elapsed:Float):Void
{
super.update(elapsed);
if (FlxG.keys.anyJustPressed([ENTER]) || (FlxG.gamepads.lastActive != null && FlxG.gamepads.lastActive.justPressed.START)) {
openSubState(new PauseSubState());
}
}
}
class PauseSubState extends FlxSubState
{
override public function create():Void
{
super.create();
openCallback = () -> trace("ENTERING PAUSE STATE");
closeCallback = () -> trace("EXITING PAUSE STATE");
}
override public function update(elapsed:Float) {
super.update(elapsed);
if (FlxG.gamepads.lastActive.anyJustPressed([START])) trace("START BUTTON IS STILL PRESSED");
if (FlxG.keys.anyJustPressed([ENTER]) || (FlxG.gamepads.lastActive != null && FlxG.gamepads.lastActive.justPressed.START)) {
close();
}
}
}
Observed behavior: GamePads input is not reset when entering substate
Expected behavior: GamePad input should be reset, so it would not trigger substate close. Keyboard works as expected.
It seems that gamepad IS reset when entering substate, but something triggers the input after one update loop.
If I add trace(FlxG.gamepads.lastActive.checkStatus(START, JUST_PRESSED)); inside the substate update function we can see that it is correctly false, but it becomes true in the next update.
Maybe this can put someone on the right track.
I'm running into this same issue too, and I haven't come up with a good solution or workaround. I can confirm it's happening just for gamepad and not keyboard too. I'll share any updates or solutions I find as I continue to dig into this, as it's blocking my current project from progressing.
I was curious if this issue is specific to substates or all states, so I put together this simple test using just normal FlxStates that exhibits the same issue:
package;
import flixel.FlxG;
import flixel.FlxState;
import flixel.text.FlxText;
class PlayState extends FlxState
{
override public function create()
{
super.create();
add(new FlxText(0, 0, 0, "PlayState"));
}
override public function update(elapsed:Float)
{
super.update(elapsed);
if (FlxG.gamepads.lastActive.justPressed.A)
{
trace("Gamepad A just pressed");
}
if (FlxG.keys.justPressed.A)
{
trace("Keyboard A just pressed");
}
if (FlxG.gamepads.lastActive.justPressed.A || FlxG.keys.justPressed.A)
FlxG.switchState(new OtherState());
}
}
package;
import flixel.FlxG;
import flixel.FlxState;
import flixel.text.FlxText;
class OtherState extends FlxState
{
override public function create()
{
super.create();
add(new FlxText(0, 0, 0, "OtherState"));
}
override public function update(elapsed:Float)
{
super.update(elapsed);
if (FlxG.gamepads.lastActive.justPressed.A)
{
trace("A just pressed");
}
if (FlxG.keys.justPressed.A)
{
trace("Keyboard A just pressed");
}
if (FlxG.gamepads.lastActive.justPressed.A || FlxG.keys.justPressed.A)
FlxG.switchState(new PlayState());
}
}
When pressing and releasing the A key on the keyboard, it switches the state once to the other, which is great and expected.
But when pressing and releasing the A key on the gamepad, it switches twice or more, which is the bug that I've been seeing in my project.
Just a reckon, but it seems like the releasing of the button on the gamepad lasts a bit longer than the keyboard, so after the state switches, it's reset for a couple frames, but it still catches the button being pressed before it's released, just returning true for FlxG.gamepads.lastActive.justPressed.A.
It seems like adding some timer-based delays when opening states or substates to let the gamepad button fully release would help alleviate the issue, like with a fade. I'm not sure of a way to fix it so that justPressed gets properly reset when switching states otherwise...
One quick solution in the meantime that I've been using is instead checking justReleased instead, since that's more reliable of a check, e.g. FlxG.gamepads.lastActive.justReleased.A. That's working pretty well so far, but there's a brief delay I'm noticing between press & release, but I think that's potentially to be expected.
Anyway, hope this helps whomever may be experiencing some gamepad woes with justPressed.
Sorry for a third comment on this today, I'm being a bit noisy about all this. But I think I found a solution that works nicely for my needs...
I set FlxG.inputs.resetOnStateSwitch = false; in my Main.hx so that the reset doesn't happen, which means justPressed can work as intended because it never resets, thus not retriggering it for gamepads. I think there's some risk here with other checks in the states by not reseting all of the inputs, but so far, so good.
Edit with more details
- Source for this option: https://github.com/HaxeFlixel/flixel/blob/27960e3b66c8ebad0052973831960761971168fd/flixel/system/frontEnds/InputFrontEnd.hx#L14-L18
- API docs for this option: https://api.haxeflixel.com/flixel/system/frontEnds/InputFrontEnd.html