Sonic movement
(If implemented this code will need to be bound correctly)
(walking/running with momentum):
// In Player.h
private:
float WalkSpeed = 400.f; // Base walking speed
float RunSpeed = 1200.f; // Base running speed
float CurrentSpeed = 0.f; // Current speed (momentum)
float Acceleration = 1500.f; // How fast we speed up
float Deceleration = 600.f; // How fast we slow down
float MaxSpeed = 0.f; // Max speed, set per movement state
bool bIsRunning = false;
bool bIsGrounded = true; // Simplification of grounded state
float MinimumSpeed = 50.f; // Minimum speed to prevent slipping
protected:
void MoveForward(float Value);
void MoveRight(float Value);
void ToggleRun(bool bPressed);
void UpdateSpeed(float DeltaTime);
void ApplyMomentum(float DeltaTime);
void SetMaxSpeed();
virtual void Tick(float DeltaTime) override; // For updating speed over time
// In Player.cpp
void APlayer::MoveForward(float Value)
{
if (Value != 0.f)
{
// Accelerate when moving forward
CurrentSpeed = FMath::Clamp(CurrentSpeed + (Value * Acceleration * GetWorld()->DeltaTimeSeconds), 0.f, MaxSpeed);
}
else
{
// Decelerate when no input is given
CurrentSpeed = FMath::Clamp(CurrentSpeed - (Deceleration * GetWorld()->DeltaTimeSeconds), MinimumSpeed, MaxSpeed);
}
}
void APlayer::MoveRight(float Value)
{
// Optional - Handle right/left movement similarly if needed
if (Value != 0.f)
{
AddMovementInput(GetActorRightVector(), Value);
}
}
void APlayer::ToggleRun(bool bPressed)
{
bIsRunning = bPressed;
SetMaxSpeed();
}
void APlayer::SetMaxSpeed()
{
// Set max speed based on whether we're walking or running
MaxSpeed = bIsRunning ? RunSpeed : WalkSpeed;
}
void APlayer::UpdateSpeed(float DeltaTime)
{
// If we're in the air or not grounded, stop the momentum decay from deceleration
if (!bIsGrounded)
{
CurrentSpeed = FMath::Clamp(CurrentSpeed, 0.f, MaxSpeed);
}
}
void APlayer::ApplyMomentum(float DeltaTime)
{
// Apply the current speed to movement
FVector ForwardVector = GetActorForwardVector();
FVector Velocity = ForwardVector * CurrentSpeed;
GetCharacterMovement()->Velocity = Velocity;
}
void APlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
UpdateSpeed(DeltaTime);
ApplyMomentum(DeltaTime);
}
Jumping (pressure, min/max):
private:
float MinJumpHeight = 600.f; // Minimum jump force
float MaxJumpHeight = 1200.f; // Maximum jump force
float JumpCharge = 0.f; // Jump charge value when holding the button
float JumpChargeRate = 800.f; // How fast the jump charge increases
bool bIsJumping = false; // Whether the player is jumping or not
protected:
void StartJump();
void StopJump();
void UpdateJumpCharge(float DeltaTime);
void ApplyJumpForce();
// In Player.cpp
void APlayer::StartJump()
{
if (bIsGrounded && !bIsJumping) // Make sure the player is on the ground
{
bIsJumping = true;
JumpCharge = MinJumpHeight; // Start the jump charge from the minimum jump height
}
}
void APlayer::StopJump()
{
if (bIsJumping) // Stop charging the jump when the button is released
{
ApplyJumpForce();
bIsJumping = false;
}
}
void APlayer::UpdateJumpCharge(float DeltaTime)
{
if (bIsJumping)
{
// Increase the jump charge gradually as long as the jump button is held
JumpCharge = FMath::Clamp(JumpCharge + JumpChargeRate * DeltaTime, MinJumpHeight, MaxJumpHeight);
}
}
void APlayer::ApplyJumpForce()
{
// Apply the calculated jump force
if (bIsGrounded)
{
FVector JumpImpulse = FVector(0.f, 0.f, JumpCharge); // Vertical impulse
GetCharacterMovement()->Launch(FVector(0, 0, 1) * JumpCharge); // Apply the force for the jump
}
}
void APlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (bIsJumping)
{
UpdateJumpCharge(DeltaTime); // Keep updating the jump force while holding the button
}
}
Spindash (build up/launching):
private:
float MinSpindashCharge = 300.f; // Minimum charge for Spindash
float MaxSpindashCharge = 1000.f; // Maximum charge for Spindash
float SpindashCharge = 0.f; // Current charge level
float SpindashChargeRate = 600.f; // Charge rate when holding the button
float SpindashLaunchForce = 2000.f; // Launch force when the Spindash is released
bool bIsChargingSpindash = false; // Whether the Spindash is charging
bool bIsSpindashing = false; // Whether the player is currently in a Spindash state
bool bIsOnSlope = false; // Whether the character is on a slope (simplified check)
protected:
void StartSpindash();
void StopSpindash();
void UpdateSpindashCharge(float DeltaTime);
void LaunchSpindash();
void CheckIfOnSlope();
void ResetSpindash();
virtual void Tick(float DeltaTime) override; // For updating Spindash charge over time
// In Player.cpp
void APlayer::StartSpindash()
{
if (!bIsSpindashing) // Start charging Spindash if we aren't already Spindashing
{
bIsChargingSpindash = true;
SpindashCharge = MinSpindashCharge; // Start from minimum charge
}
}
void APlayer::StopSpindash()
{
if (bIsChargingSpindash)
{
LaunchSpindash(); // Launch when the button is released
}
bIsChargingSpindash = false; // Stop charging
}
void APlayer::UpdateSpindashCharge(float DeltaTime)
{
if (bIsChargingSpindash)
{
// Continue charging the Spindash as long as the button is held, clamping between Min and Max
SpindashCharge = FMath::Clamp(SpindashCharge + (SpindashChargeRate * DeltaTime), MinSpindashCharge, MaxSpindashCharge);
}
}
void APlayer::LaunchSpindash()
{
if (bIsOnSlope) // If we're on a slope, we allow a special launch behavior (upward).
{
FVector LaunchDirection = GetActorForwardVector() + FVector(0.f, 0.f, 1.f); // Adding a little upward vector
GetCharacterMovement()->Launch(FVector(LaunchDirection * SpindashCharge)); // Apply force based on charge
}
else
{
// Normal Spindash launch
GetCharacterMovement()->Launch(FVector(GetActorForwardVector() * SpindashCharge)); // Apply horizontal force based on charge
}
ResetSpindash(); // Reset charge and stop spindashing
}
void APlayer::CheckIfOnSlope()
{
// Simplified check for if the player is on a slope
FVector DownVector = FVector(0.f, 0.f, -1.f);
FHitResult Hit;
FVector Start = GetActorLocation();
FVector End = Start + (DownVector * 100.f); // Check a small distance below the player
// Raycast down to check for slope
if (GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility))
{
FVector Normal = Hit.Normal;
float Angle = FMath::RadiansToDegrees(FMath::Acos(FVector:
otProduct(Normal, DownVector)));
// If the angle of the slope is steep enough (for example, > 10 degrees), we consider it a slope.
bIsOnSlope = Angle > 10.f;
}
else
{
bIsOnSlope = false; // Not on a slope if we can't hit anything
}
}
void APlayer::ResetSpindash()
{
SpindashCharge = 0.f; // Reset charge after use
bIsSpindashing = false;
}
void APlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (bIsChargingSpindash)
{
UpdateSpindashCharge(DeltaTime); // Keep updating the Spindash charge while holding the button
}
CheckIfOnSlope(); // Check if we're on a slope, which might influence the Spindash launch
}
(If implemented this code will need to be bound correctly)
(walking/running with momentum):
// In Player.h
private:
float WalkSpeed = 400.f; // Base walking speed
float RunSpeed = 1200.f; // Base running speed
float CurrentSpeed = 0.f; // Current speed (momentum)
float Acceleration = 1500.f; // How fast we speed up
float Deceleration = 600.f; // How fast we slow down
float MaxSpeed = 0.f; // Max speed, set per movement state
bool bIsRunning = false;
bool bIsGrounded = true; // Simplification of grounded state
float MinimumSpeed = 50.f; // Minimum speed to prevent slipping
protected:
void MoveForward(float Value);
void MoveRight(float Value);
void ToggleRun(bool bPressed);
void UpdateSpeed(float DeltaTime);
void ApplyMomentum(float DeltaTime);
void SetMaxSpeed();
virtual void Tick(float DeltaTime) override; // For updating speed over time
// In Player.cpp
void APlayer::MoveForward(float Value)
{
if (Value != 0.f)
{
// Accelerate when moving forward
CurrentSpeed = FMath::Clamp(CurrentSpeed + (Value * Acceleration * GetWorld()->DeltaTimeSeconds), 0.f, MaxSpeed);
}
else
{
// Decelerate when no input is given
CurrentSpeed = FMath::Clamp(CurrentSpeed - (Deceleration * GetWorld()->DeltaTimeSeconds), MinimumSpeed, MaxSpeed);
}
}
void APlayer::MoveRight(float Value)
{
// Optional - Handle right/left movement similarly if needed
if (Value != 0.f)
{
AddMovementInput(GetActorRightVector(), Value);
}
}
void APlayer::ToggleRun(bool bPressed)
{
bIsRunning = bPressed;
SetMaxSpeed();
}
void APlayer::SetMaxSpeed()
{
// Set max speed based on whether we're walking or running
MaxSpeed = bIsRunning ? RunSpeed : WalkSpeed;
}
void APlayer::UpdateSpeed(float DeltaTime)
{
// If we're in the air or not grounded, stop the momentum decay from deceleration
if (!bIsGrounded)
{
CurrentSpeed = FMath::Clamp(CurrentSpeed, 0.f, MaxSpeed);
}
}
void APlayer::ApplyMomentum(float DeltaTime)
{
// Apply the current speed to movement
FVector ForwardVector = GetActorForwardVector();
FVector Velocity = ForwardVector * CurrentSpeed;
GetCharacterMovement()->Velocity = Velocity;
}
void APlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
UpdateSpeed(DeltaTime);
ApplyMomentum(DeltaTime);
}
Jumping (pressure, min/max):
private:
float MinJumpHeight = 600.f; // Minimum jump force
float MaxJumpHeight = 1200.f; // Maximum jump force
float JumpCharge = 0.f; // Jump charge value when holding the button
float JumpChargeRate = 800.f; // How fast the jump charge increases
bool bIsJumping = false; // Whether the player is jumping or not
protected:
void StartJump();
void StopJump();
void UpdateJumpCharge(float DeltaTime);
void ApplyJumpForce();
// In Player.cpp
void APlayer::StartJump()
{
if (bIsGrounded && !bIsJumping) // Make sure the player is on the ground
{
bIsJumping = true;
JumpCharge = MinJumpHeight; // Start the jump charge from the minimum jump height
}
}
void APlayer::StopJump()
{
if (bIsJumping) // Stop charging the jump when the button is released
{
ApplyJumpForce();
bIsJumping = false;
}
}
void APlayer::UpdateJumpCharge(float DeltaTime)
{
if (bIsJumping)
{
// Increase the jump charge gradually as long as the jump button is held
JumpCharge = FMath::Clamp(JumpCharge + JumpChargeRate * DeltaTime, MinJumpHeight, MaxJumpHeight);
}
}
void APlayer::ApplyJumpForce()
{
// Apply the calculated jump force
if (bIsGrounded)
{
FVector JumpImpulse = FVector(0.f, 0.f, JumpCharge); // Vertical impulse
GetCharacterMovement()->Launch(FVector(0, 0, 1) * JumpCharge); // Apply the force for the jump
}
}
void APlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (bIsJumping)
{
UpdateJumpCharge(DeltaTime); // Keep updating the jump force while holding the button
}
}
Spindash (build up/launching):
private:
float MinSpindashCharge = 300.f; // Minimum charge for Spindash
float MaxSpindashCharge = 1000.f; // Maximum charge for Spindash
float SpindashCharge = 0.f; // Current charge level
float SpindashChargeRate = 600.f; // Charge rate when holding the button
float SpindashLaunchForce = 2000.f; // Launch force when the Spindash is released
bool bIsChargingSpindash = false; // Whether the Spindash is charging
bool bIsSpindashing = false; // Whether the player is currently in a Spindash state
bool bIsOnSlope = false; // Whether the character is on a slope (simplified check)
protected:
void StartSpindash();
void StopSpindash();
void UpdateSpindashCharge(float DeltaTime);
void LaunchSpindash();
void CheckIfOnSlope();
void ResetSpindash();
virtual void Tick(float DeltaTime) override; // For updating Spindash charge over time
// In Player.cpp
void APlayer::StartSpindash()
{
if (!bIsSpindashing) // Start charging Spindash if we aren't already Spindashing
{
bIsChargingSpindash = true;
SpindashCharge = MinSpindashCharge; // Start from minimum charge
}
}
void APlayer::StopSpindash()
{
if (bIsChargingSpindash)
{
LaunchSpindash(); // Launch when the button is released
}
bIsChargingSpindash = false; // Stop charging
}
void APlayer::UpdateSpindashCharge(float DeltaTime)
{
if (bIsChargingSpindash)
{
// Continue charging the Spindash as long as the button is held, clamping between Min and Max
SpindashCharge = FMath::Clamp(SpindashCharge + (SpindashChargeRate * DeltaTime), MinSpindashCharge, MaxSpindashCharge);
}
}
void APlayer::LaunchSpindash()
{
if (bIsOnSlope) // If we're on a slope, we allow a special launch behavior (upward).
{
FVector LaunchDirection = GetActorForwardVector() + FVector(0.f, 0.f, 1.f); // Adding a little upward vector
GetCharacterMovement()->Launch(FVector(LaunchDirection * SpindashCharge)); // Apply force based on charge
}
else
{
// Normal Spindash launch
GetCharacterMovement()->Launch(FVector(GetActorForwardVector() * SpindashCharge)); // Apply horizontal force based on charge
}
ResetSpindash(); // Reset charge and stop spindashing
}
void APlayer::CheckIfOnSlope()
{
// Simplified check for if the player is on a slope
FVector DownVector = FVector(0.f, 0.f, -1.f);
FHitResult Hit;
FVector Start = GetActorLocation();
FVector End = Start + (DownVector * 100.f); // Check a small distance below the player
// Raycast down to check for slope
if (GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility))
{
FVector Normal = Hit.Normal;
float Angle = FMath::RadiansToDegrees(FMath::Acos(FVector:
// If the angle of the slope is steep enough (for example, > 10 degrees), we consider it a slope.
bIsOnSlope = Angle > 10.f;
}
else
{
bIsOnSlope = false; // Not on a slope if we can't hit anything
}
}
void APlayer::ResetSpindash()
{
SpindashCharge = 0.f; // Reset charge after use
bIsSpindashing = false;
}
void APlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (bIsChargingSpindash)
{
UpdateSpindashCharge(DeltaTime); // Keep updating the Spindash charge while holding the button
}
CheckIfOnSlope(); // Check if we're on a slope, which might influence the Spindash launch
}






