Download

Detecting quick analog tap in one direction

Hello there, I want to implement something similar to super smash brothers’ smash attacks, where by smashing (aka turning a stick very fast in one direction) the analog stick and pressing the attack button you perform a stronger attack.

My idea of implementing this is having some sort of delta-time based value that I can extract from the difference of the stick’s position since last frame.

Anyone has any tips on how to do this?

Finally figured this out, here’s how I did it, it’s for the right axis, but you can adapt it to the left one

I added the following values to my pawn:


	
float axisTapWindow = 0.05f; //the time between letting go of neutral and the minimum tap for the move to be considered a tap
float axisTapMinimum = 0.5f; //the minimum axis value required for it to be considered a tap
float axisTapAttackWindow = 0.03f; //the time the user has after the tap to perform an attack
bool wasRightAxisNeutralLastTick = true; //if the axis was at 0 last tick
bool isTappingRightAxis = false; //if the user is tapping the right axis

Here’s the code in the controller:


void ABorealController::MoveRight(float Value)
{
	/*UpdateChar();*/

	// Apply the input to the character motion
	//AddMovementInput(FVector(1.0f, 0.0f, 0.0f), Value);
	ABorealCharacter *character = Cast<ABorealCharacter>(GetPawn());
	if (GetWorld())
	{
		if (character != NULL)
		{
			if (Value == 0)
			{
				character->wasRightAxisNeutralLastTick = true;
			}

			if (character->wasRightAxisNeutralLastTick)
			{
				character->wasRightAxisNeutralLastTick = false;
				GetWorld()->GetTimerManager().SetTimer(RightAxisTapTimeoutHandle, this, &ABorealController::RightAxisTapTimeout, character->axisTapWindow, false);
			}
			if (Value > character->axisTapMinimum || Value < (character->axisTapMinimum*-1))
			{
				if (GetWorld()->GetTimerManager().IsTimerActive(RightAxisTapTimeoutHandle))
				{
					GetWorld()->GetTimerManager().ClearTimer(RightAxisTapTimeoutHandle);
					GetWorld()->GetTimerManager().SetTimer(RightAxisAttackTimeoutHandle, this, &ABorealController::RightAxisAttackTimeout, character->axisTapAttackWindow, false);
					character->isTappingRightAxis = true;
					UE_LOG(LogTemp, Warning, TEXT("Tapped right"));
				}
			}


			
		}

	}

}

void ABorealController::RightAxisTapTimeout()
{
	return;
}

void ABorealController::RightAxisAttackTimeout()
{
	ABorealCharacter *character = Cast<ABorealCharacter>(GetPawn());
	if (character != NULL)
	{
		character->isTappingRightAxis = false;
	}
}

Header:


// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameFramework/PlayerController.h"
#include "BorealController.generated.h"

/**
 * 
 */
UCLASS()
class BOREAL_API ABorealController : public APlayerController
{
	GENERATED_BODY()
protected:
	FTimerHandle RightAxisTapTimeoutHandle;
	FTimerHandle UpAxisTapTimeoutHandle;
	FTimerHandle RightAxisAttackTimeoutHandle;
	FTimerHandle UpAxisAttackTimeoutHandle;

public:
	void RightAxisTapTimeout();
	void RightAxisAttackTimeout();
};