Pressing two 'action' inputs simultaneously?

Solution Here:

I have decided to post my solution in case anyone else wants it for their own purposes. I’m editing the OP so you don’t have to scroll down. I think my example is self-explanatory but if you need clarification then ask away.

I’m using a player controller, you don’t have to.

In PlayerController .h:


/* Input Window */
void InputWindow_AddInput(int32 flag);
void InputWindow_Tick();
void InputWindow_Process();	

/** Used for simultaneous action input */
float InputWindowTimer = 0.f;
float InputWindowTimerReset = 0.01f;
bool bInputProcessing = false;

/** Used for handling input window and button states */
int32 input_flags = 0;
TArray<int32> input_flags_used;

int32 input_flag_AttackA = 1;
int32 input_flag_AttackB = 2;
int32 input_flag_Special = 3;

In PlayerController .cpp:


void APC::InputWindow_AddInput(int32 flag)
{
	if (!input_flags_used.Contains(flag))
	{
		input_flags += flag;		
		input_flags_used.Add(flag);
	}

	if (!bInputProcessing)
	{
		InputWindowTimer = InputWindowTimerReset;
		bInputProcessing = true;
	}
}

void APC::InputWindow_Tick()
{
	if (bInputProcessing && input_flags <= 0)
	{
		bInputProcessing = false;
		InputWindowTimer = 0.f;
		input_flags_used.Empty();
		return;
	}

	if (InputWindowTimer > 0.f)
	{
		InputWindowTimer -= DT; // DT = Delta Time Variable
	}
	else if (bInputProcessing)
	{
		bInputProcessing = false;
		InputWindow_Process();
	}
}

void APC::InputWindow_Process()
{
	switch (input_flags)
	{
	case 1:
		CAQ(EAttackInput::M_AttackA);
		break;
	case 2:
		CAQ(EAttackInput::M_AttackB);
		break;
	case 3:
		if (input_flags_used.Num() >= 2) // Not needed for my case, just an example
			CAQ(EAttackInput::M_AttackAB);
		break;
	}

	input_flags = 0;
	input_flags_used.Empty();
}

Original Post:

Hey,

Lets say:
Y button = Attack 1
B button = Attack 2
Y+B Button = Attack 3

Pressing either Y or B will execute Attack 1 or 2, but if both are down I want to execute Attack 3.

At first I would set a boolean for whether the buttons are down or not and when either Y or B is pressed it’ll check if the other is down. This doesn’t work.

If neither is currently being pressed and the player wants to execute Attack 3, the split second difference between both buttons going down results in either Attack 1 or 2 being executed instead of Attack 3.

How do I solve this? I don’t want to put some sort of delay in here.

This is happenning because you are attaching immediate events to key inputs. That doesn’t work very well for fighting games.

Tekken does what you want by implementing ‘timed input windows’, if I may call it like that…
The input to be taken has a millisecs delay before taking any actions; each button pressed ads to a flag(int), and after the keypress window is closed, the action is taken. I.e:

While no press happens, Flag=0;

  • (ANY) Key press opens an input window.
  • (ANY) Key release closes it or a timer will close it anyway.

Let’s say each button instead of calling an action directly on press add(or remove on release) to the flag and no matter what button was pressed, the same action will be taken to evaluate what move must be performed based on the value the flag has after the input window is closed: X=1,Y=2,A=3,B=4;
Player pressed Y+B until the input window was closed; So no matter which button was pressed first, Flag=6(Y+B);

Than you do, after timed input window is closed, a check based on the Flag:

Switch(Flag)
Case 1:
–Perform Attack movement 1;
Case…

Case 6:
–Perform (Y+B) Attack movement 6;

‘Timed input window’ routines will ease many other aspecs of design as well, like making easier to compute and validate combos.

Thanks! I can see a few ways to go about it thanks to your post.

Need one thing clarified though. X = 1, Y = 3, A = 3

X + Y = 3 and also A = 3. Is it just a fault with the quick example or am I missing something here?

Edit: Since I have your attention I will also ask if you know what a generic time in milliseconds might be? Right now it’s at 10ms and feels alright just want to make sure I’m not way off target. Anyway, the system works! Thanks for your insight hopefully you can answer the questions, for now I just did a couple boolean toggles instead of flags since my system is still being fleshed out and doesn’t need anything over the top. Don’t need directional input atm since I’m going for Monster Hunter rather than a fighting game (did that a while ago! my combo system is a dumbed down version from that).

You can simply check with a bool if input is ‘composed’… The first key pressed, at this case X or Y, always gives its value (1 or 2) before you open the input window;
After the input time window is closed, if first input value = still the same (3), that means no other key was pressed thus you know that the input was a ‘pure A’ button press.
If flag value was anything != 3 before you open the input window that means the input can’t be a single button A pressed; you automatically knows it wasn’t a single button press, but was infact the only composed input capable of evaluating as “3”, at this case X+Y…

Anything under 10/60 is just fine; You keep in mind that joystick controllers and TV displays also have input delay themselves, when combined most of the time are not much, from 40~180ms usually. So for your input logic, adding 10~20ms is ok.

That makes sense. Thanks for clarifying :slight_smile:

I edited the original post with my solution in case anyone comes here from google or what not looking for the same answer.

Thanks again for your insight BrUnO!

Just to add to the flags values, you should probably use power of 2 values, so you have no situations where 2 completely different inputs result in the same value.
In the X=1, Y=2, A=3 example, X+Y=3 as well, but if you use X=1, Y=2 and A=4, then X+Y=3, X+Y+A=7 which would be different from B=8 and so on.

I’d like to ask a question regarding that solution as well: can the “input window” result in any noticeable lag in control response? Would it be possible to start playing an animation as soon as a button is pressed, and then change this animation to another one if other buttons are pressed?

Thanks for the tip! Should be more efficient that way, I’ll try it.

The lag is completely unnoticeable until values well above what you would require. Switching animation is something I considered but it’s unnecessary when you can just do a system like this, and it’s a bunch of extra (pointless, at least in my case) work particularly with my combo system that it’s based on being complex enough already :wink:

Hmm quick question, using that array allows me to execute input on press instead of release which is better for action games because its faster response time. If I’m just using flags then pressing the button accumulates the flags.

How’d you handle that? Just keep the array for checking against?