Modify movement implementation for more arcade feel and add strafing
This commit is contained in:
Binary file not shown.
BIN
Content/Input/IA_Fire.uasset
LFS
BIN
Content/Input/IA_Fire.uasset
LFS
Binary file not shown.
Binary file not shown.
BIN
Content/Input/IA_Movement.uasset
LFS
BIN
Content/Input/IA_Movement.uasset
LFS
Binary file not shown.
BIN
Content/Input/IA_Strafe.uasset
LFS
Normal file
BIN
Content/Input/IA_Strafe.uasset
LFS
Normal file
Binary file not shown.
Binary file not shown.
BIN
Content/Main.umap
LFS
BIN
Content/Main.umap
LFS
Binary file not shown.
@@ -32,19 +32,19 @@ ASpaceshipPawn::ASpaceshipPawn()
|
||||
CameraSpringArm->CameraLagSpeed = 10.0f;
|
||||
CameraSpringArm->bEnableCameraRotationLag = true;
|
||||
CameraSpringArm->CameraRotationLagSpeed = 10.0f;
|
||||
CameraSpringArm->CameraLagMaxDistance = 7.0f;
|
||||
CameraSpringArm->bUsePawnControlRotation = false; // Add this line
|
||||
CameraSpringArm->bInheritPitch = true; // Add this line
|
||||
CameraSpringArm->bInheritYaw = true; // Add this line
|
||||
CameraSpringArm->bInheritRoll = false; // Add this line
|
||||
CameraSpringArm->CameraLagMaxDistance = 7.0f;
|
||||
CameraSpringArm->bUsePawnControlRotation = false;
|
||||
CameraSpringArm->bInheritPitch = true;
|
||||
CameraSpringArm->bInheritYaw = true;
|
||||
CameraSpringArm->bInheritRoll = false;
|
||||
|
||||
// Create camera
|
||||
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
|
||||
Camera->SetupAttachment(CameraSpringArm, USpringArmComponent::SocketName);
|
||||
|
||||
// Initialize movement variables
|
||||
CurrentThrust = 0.0f;
|
||||
TargetThrust = 0.0f;
|
||||
CurrentThrottleInput = 0.0f;
|
||||
CurrentStrafeInput = 0.0f;
|
||||
bThrottlePressed = false;
|
||||
CurrentVelocity = FVector::ZeroVector;
|
||||
CurrentPitch = 0.0f;
|
||||
@@ -110,15 +110,49 @@ void ASpaceshipPawn::Tick(float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
|
||||
// Update ship rotation first (common to all movement modes)
|
||||
UpdateShipRotation(DeltaTime);
|
||||
|
||||
// Handle movement based on the selected movement mode
|
||||
switch (MovementMode)
|
||||
{
|
||||
case EShipMovementMode::Arcade:
|
||||
UpdateArcadeMovement(DeltaTime);
|
||||
break;
|
||||
|
||||
case EShipMovementMode::Assisted:
|
||||
UpdateAssistedMovement(DeltaTime);
|
||||
break;
|
||||
|
||||
case EShipMovementMode::Realistic:
|
||||
UpdateRealisticMovement(DeltaTime);
|
||||
break;
|
||||
}
|
||||
|
||||
// Update position
|
||||
FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);
|
||||
SetActorLocation(NewLocation, true);
|
||||
|
||||
// Reset mouse delta for next frame
|
||||
LastMouseDelta = FVector2D::ZeroVector;
|
||||
|
||||
// Debug info
|
||||
if (GEngine)
|
||||
{
|
||||
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Yellow,
|
||||
FString::Printf(TEXT("Thrust: %.2f"), CurrentThrust));
|
||||
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Green,
|
||||
FString::Printf(TEXT("Velocity: %.2f"), CurrentVelocity.Size()));
|
||||
}
|
||||
FString::Printf(TEXT("Mode: %s | Speed: %.1f"),
|
||||
MovementMode == EShipMovementMode::Arcade ? TEXT("Arcade") :
|
||||
MovementMode == EShipMovementMode::Assisted ? TEXT("Assisted") : TEXT("Realistic"),
|
||||
CurrentVelocity.Size()));
|
||||
|
||||
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Green,
|
||||
FString::Printf(TEXT("Throttle: %.2f | Strafe: %.2f"),
|
||||
CurrentThrottleInput, CurrentStrafeInput));
|
||||
}
|
||||
}
|
||||
|
||||
void ASpaceshipPawn::UpdateShipRotation(float DeltaTime)
|
||||
{
|
||||
// Smooth mouse movement
|
||||
MouseDeltaSmoothed = FMath::Vector2DInterpTo(
|
||||
MouseDeltaSmoothed,
|
||||
@@ -128,7 +162,7 @@ void ASpaceshipPawn::Tick(float DeltaTime)
|
||||
);
|
||||
|
||||
// Update rotation based on smoothed mouse movement
|
||||
CurrentYaw += MouseDeltaSmoothed.X * MouseSensitivity * DeltaTime * 60.0f; // Multiply by 60 to normalize for frame rate
|
||||
CurrentYaw += MouseDeltaSmoothed.X * MouseSensitivity * DeltaTime * 60.0f;
|
||||
CurrentPitch = FMath::ClampAngle(
|
||||
CurrentPitch + (MouseDeltaSmoothed.Y * MouseSensitivity * DeltaTime * 60.0f),
|
||||
-85.0f,
|
||||
@@ -144,67 +178,6 @@ void ASpaceshipPawn::Tick(float DeltaTime)
|
||||
FQuat NewQuat = FQuat::Slerp(CurrentQuat, TargetQuat, RotationSpeed * DeltaTime);
|
||||
SetActorRotation(NewQuat);
|
||||
|
||||
// Get the current forward vector
|
||||
FVector CurrentDirection = GetActorForwardVector();
|
||||
float CurrentSpeed = CurrentVelocity.Size();
|
||||
|
||||
// Handle thrust and velocity direction
|
||||
if (!bThrottlePressed)
|
||||
{
|
||||
// Decelerate when not thrusting
|
||||
CurrentThrust = FMath::FInterpTo(CurrentThrust, 0.0f, DeltaTime, ThrustDeceleration);
|
||||
bWasThrottlePressed = false;
|
||||
|
||||
// Maintain current velocity direction when not thrusting
|
||||
DesiredVelocityDirection = CurrentVelocity.GetSafeNormal();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Accelerate when thrusting
|
||||
CurrentThrust = FMath::FInterpConstantTo(CurrentThrust, TargetThrust, DeltaTime, ThrustAcceleration);
|
||||
|
||||
if (!bWasThrottlePressed)
|
||||
{
|
||||
// Just started thrusting - blend between current and new direction
|
||||
if (!CurrentVelocity.IsNearlyZero())
|
||||
{
|
||||
// Blend between current velocity direction and new direction
|
||||
FVector CurrentDir = CurrentVelocity.GetSafeNormal();
|
||||
DesiredVelocityDirection = FMath::Lerp(CurrentDir, CurrentDirection, 1.0f - DirectionalInertia);
|
||||
DesiredVelocityDirection.Normalize();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If nearly stationary, use new direction
|
||||
DesiredVelocityDirection = CurrentDirection;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Continuously blend towards current facing direction while thrusting
|
||||
DesiredVelocityDirection = FMath::VInterpNormalRotationTo(
|
||||
DesiredVelocityDirection,
|
||||
CurrentDirection,
|
||||
DeltaTime,
|
||||
VelocityAlignmentSpeed
|
||||
);
|
||||
}
|
||||
bWasThrottlePressed = true;
|
||||
}
|
||||
|
||||
// Calculate thrust force
|
||||
FVector ThrustForce = CurrentDirection * CurrentThrust;
|
||||
|
||||
// Apply drag
|
||||
FVector DragForce = -CurrentVelocity * DragCoefficient;
|
||||
|
||||
// Update velocity with forces
|
||||
CurrentVelocity += (ThrustForce + DragForce) * DeltaTime;
|
||||
|
||||
// Update position
|
||||
FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);
|
||||
SetActorLocation(NewLocation, true);
|
||||
|
||||
// Update spring arm rotation to match ship with smooth interpolation
|
||||
if (CameraSpringArm)
|
||||
{
|
||||
@@ -218,17 +191,106 @@ void ASpaceshipPawn::Tick(float DeltaTime)
|
||||
);
|
||||
CameraSpringArm->SetWorldRotation(NewSpringArmRotation);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset mouse delta for next frame
|
||||
LastMouseDelta = FVector2D::ZeroVector;
|
||||
void ASpaceshipPawn::UpdateArcadeMovement(float DeltaTime)
|
||||
{
|
||||
// In arcade mode, the ship moves exactly where it's pointed with minimal inertia
|
||||
FVector ForwardVector = GetActorForwardVector();
|
||||
FVector RightVector = GetActorRightVector();
|
||||
|
||||
// Debug info
|
||||
if (GEngine)
|
||||
// Calculate desired velocity (forward/back + strafe)
|
||||
FVector DesiredVelocity = (ForwardVector * CurrentThrottleInput * MaxSpeed) +
|
||||
(RightVector * CurrentStrafeInput * (MaxSpeed * 0.7f)); // Strafe is slightly slower
|
||||
|
||||
// Smoothly interpolate current velocity to desired velocity
|
||||
if (!FMath::IsNearlyZero(CurrentThrottleInput) || !FMath::IsNearlyZero(CurrentStrafeInput))
|
||||
{
|
||||
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Yellow,
|
||||
FString::Printf(TEXT("Smoothed Mouse Delta: X=%.2f Y=%.2f"), MouseDeltaSmoothed.X, MouseDeltaSmoothed.Y));
|
||||
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Green,
|
||||
FString::Printf(TEXT("Current Rotation: P=%.2f Y=%.2f"), CurrentPitch, CurrentYaw));
|
||||
// Accelerating
|
||||
CurrentVelocity = FMath::VInterpTo(
|
||||
CurrentVelocity,
|
||||
DesiredVelocity,
|
||||
DeltaTime,
|
||||
Acceleration / MaxSpeed
|
||||
);
|
||||
}
|
||||
else if (bAutoBrakeEnabled)
|
||||
{
|
||||
// Auto-braking when no input
|
||||
CurrentVelocity = FMath::VInterpTo(
|
||||
CurrentVelocity,
|
||||
FVector::ZeroVector,
|
||||
DeltaTime,
|
||||
AutoBrakeStrength
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Gradual deceleration
|
||||
float Speed = CurrentVelocity.Size();
|
||||
if (Speed > 0)
|
||||
{
|
||||
Speed = FMath::FInterpTo(Speed, 0, DeltaTime, Deceleration / MaxSpeed);
|
||||
CurrentVelocity = CurrentVelocity.GetSafeNormal() * Speed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ASpaceshipPawn::UpdateAssistedMovement(float DeltaTime)
|
||||
{
|
||||
// Assisted mode - a middle ground with some inertia but stabilization assistance
|
||||
FVector ForwardVector = GetActorForwardVector();
|
||||
FVector RightVector = GetActorRightVector();
|
||||
|
||||
// Calculate thrust force
|
||||
FVector ThrustForce = (ForwardVector * CurrentThrottleInput * Acceleration) +
|
||||
(RightVector * CurrentStrafeInput * (Acceleration * 0.7f));
|
||||
|
||||
// Apply thrust to velocity
|
||||
CurrentVelocity += ThrustForce * DeltaTime;
|
||||
|
||||
// Limit max speed
|
||||
float CurrentSpeed = CurrentVelocity.Size();
|
||||
if (CurrentSpeed > MaxSpeed)
|
||||
{
|
||||
CurrentVelocity = CurrentVelocity.GetSafeNormal() * MaxSpeed;
|
||||
}
|
||||
|
||||
// Apply auto-stabilization (gradual slowdown) when not thrusting
|
||||
if (FMath::IsNearlyZero(CurrentThrottleInput) && FMath::IsNearlyZero(CurrentStrafeInput) && bAutoBrakeEnabled)
|
||||
{
|
||||
CurrentVelocity = FMath::VInterpTo(
|
||||
CurrentVelocity,
|
||||
FVector::ZeroVector,
|
||||
DeltaTime,
|
||||
StabilizationSpeed
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void ASpaceshipPawn::UpdateRealisticMovement(float DeltaTime)
|
||||
{
|
||||
// This is the original physics-based movement with momentum
|
||||
FVector CurrentDirection = GetActorForwardVector();
|
||||
FVector RightVector = GetActorRightVector();
|
||||
|
||||
// Calculate thrust force (forward + strafe)
|
||||
FVector ThrustForce = (CurrentDirection * CurrentThrottleInput * Acceleration) +
|
||||
(RightVector * CurrentStrafeInput * (Acceleration * 0.7f));
|
||||
|
||||
// Apply thrust to velocity
|
||||
CurrentVelocity += ThrustForce * DeltaTime;
|
||||
|
||||
// Apply drag
|
||||
float DragCoefficient = 0.05f;
|
||||
FVector DragForce = -CurrentVelocity * DragCoefficient;
|
||||
CurrentVelocity += DragForce * DeltaTime;
|
||||
|
||||
// Limit max speed
|
||||
float CurrentSpeed = CurrentVelocity.Size();
|
||||
if (CurrentSpeed > MaxSpeed)
|
||||
{
|
||||
CurrentVelocity = CurrentVelocity.GetSafeNormal() * MaxSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,9 +300,14 @@ void ASpaceshipPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputCompo
|
||||
|
||||
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
|
||||
{
|
||||
// Bind both Hold and Released events for throttle
|
||||
EnhancedInputComponent->BindAction(ThrottleAction, ETriggerEvent::Started, this, &ASpaceshipPawn::HandleThrottleStarted);
|
||||
EnhancedInputComponent->BindAction(ThrottleAction, ETriggerEvent::Completed, this, &ASpaceshipPawn::HandleThrottleReleased);
|
||||
// Bind throttle input
|
||||
EnhancedInputComponent->BindAction(ThrottleAction, ETriggerEvent::Triggered, this, &ASpaceshipPawn::HandleThrottleInput);
|
||||
|
||||
// Bind strafe input if available
|
||||
if (StrafeAction)
|
||||
{
|
||||
EnhancedInputComponent->BindAction(StrafeAction, ETriggerEvent::Triggered, this, &ASpaceshipPawn::HandleStrafeInput);
|
||||
}
|
||||
|
||||
// Bind mouse control
|
||||
EnhancedInputComponent->BindAction(MouseLookAction, ETriggerEvent::Triggered, this, &ASpaceshipPawn::HandleMouseLook);
|
||||
@@ -250,24 +317,20 @@ void ASpaceshipPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputCompo
|
||||
}
|
||||
}
|
||||
|
||||
// Split the throttle handling into two functions
|
||||
void ASpaceshipPawn::HandleThrottleStarted(const FInputActionValue& Value)
|
||||
void ASpaceshipPawn::HandleThrottleInput(const FInputActionValue& Value)
|
||||
{
|
||||
const float ThrottleValue = Value.Get<float>();
|
||||
bThrottlePressed = true;
|
||||
TargetThrust = ThrottleValue * MaxThrust;
|
||||
CurrentThrottleInput = Value.Get<float>();
|
||||
bThrottlePressed = !FMath::IsNearlyZero(CurrentThrottleInput);
|
||||
}
|
||||
|
||||
void ASpaceshipPawn::HandleThrottleReleased(const FInputActionValue& Value)
|
||||
void ASpaceshipPawn::HandleStrafeInput(const FInputActionValue& Value)
|
||||
{
|
||||
bThrottlePressed = false;
|
||||
CurrentStrafeInput = Value.Get<float>();
|
||||
}
|
||||
|
||||
void ASpaceshipPawn::HandleMouseLook(const FInputActionValue& Value)
|
||||
{
|
||||
const FVector2D MouseDelta = Value.Get<FVector2D>();
|
||||
|
||||
// Smoothly interpolate mouse delta
|
||||
LastMouseDelta = MouseDelta;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,15 @@
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "SpaceshipPawn.generated.h"
|
||||
|
||||
// Movement mode enum to allow switching between different control schemes
|
||||
UENUM(BlueprintType)
|
||||
enum class EShipMovementMode : uint8
|
||||
{
|
||||
Arcade, // Direct control, minimal inertia
|
||||
Assisted, // Some inertia with auto-stabilization
|
||||
Realistic // Full physics with momentum (original)
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class MYPROJECT3_API ASpaceshipPawn : public APawn
|
||||
{
|
||||
@@ -41,29 +50,45 @@ protected:
|
||||
|
||||
// Movement Parameters
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
float MaxThrust = 2000.0f;
|
||||
EShipMovementMode MovementMode = EShipMovementMode::Arcade;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
float ThrustAcceleration = 500.0f;
|
||||
float MaxSpeed = 2000.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
float ThrustDeceleration = 500.0f;
|
||||
float Acceleration = 2000.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
float RotationSpeed = 100.0f;
|
||||
float Deceleration = 1500.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
float RotationSpeed = 5.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
float MouseSensitivity = 2.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
float DragCoefficient = 0.05f;
|
||||
// Auto-stabilization for assisted mode
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement", meta = (ClampMin = "0.0", ClampMax = "10.0"))
|
||||
float StabilizationSpeed = 3.0f;
|
||||
|
||||
// How quickly velocity aligns with new direction
|
||||
// How much momentum to preserve when changing direction (0 = none, 1 = full)
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement", meta = (ClampMin = "0.0", ClampMax = "1.0"))
|
||||
float DirectionalInertia = 0.1f;
|
||||
|
||||
// How quickly the ship aligns with its movement direction
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement", meta = (ClampMin = "0.0", ClampMax = "10.0"))
|
||||
float VelocityAlignmentSpeed = 4.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement", meta = (ClampMin = "0.0", ClampMax = "1.0", ToolTip = "How much of the current velocity is maintained when changing direction (0 = none, 1 = full)"))
|
||||
float DirectionalInertia = 0.3f;
|
||||
// Auto-braking when not thrusting in Arcade mode
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
bool bAutoBrakeEnabled = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
float AutoBrakeStrength = 3.0f;
|
||||
|
||||
// Add a strafe input to allow lateral movement
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
||||
class UInputAction* StrafeAction;
|
||||
|
||||
// Shooting properties
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Combat")
|
||||
@@ -86,14 +111,14 @@ protected:
|
||||
UUserWidget* CrosshairWidget;
|
||||
|
||||
// Input functions
|
||||
void HandleThrottleStarted(const FInputActionValue& Value);
|
||||
void HandleThrottleReleased(const FInputActionValue& Value);
|
||||
void HandleThrottleInput(const FInputActionValue& Value);
|
||||
void HandleStrafeInput(const FInputActionValue& Value);
|
||||
void HandleMouseLook(const FInputActionValue& Value);
|
||||
|
||||
private:
|
||||
// Movement state
|
||||
float CurrentThrust;
|
||||
float TargetThrust;
|
||||
float CurrentThrottleInput;
|
||||
float CurrentStrafeInput;
|
||||
bool bThrottlePressed;
|
||||
FVector CurrentVelocity;
|
||||
FRotator TargetRotation;
|
||||
@@ -104,10 +129,7 @@ private:
|
||||
|
||||
FVector2D MouseDeltaSmoothed;
|
||||
FVector2D LastMouseDelta;
|
||||
float MouseSmoothingSpeed = 10.0f;
|
||||
|
||||
bool bWasThrottlePressed;
|
||||
FVector DesiredVelocityDirection;
|
||||
float MouseSmoothingSpeed = 10.0f;
|
||||
|
||||
FTimerHandle FireTimerHandle;
|
||||
bool bCanFire = true;
|
||||
@@ -115,4 +137,10 @@ private:
|
||||
void HandleShoot(const FInputActionValue& Value);
|
||||
void Fire();
|
||||
void ResetFire();
|
||||
|
||||
// Movement helper functions
|
||||
void UpdateArcadeMovement(float DeltaTime);
|
||||
void UpdateAssistedMovement(float DeltaTime);
|
||||
void UpdateRealisticMovement(float DeltaTime);
|
||||
void UpdateShipRotation(float DeltaTime);
|
||||
};
|
||||
Reference in New Issue
Block a user