Advertisement
Shiny_

Untitled

Dec 9th, 2023
777
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.17 KB | None | 0 0
  1. // LD_CharacterFunctionLibrary.h
  2.  
  3. #pragma once
  4.  
  5. #include "CoreMinimal.h"
  6. #include "Kismet/BlueprintFunctionLibrary.h"
  7. #include "GameFramework/CharacterMovementComponent.h"
  8. #include "LD_CharacterFunctionLibrary.generated.h"
  9.  
  10. UCLASS()
  11. class LD_API ULD_CharacterFunctionLibrary : public UBlueprintFunctionLibrary
  12. {
  13.     GENERATED_BODY()
  14.  
  15. public:
  16.     UFUNCTION(BlueprintCallable, Category = "Character Movement")
  17.     static void SmoothSprinting(
  18.         UCharacterMovementComponent* CharMovementComp,
  19.         bool bIsSprinting,
  20.         float DeltaTime,
  21.         float AccelerationTime,
  22.         float DecelerationTime,
  23.         float WalkingSpeed,
  24.         float SprintingSpeed,
  25.         float& Alpha,
  26.         bool& bWasSprinting,
  27.         float& TimeSinceMaxSpeedReached
  28.     );
  29. };
  30.  
  31.  
  32.  
  33. // LD_CharacterFunctionLibrary.cpp
  34.  
  35. #include "LD_CharacterFunctionLibrary.h"
  36.  
  37. // Declare static variables for debug purposes
  38. static float DebugAccumulatedDeltaTime = 0.0f;
  39. static float DebugAccumulatedAlpha = 0.0f;
  40. static int32 CallCount = 0;
  41.  
  42. void ULD_CharacterFunctionLibrary::SmoothSprinting(
  43.     UCharacterMovementComponent* CharMovementComp,
  44.     bool bIsSprinting,
  45.     float DeltaTime,
  46.     float AccelerationTime,
  47.     float DecelerationTime,
  48.     float WalkingSpeed,
  49.     float SprintingSpeed,
  50.     float& Alpha,
  51.     bool& bWasSprinting,
  52.     float& TimeSinceMaxSpeedReached)
  53. {
  54.     if (!CharMovementComp) return;
  55.  
  56.     // Update Alpha based on whether we are sprinting or not
  57.     if (bIsSprinting != bWasSprinting)
  58.     {
  59.         Alpha = bIsSprinting ? 0.0f : 1.0f;
  60.         bWasSprinting = bIsSprinting;
  61.         TimeSinceMaxSpeedReached = 0.0f;
  62.     }
  63.  
  64.     if (bIsSprinting)
  65.     {
  66.         // Accelerate towards the sprinting speed
  67.         Alpha = FMath::Clamp(Alpha + (DeltaTime / AccelerationTime), 0.0f, 1.0f);
  68.     }
  69.     else
  70.     {
  71.         // Decelerate towards the walking speed
  72.         Alpha = FMath::Clamp(Alpha - (DeltaTime / DecelerationTime), 0.0f, 1.0f);
  73.     }
  74.  
  75.     float NewSpeed = FMath::InterpEaseInOut(WalkingSpeed, SprintingSpeed, Alpha, 2.0f);
  76.     CharMovementComp->MaxWalkSpeed = NewSpeed;
  77.  
  78.     // Debug logging for DeltaTime accumulation over 10 seconds
  79. // #if UE_BUILD_DEVELOPMENT || UE_BUILD_DEBUG
  80.     DebugAccumulatedDeltaTime += DeltaTime;
  81.     DebugAccumulatedAlpha += (DeltaTime / AccelerationTime);
  82.  
  83.     if (GEngine)
  84.     {
  85.         GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("DeltaTime: %f, Alpha: %f"), DeltaTime, Alpha));
  86.     }
  87.  
  88.     /* if (GEngine && DebugAccumulatedDeltaTime >= 10.0f)
  89.     {
  90.         CallCount++;
  91.  
  92.         // On-screen debug messages
  93.         GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Function called %d times, DeltaTime: %f, Accumulated Alpha: %f"), CallCount, DeltaTime, DebugAccumulatedAlpha));
  94.  
  95.         // Prepare log text
  96.         FString LogText = FString::Printf(TEXT("Alpha: %f, Sprinting: %s, Speed: %f, DeltaTime: %f\n"),
  97.             Alpha,
  98.             bIsSprinting ? TEXT("True") : TEXT("False"),
  99.             CharMovementComp->MaxWalkSpeed,
  100.             DeltaTime);
  101.  
  102.         // Define a log file name with a complete path
  103.         FString LogFilename = FPaths::ProjectDir() + TEXT("Log/SprintLog.txt");
  104.  
  105.         // Append the log text to the file
  106.         FFileHelper::SaveStringToFile(LogText, *LogFilename, FFileHelper::EEncodingOptions::AutoDetect, &IFileManager::Get(), FILEWRITE_Append);
  107.  
  108.         // Reset the accumulated time and alpha
  109.         DebugAccumulatedDeltaTime = 0.0f;
  110.         DebugAccumulatedAlpha = 0.0f;
  111.     }*/
  112. // #endif
  113.     bWasSprinting = bIsSprinting;
  114. }
  115.  
  116.  
  117.  
  118.  
  119. // LD_Character.h
  120.  
  121. #pragma once
  122.  
  123. #include "CoreMinimal.h"
  124. #include "GameFramework/Character.h"
  125. #include "LD_Character.generated.h"
  126.  
  127. UCLASS()
  128. class LD_API ALD_Character : public ACharacter
  129. {
  130.     GENERATED_BODY()
  131.  
  132. public:
  133.     ALD_Character();
  134.  
  135.     virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
  136.  
  137.     // Functions to handle sprinting input
  138.     UFUNCTION(BlueprintCallable, Category = "Character Movement")
  139.     void StartSprinting();
  140.    
  141.     UFUNCTION(BlueprintCallable, Category = "Character Movement")
  142.     void StopSprinting();
  143.  
  144.     void EndGracePeriod();
  145.  
  146.  
  147.     UFUNCTION()
  148.     void OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
  149.  
  150.     // Function to be called by the timer
  151.     UFUNCTION(BlueprintCallable, Category = "Character Movement")
  152.     void UpdateSprintState();
  153.  
  154.     virtual void Tick(float DeltaTime) override;
  155.  
  156.     // Movement parameters
  157.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Character Movement")
  158.     float WalkingSpeed = 600.0f;
  159.  
  160.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Character Movement")
  161.     float SprintingSpeed = 10000.0f;
  162.  
  163.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Character Movement")
  164.     float AccelerationTime = 10.0f;
  165.  
  166.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Character Movement")
  167.     float DecelerationTime = 2.0f;
  168.  
  169.     // Sprint state variables
  170.     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Movement")
  171.     float Alpha = 0.0f;
  172.  
  173.     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Movement")
  174.     bool bWasSprinting = false;
  175.  
  176.     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Movement")
  177.     float TimeSinceMaxSpeedReached = 0.0f;
  178.  
  179.     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Movement")
  180.     FVector LastForwardVector;
  181.  
  182. private:
  183.     FTimerHandle DecelerationTimerHandle;
  184.  
  185.     static constexpr float GracePeriodDuration = 0.5f;
  186.     bool bWithinGracePeriod = false;
  187.     FTimerHandle GracePeriodTimerHandle;
  188.  
  189.     bool bHasCollided = false; // Flag to indicate a recent collision
  190.  
  191.     bool bIsSprinting = false;
  192.    
  193.     FTimerHandle SprintTimerHandle;
  194.    
  195.     bool bSprintKeyPressed = false;
  196.    
  197.     float SprintingTime;
  198.  
  199.     void DecelerateCharacter();
  200.    
  201.     virtual void Landed(const FHitResult& Hit) override;
  202.    
  203. //    virtual void NotifyHit(class UPrimitiveComponent* MyComp, AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit) override;
  204.  
  205.     void StartDeceleration();
  206. };
  207.  
  208.  
  209.  
  210.  
  211. // LD_Character.cpp
  212.  
  213. #include "LD_Character.h"
  214. #include "LD_CharacterFunctionLibrary.h"
  215. #include "Components/CapsuleComponent.h"
  216.  
  217. ALD_Character::ALD_Character()
  218. {
  219.     PrimaryActorTick.bCanEverTick = true;
  220.     LastForwardVector = GetActorForwardVector();
  221.     GetCapsuleComponent()->OnComponentHit.AddDynamic(this, &ALD_Character::OnHit);
  222. }
  223.  
  224. void ALD_Character::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
  225. {
  226.     Super::SetupPlayerInputComponent(PlayerInputComponent);
  227.     PlayerInputComponent->BindAction("Sprint", IE_Pressed, this, &ALD_Character::StartSprinting);
  228.     PlayerInputComponent->BindAction("Sprint", IE_Released, this, &ALD_Character::StopSprinting);
  229. }
  230.  
  231. void ALD_Character::Tick(float DeltaTime)
  232. {
  233.     Super::Tick(DeltaTime);
  234.     if (bSprintKeyPressed && !bIsSprinting && GetCharacterMovement()->Velocity.Size() >= WalkingSpeed)
  235.     {
  236.         StartSprinting();
  237.     }
  238.  
  239.     // If sprinting, increment the sprinting time
  240.     if (bIsSprinting)
  241.     {
  242.         SprintingTime += DeltaTime;
  243.     }
  244.  
  245.     if (GEngine && bIsSprinting)
  246.     {
  247.         GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("Sprinting Time: %f"), SprintingTime));
  248.     }
  249.  
  250. }
  251.  
  252. void ALD_Character::StartSprinting()
  253. {
  254.     float CurrentSpeed = GetCharacterMovement()->Velocity.Size();
  255.     if (CurrentSpeed >= WalkingSpeed)
  256.     {
  257.         bIsSprinting = true;
  258.         if (!bWithinGracePeriod)
  259.         {
  260.             Alpha = FMath::Clamp(CurrentSpeed / SprintingSpeed, 0.0f, 1.0f);
  261.         }
  262.         GetWorldTimerManager().SetTimer(SprintTimerHandle, this, &ALD_Character::UpdateSprintState, 0.01f, true);
  263.         bWithinGracePeriod = false;
  264.     }
  265.     bSprintKeyPressed = true;
  266.     SprintingTime = 0.0f;  // Reset the sprinting timer
  267. }
  268.  
  269. void ALD_Character::StopSprinting()
  270. {
  271.     bSprintKeyPressed = false;
  272.     GetWorldTimerManager().SetTimer(GracePeriodTimerHandle, this, &ALD_Character::EndGracePeriod, GracePeriodDuration, false);
  273. }
  274.  
  275. void ALD_Character::EndGracePeriod()
  276. {
  277.     bWithinGracePeriod = false;
  278.     if (!bSprintKeyPressed && bIsSprinting)
  279.     {
  280.         bIsSprinting = false;
  281.         StartDeceleration();
  282.     }
  283. }
  284.  
  285. void ALD_Character::Landed(const FHitResult& Hit)
  286. {
  287.     Super::Landed(Hit);
  288.     if (bSprintKeyPressed)
  289.     {
  290.         StartSprinting();
  291.     }
  292.     else
  293.     {
  294.         StartDeceleration();
  295.     }
  296. }
  297.  
  298. void ALD_Character::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
  299. {
  300.     bHasCollided = true;
  301.    
  302.     StartDeceleration();
  303. }
  304.  
  305. void ALD_Character::UpdateSprintState()
  306. {
  307.     // Handle the case where the character has collided
  308.     if (bHasCollided)
  309.     {
  310.         // If the character has collided, handle the deceleration or stop sprinting as needed
  311.         if (!GetWorldTimerManager().IsTimerActive(DecelerationTimerHandle))
  312.         {
  313.             StartDeceleration();
  314.         }
  315.  
  316.         // Reset the collision flag
  317.         bHasCollided = false;
  318.         return; // Exit early to prevent further sprint logic
  319.     }
  320.  
  321.     if (!bSprintKeyPressed && bIsSprinting)
  322.     {
  323.         bIsSprinting = false;
  324.         StartDeceleration();
  325.     }
  326.    
  327.     if (!bIsSprinting)
  328.     {
  329.         return;
  330.     }
  331.  
  332.     float DeltaTime = GetWorld()->GetDeltaSeconds();
  333.     FVector CurrentVelocity = GetCharacterMovement()->Velocity;
  334.     float CurrentSpeed = CurrentVelocity.Size();
  335.  
  336.     if (CurrentSpeed >= WalkingSpeed)
  337.     {
  338.         ULD_CharacterFunctionLibrary::SmoothSprinting(
  339.             GetCharacterMovement(),
  340.             bIsSprinting,
  341.             DeltaTime,
  342.             AccelerationTime,
  343.             DecelerationTime,
  344.             WalkingSpeed,
  345.             SprintingSpeed,
  346.             Alpha,
  347.             bWasSprinting,
  348.             TimeSinceMaxSpeedReached
  349.         );
  350.     }
  351.     else
  352.     {
  353.         StartDeceleration();
  354.     }
  355. }
  356.  
  357. void ALD_Character::StartDeceleration()
  358. {
  359.     if (!GetWorldTimerManager().IsTimerActive(DecelerationTimerHandle))
  360.     {
  361.         // GetWorldTimerManager().SetTimer(DecelerationTimerHandle, this, &ALD_Character::DecelerateCharacter, GetWorld()->GetDeltaSeconds(), true);
  362.         GetWorldTimerManager().SetTimer(DecelerationTimerHandle, this, &ALD_Character::DecelerateCharacter, 0.01f, true);
  363.     }
  364. }
  365.  
  366. void ALD_Character::DecelerateCharacter()
  367. {
  368.     if (!bIsSprinting && Alpha > 0.0f)
  369.     {
  370.         // Alpha -= GetWorld()->GetDeltaSeconds() / DecelerationTime;
  371.         Alpha -= 0.01f / DecelerationTime;  // Adjust this rate as needed for smoother deceleration
  372.         Alpha = FMath::Clamp(Alpha, 0.0f, 1.0f);
  373.         float NewSpeed = FMath::Lerp(SprintingSpeed, WalkingSpeed, 1.0f - Alpha);
  374.         GetCharacterMovement()->MaxWalkSpeed = NewSpeed;
  375.     }
  376.  
  377.     if (Alpha <= 0.0f)
  378.     {
  379.         GetWorldTimerManager().ClearTimer(DecelerationTimerHandle);
  380.     }
  381. }
  382.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement