Detect button press/release and disable inputs when they trigger a sequence

This commit is contained in:
Kevin Poretti 2023-07-01 16:18:09 -04:00
parent 9f16901de6
commit b8fa341503
2 changed files with 63 additions and 13 deletions

View File

@ -12,28 +12,54 @@ void UFFInputBufferComponent::AddInput(const FFFInputState& InputState)
InputBuffer.ForcePush(InputState);
}
bool UFFInputBufferComponent::CheckInputSequence(const FFFInputCondition& InputCondition)
bool UFFInputBufferComponent::CheckInputSequence(const FFFInputSequence& InputSequence)
{
int CondIdx = InputCondition.Sequence.Num() - 1;
int CondIdx = InputSequence.Sequence.Num() - 1;
int FramesSinceValidInput = 0;
for(int InpIdx = 0; InpIdx < InputBuffer.Num(); InpIdx++)
for(int InpIdx = 0; InpIdx < InputBuffer.Num() - 1; InpIdx++)
{
int32 CurrCondition = InputCondition.Sequence[CondIdx].Buttons;
int32 ThisInput = InputBuffer[InpIdx].Buttons;
if(ThisInput & CurrCondition)
int32 RequiredButtons = InputSequence.Sequence[CondIdx].RequiredButtons;
EFFButtonState RequiredButtonState = InputSequence.Sequence[CondIdx].RequiredButtonState;
int32 PrevInput = InputBuffer[InpIdx + 1].Buttons;
int32 CurrInput = InputBuffer[InpIdx].Buttons;
int32 PrevDisable = InputBuffer[InpIdx + 1].DisabledButtons;
int32 CurrDisable = InputBuffer[InpIdx].DisabledButtons;
switch (RequiredButtonState)
{
case EFFButtonState::BTNS_Pressed:
if(!(PrevInput & RequiredButtons | PrevDisable) &&
CurrInput & RequiredButtons & ~CurrDisable)
{
CondIdx--;
FramesSinceValidInput = 0;
}
break;
case EFFButtonState::BTNS_Released:
if(PrevInput & RequiredButtons & ~PrevDisable &&
!(CurrInput & RequiredButtons | CurrDisable))
{
CondIdx--;
FramesSinceValidInput = 0;
}
break;
// TODO: implement button held condition
/*
case EFFButtonState::BTNS_Held:
break;
*/
}
// All conditions were met
if(CondIdx == -1)
{
// disable inputs that triggered the sequence
InputBuffer[InpIdx].DisabledButtons |= InputBuffer[InpIdx].Buttons;
InputBuffer[InpIdx + 1].DisabledButtons |= InputBuffer[InpIdx + 1].Buttons;
return true;
}
FramesSinceValidInput++;
if(FramesSinceValidInput > InputCondition.Lenience)
if(FramesSinceValidInput > InputSequence.Sequence[CondIdx].Lenience)
{
return false;
}

View File

@ -11,6 +11,15 @@
#include "FFInputBufferComponent.generated.h"
UENUM(BlueprintType)
enum class EFFButtonState : uint8
{
BTNS_Pressed UMETA(DisplayName="Pressed"),
BTNS_Released UMETA(DisplayName="Released"),
//BTNS_Held UMETA(DisplayName="Held"),
BTNS_MAX UMETA(Hidden)
};
/**
* Struct representing the state of a player's inputs for one frame
*/
@ -24,6 +33,7 @@ struct FFFInputState
UPROPERTY(EditAnywhere, Meta = (Bitmask))
int32 Buttons;
int32 DisabledButtons;
};
USTRUCT(BlueprintType)
@ -31,13 +41,27 @@ struct FFFInputCondition
{
GENERATED_BODY()
// Buttons required for this specific condition to be valid
UPROPERTY(EditAnywhere)
TArray<FFFInputState> Sequence;
int32 RequiredButtons;
// The button state required for condition to be valid i.e. pressed or released
UPROPERTY(EditAnywhere)
EFFButtonState RequiredButtonState;
UPROPERTY(EditAnywhere)
int32 Lenience;
};
USTRUCT(BlueprintType)
struct FFFInputSequence
{
GENERATED_BODY()
UPROPERTY(EditAnywhere)
TArray<FFFInputCondition> Sequence;
};
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class UNREALFIGHTINGFRAMEWORK_API UFFInputBufferComponent : public UActorComponent
{
@ -48,7 +72,7 @@ public:
void AddInput(const FFFInputState& InputState);
bool CheckInputSequence(const FFFInputCondition& InputCondition);
bool CheckInputSequence(const FFFInputSequence& InputSequence);
protected:
/** The underlying buffer data structure for holding past input states */