Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // LD_CharacterFunctionLibrary.h
- #pragma once
- #include "CoreMinimal.h"
- #include "Kismet/BlueprintFunctionLibrary.h"
- #include "GameFramework/CharacterMovementComponent.h"
- #include "LD_CharacterFunctionLibrary.generated.h"
- UCLASS()
- class LD_API ULD_CharacterFunctionLibrary : public UBlueprintFunctionLibrary
- {
- GENERATED_BODY()
- public:
- UFUNCTION(BlueprintCallable, Category = "Character Movement")
- static void SmoothSprinting(
- UCharacterMovementComponent* CharMovementComp,
- bool bIsSprinting,
- float DeltaTime,
- float AccelerationTime,
- float DecelerationTime,
- float WalkingSpeed,
- float SprintingSpeed,
- float& Alpha,
- bool& bWasSprinting,
- float& TimeSinceMaxSpeedReached
- );
- };
- // LD_CharacterFunctionLibrary.cpp
- #include "LD_CharacterFunctionLibrary.h"
- // Declare static variables for debug purposes
- static float DebugAccumulatedDeltaTime = 0.0f;
- static float DebugAccumulatedAlpha = 0.0f;
- static int32 CallCount = 0;
- void ULD_CharacterFunctionLibrary::SmoothSprinting(
- UCharacterMovementComponent* CharMovementComp,
- bool bIsSprinting,
- float DeltaTime,
- float AccelerationTime,
- float DecelerationTime,
- float WalkingSpeed,
- float SprintingSpeed,
- float& Alpha,
- bool& bWasSprinting,
- float& TimeSinceMaxSpeedReached)
- {
- if (!CharMovementComp) return;
- // Update Alpha based on whether we are sprinting or not
- if (bIsSprinting != bWasSprinting)
- {
- Alpha = bIsSprinting ? 0.0f : 1.0f;
- bWasSprinting = bIsSprinting;
- TimeSinceMaxSpeedReached = 0.0f;
- }
- if (bIsSprinting)
- {
- // Accelerate towards the sprinting speed
- Alpha = FMath::Clamp(Alpha + (DeltaTime / AccelerationTime), 0.0f, 1.0f);
- }
- else
- {
- // Decelerate towards the walking speed
- Alpha = FMath::Clamp(Alpha - (DeltaTime / DecelerationTime), 0.0f, 1.0f);
- }
- float NewSpeed = FMath::InterpEaseInOut(WalkingSpeed, SprintingSpeed, Alpha, 2.0f);
- CharMovementComp->MaxWalkSpeed = NewSpeed;
- // Debug logging for DeltaTime accumulation over 10 seconds
- // #if UE_BUILD_DEVELOPMENT || UE_BUILD_DEBUG
- DebugAccumulatedDeltaTime += DeltaTime;
- DebugAccumulatedAlpha += (DeltaTime / AccelerationTime);
- if (GEngine)
- {
- GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("DeltaTime: %f, Alpha: %f"), DeltaTime, Alpha));
- }
- /* if (GEngine && DebugAccumulatedDeltaTime >= 10.0f)
- {
- CallCount++;
- // On-screen debug messages
- GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Function called %d times, DeltaTime: %f, Accumulated Alpha: %f"), CallCount, DeltaTime, DebugAccumulatedAlpha));
- // Prepare log text
- FString LogText = FString::Printf(TEXT("Alpha: %f, Sprinting: %s, Speed: %f, DeltaTime: %f\n"),
- Alpha,
- bIsSprinting ? TEXT("True") : TEXT("False"),
- CharMovementComp->MaxWalkSpeed,
- DeltaTime);
- // Define a log file name with a complete path
- FString LogFilename = FPaths::ProjectDir() + TEXT("Log/SprintLog.txt");
- // Append the log text to the file
- FFileHelper::SaveStringToFile(LogText, *LogFilename, FFileHelper::EEncodingOptions::AutoDetect, &IFileManager::Get(), FILEWRITE_Append);
- // Reset the accumulated time and alpha
- DebugAccumulatedDeltaTime = 0.0f;
- DebugAccumulatedAlpha = 0.0f;
- }*/
- // #endif
- bWasSprinting = bIsSprinting;
- }
- // LD_Character.h
- #pragma once
- #include "CoreMinimal.h"
- #include "GameFramework/Character.h"
- #include "LD_Character.generated.h"
- UCLASS()
- class LD_API ALD_Character : public ACharacter
- {
- GENERATED_BODY()
- public:
- ALD_Character();
- virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
- // Functions to handle sprinting input
- UFUNCTION(BlueprintCallable, Category = "Character Movement")
- void StartSprinting();
- UFUNCTION(BlueprintCallable, Category = "Character Movement")
- void StopSprinting();
- void EndGracePeriod();
- UFUNCTION()
- void OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
- // Function to be called by the timer
- UFUNCTION(BlueprintCallable, Category = "Character Movement")
- void UpdateSprintState();
- virtual void Tick(float DeltaTime) override;
- // Movement parameters
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Character Movement")
- float WalkingSpeed = 600.0f;
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Character Movement")
- float SprintingSpeed = 10000.0f;
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Character Movement")
- float AccelerationTime = 10.0f;
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Character Movement")
- float DecelerationTime = 2.0f;
- // Sprint state variables
- UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Movement")
- float Alpha = 0.0f;
- UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Movement")
- bool bWasSprinting = false;
- UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Movement")
- float TimeSinceMaxSpeedReached = 0.0f;
- UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Movement")
- FVector LastForwardVector;
- private:
- FTimerHandle DecelerationTimerHandle;
- static constexpr float GracePeriodDuration = 0.5f;
- bool bWithinGracePeriod = false;
- FTimerHandle GracePeriodTimerHandle;
- bool bHasCollided = false; // Flag to indicate a recent collision
- bool bIsSprinting = false;
- FTimerHandle SprintTimerHandle;
- bool bSprintKeyPressed = false;
- float SprintingTime;
- void DecelerateCharacter();
- virtual void Landed(const FHitResult& Hit) override;
- // virtual void NotifyHit(class UPrimitiveComponent* MyComp, AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit) override;
- void StartDeceleration();
- };
- // LD_Character.cpp
- #include "LD_Character.h"
- #include "LD_CharacterFunctionLibrary.h"
- #include "Components/CapsuleComponent.h"
- ALD_Character::ALD_Character()
- {
- PrimaryActorTick.bCanEverTick = true;
- LastForwardVector = GetActorForwardVector();
- GetCapsuleComponent()->OnComponentHit.AddDynamic(this, &ALD_Character::OnHit);
- }
- void ALD_Character::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
- {
- Super::SetupPlayerInputComponent(PlayerInputComponent);
- PlayerInputComponent->BindAction("Sprint", IE_Pressed, this, &ALD_Character::StartSprinting);
- PlayerInputComponent->BindAction("Sprint", IE_Released, this, &ALD_Character::StopSprinting);
- }
- void ALD_Character::Tick(float DeltaTime)
- {
- Super::Tick(DeltaTime);
- if (bSprintKeyPressed && !bIsSprinting && GetCharacterMovement()->Velocity.Size() >= WalkingSpeed)
- {
- StartSprinting();
- }
- // If sprinting, increment the sprinting time
- if (bIsSprinting)
- {
- SprintingTime += DeltaTime;
- }
- if (GEngine && bIsSprinting)
- {
- GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("Sprinting Time: %f"), SprintingTime));
- }
- }
- void ALD_Character::StartSprinting()
- {
- float CurrentSpeed = GetCharacterMovement()->Velocity.Size();
- if (CurrentSpeed >= WalkingSpeed)
- {
- bIsSprinting = true;
- if (!bWithinGracePeriod)
- {
- Alpha = FMath::Clamp(CurrentSpeed / SprintingSpeed, 0.0f, 1.0f);
- }
- GetWorldTimerManager().SetTimer(SprintTimerHandle, this, &ALD_Character::UpdateSprintState, 0.01f, true);
- bWithinGracePeriod = false;
- }
- bSprintKeyPressed = true;
- SprintingTime = 0.0f; // Reset the sprinting timer
- }
- void ALD_Character::StopSprinting()
- {
- bSprintKeyPressed = false;
- GetWorldTimerManager().SetTimer(GracePeriodTimerHandle, this, &ALD_Character::EndGracePeriod, GracePeriodDuration, false);
- }
- void ALD_Character::EndGracePeriod()
- {
- bWithinGracePeriod = false;
- if (!bSprintKeyPressed && bIsSprinting)
- {
- bIsSprinting = false;
- StartDeceleration();
- }
- }
- void ALD_Character::Landed(const FHitResult& Hit)
- {
- Super::Landed(Hit);
- if (bSprintKeyPressed)
- {
- StartSprinting();
- }
- else
- {
- StartDeceleration();
- }
- }
- void ALD_Character::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
- {
- bHasCollided = true;
- StartDeceleration();
- }
- void ALD_Character::UpdateSprintState()
- {
- // Handle the case where the character has collided
- if (bHasCollided)
- {
- // If the character has collided, handle the deceleration or stop sprinting as needed
- if (!GetWorldTimerManager().IsTimerActive(DecelerationTimerHandle))
- {
- StartDeceleration();
- }
- // Reset the collision flag
- bHasCollided = false;
- return; // Exit early to prevent further sprint logic
- }
- if (!bSprintKeyPressed && bIsSprinting)
- {
- bIsSprinting = false;
- StartDeceleration();
- }
- if (!bIsSprinting)
- {
- return;
- }
- float DeltaTime = GetWorld()->GetDeltaSeconds();
- FVector CurrentVelocity = GetCharacterMovement()->Velocity;
- float CurrentSpeed = CurrentVelocity.Size();
- if (CurrentSpeed >= WalkingSpeed)
- {
- ULD_CharacterFunctionLibrary::SmoothSprinting(
- GetCharacterMovement(),
- bIsSprinting,
- DeltaTime,
- AccelerationTime,
- DecelerationTime,
- WalkingSpeed,
- SprintingSpeed,
- Alpha,
- bWasSprinting,
- TimeSinceMaxSpeedReached
- );
- }
- else
- {
- StartDeceleration();
- }
- }
- void ALD_Character::StartDeceleration()
- {
- if (!GetWorldTimerManager().IsTimerActive(DecelerationTimerHandle))
- {
- // GetWorldTimerManager().SetTimer(DecelerationTimerHandle, this, &ALD_Character::DecelerateCharacter, GetWorld()->GetDeltaSeconds(), true);
- GetWorldTimerManager().SetTimer(DecelerationTimerHandle, this, &ALD_Character::DecelerateCharacter, 0.01f, true);
- }
- }
- void ALD_Character::DecelerateCharacter()
- {
- if (!bIsSprinting && Alpha > 0.0f)
- {
- // Alpha -= GetWorld()->GetDeltaSeconds() / DecelerationTime;
- Alpha -= 0.01f / DecelerationTime; // Adjust this rate as needed for smoother deceleration
- Alpha = FMath::Clamp(Alpha, 0.0f, 1.0f);
- float NewSpeed = FMath::Lerp(SprintingSpeed, WalkingSpeed, 1.0f - Alpha);
- GetCharacterMovement()->MaxWalkSpeed = NewSpeed;
- }
- if (Alpha <= 0.0f)
- {
- GetWorldTimerManager().ClearTimer(DecelerationTimerHandle);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement