Implement better throttle system
This commit is contained in:
@@ -10,20 +10,32 @@ ASpaceshipPawn::ASpaceshipPawn()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
|
||||
// Create and setup the ship's mesh
|
||||
// Create ship mesh
|
||||
ShipMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ShipMesh"));
|
||||
RootComponent = ShipMesh;
|
||||
ShipMesh->SetSimulatePhysics(false);
|
||||
ShipMesh->SetEnableGravity(false);
|
||||
|
||||
// Create and setup the camera spring arm
|
||||
// Create camera spring arm
|
||||
CameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));
|
||||
CameraSpringArm->SetupAttachment(RootComponent);
|
||||
CameraSpringArm->TargetArmLength = 400.0f;
|
||||
CameraSpringArm->bEnableCameraLag = true;
|
||||
CameraSpringArm->CameraLagSpeed = 3.0f;
|
||||
CameraSpringArm->bEnableCameraRotationLag = true;
|
||||
CameraSpringArm->CameraRotationLagSpeed = 10.0f;
|
||||
|
||||
// Create and setup the camera
|
||||
// Create camera
|
||||
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
|
||||
Camera->SetupAttachment(CameraSpringArm, USpringArmComponent::SocketName);
|
||||
|
||||
// Initialize movement variables
|
||||
CurrentThrust = 0.0f;
|
||||
TargetThrust = 0.0f;
|
||||
bThrottlePressed = false;
|
||||
CurrentVelocity = FVector::ZeroVector;
|
||||
CurrentRotation = GetActorQuat();
|
||||
TargetRotation = GetActorRotation();
|
||||
}
|
||||
|
||||
void ASpaceshipPawn::BeginPlay()
|
||||
@@ -44,10 +56,42 @@ void ASpaceshipPawn::Tick(float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
|
||||
if (!CurrentVelocity.IsZero())
|
||||
// Handle thrust deceleration when not pressing throttle
|
||||
if (!bThrottlePressed)
|
||||
{
|
||||
FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);
|
||||
SetActorLocation(NewLocation);
|
||||
CurrentThrust = FMath::FInterpTo(CurrentThrust, 0.0f, DeltaTime, ThrustDeceleration);
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentThrust = FMath::FInterpTo(CurrentThrust, TargetThrust, DeltaTime, ThrustAcceleration);
|
||||
}
|
||||
|
||||
// Calculate movement
|
||||
FVector ThrustDirection = GetActorForwardVector();
|
||||
FVector ThrustForce = ThrustDirection * CurrentThrust;
|
||||
|
||||
// Apply drag
|
||||
FVector DragForce = -CurrentVelocity * DragCoefficient;
|
||||
|
||||
// Update velocity
|
||||
CurrentVelocity += (ThrustForce + DragForce) * DeltaTime;
|
||||
|
||||
// Update position
|
||||
FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);
|
||||
SetActorLocation(NewLocation, true);
|
||||
|
||||
// Smooth rotation using quaternion interpolation
|
||||
FQuat TargetQuat = TargetRotation.Quaternion();
|
||||
CurrentRotation = FQuat::Slerp(CurrentRotation, TargetQuat, RotationSpeed * DeltaTime);
|
||||
SetActorRotation(CurrentRotation);
|
||||
|
||||
// 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()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,45 +101,54 @@ void ASpaceshipPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputCompo
|
||||
|
||||
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
|
||||
{
|
||||
// Binding the Movement action
|
||||
EnhancedInputComponent->BindAction(MovementAction, ETriggerEvent::Triggered, this, &ASpaceshipPawn::Move);
|
||||
// Bind both Hold and Released events for throttle
|
||||
EnhancedInputComponent->BindAction(ThrottleAction, ETriggerEvent::Started, this, &ASpaceshipPawn::HandleThrottleStarted);
|
||||
EnhancedInputComponent->BindAction(ThrottleAction, ETriggerEvent::Completed, this, &ASpaceshipPawn::HandleThrottleReleased);
|
||||
|
||||
// Binding the Look action
|
||||
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ASpaceshipPawn::Look);
|
||||
// Bind mouse control
|
||||
EnhancedInputComponent->BindAction(MouseControlAction, ETriggerEvent::Started, this, &ASpaceshipPawn::HandleMouseControl);
|
||||
|
||||
// Binding the Fire action
|
||||
EnhancedInputComponent->BindAction(FireAction, ETriggerEvent::Triggered, this, &ASpaceshipPawn::Fire);
|
||||
// Bind fire action
|
||||
EnhancedInputComponent->BindAction(FireAction, ETriggerEvent::Triggered, this, &ASpaceshipPawn::HandleFire);
|
||||
}
|
||||
}
|
||||
|
||||
void ASpaceshipPawn::Move(const FInputActionValue& Value)
|
||||
// Split the throttle handling into two functions
|
||||
void ASpaceshipPawn::HandleThrottleStarted(const FInputActionValue& Value)
|
||||
{
|
||||
const FVector2D MovementVector = Value.Get<FVector2D>();
|
||||
|
||||
CurrentVelocity = FVector(
|
||||
MovementVector.X * MovementSpeed,
|
||||
MovementVector.Y * MovementSpeed,
|
||||
0.0f
|
||||
);
|
||||
const float ThrottleValue = Value.Get<float>();
|
||||
bThrottlePressed = true;
|
||||
TargetThrust = ThrottleValue * MaxThrust;
|
||||
}
|
||||
|
||||
void ASpaceshipPawn::Look(const FInputActionValue& Value)
|
||||
void ASpaceshipPawn::HandleThrottleReleased(const FInputActionValue& Value)
|
||||
{
|
||||
const FVector2D LookAxisVector = Value.Get<FVector2D>();
|
||||
|
||||
// Yaw rotation (left/right)
|
||||
AddActorLocalRotation(FRotator(0.0f, LookAxisVector.X * RotationSpeed * GetWorld()->GetDeltaSeconds(), 0.0f));
|
||||
|
||||
// Pitch rotation (up/down) for camera
|
||||
float NewPitch = CameraSpringArm->GetRelativeRotation().Pitch +
|
||||
LookAxisVector.Y * RotationSpeed * GetWorld()->GetDeltaSeconds();
|
||||
NewPitch = FMath::Clamp(NewPitch, -80.0f, 80.0f);
|
||||
CameraSpringArm->SetRelativeRotation(FRotator(NewPitch, 0.0f, 0.0f));
|
||||
bThrottlePressed = false;
|
||||
}
|
||||
|
||||
void ASpaceshipPawn::Fire(const FInputActionValue& Value)
|
||||
void ASpaceshipPawn::HandleMouseControl(const FInputActionValue& Value)
|
||||
{
|
||||
const FVector2D MouseValue = Value.Get<FVector2D>();
|
||||
|
||||
// Get current rotation
|
||||
FRotator CurrentRot = GetActorRotation();
|
||||
|
||||
// Calculate new rotation values
|
||||
float NewPitch = CurrentRot.Pitch + (-MouseValue.Y * RotationSpeed * GetWorld()->GetDeltaSeconds());
|
||||
float NewYaw = CurrentRot.Yaw + (MouseValue.X * RotationSpeed * GetWorld()->GetDeltaSeconds());
|
||||
|
||||
// Clamp pitch to prevent flipping
|
||||
NewPitch = FMath::ClampAngle(NewPitch, -85.0f, 85.0f);
|
||||
|
||||
// Set target rotation
|
||||
TargetRotation = FRotator(NewPitch, NewYaw, CurrentRot.Roll);
|
||||
|
||||
// Update camera spring arm rotation to match
|
||||
CameraSpringArm->SetRelativeRotation(FRotator(NewPitch * 0.3f, 0.0f, 0.0f));
|
||||
}
|
||||
|
||||
void ASpaceshipPawn::HandleFire(const FInputActionValue& Value)
|
||||
{
|
||||
// Implementation remains the same as before
|
||||
UWorld* World = GetWorld();
|
||||
if (World)
|
||||
{
|
||||
@@ -110,7 +163,7 @@ void ASpaceshipPawn::Fire(const FInputActionValue& Value)
|
||||
SpawnParams.Owner = this;
|
||||
SpawnParams.Instigator = GetInstigator();
|
||||
|
||||
ASpaceshipProjectile* Projectile = World->SpawnActor<ASpaceshipProjectile>(
|
||||
World->SpawnActor<ASpaceshipProjectile>(
|
||||
ASpaceshipProjectile::StaticClass(),
|
||||
SpawnLocation,
|
||||
SpawnRotation,
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
// Components
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
|
||||
class UStaticMeshComponent* ShipMesh;
|
||||
|
||||
@@ -32,25 +33,42 @@ protected:
|
||||
class UInputMappingContext* DefaultMappingContext;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
||||
class UInputAction* MovementAction;
|
||||
class UInputAction* ThrottleAction;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
||||
class UInputAction* LookAction;
|
||||
class UInputAction* MouseControlAction;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
||||
class UInputAction* FireAction;
|
||||
|
||||
// Movement Parameters
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
float MovementSpeed = 1000.0f;
|
||||
float MaxThrust = 2000.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
float ThrustAcceleration = 500.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
float ThrustDeceleration = 200.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
float RotationSpeed = 100.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||
float DragCoefficient = 0.1f;
|
||||
|
||||
// Input functions
|
||||
void Move(const FInputActionValue& Value);
|
||||
void Look(const FInputActionValue& Value);
|
||||
void Fire(const FInputActionValue& Value);
|
||||
void HandleThrottleStarted(const FInputActionValue& Value);
|
||||
void HandleThrottleReleased(const FInputActionValue& Value);
|
||||
void HandleMouseControl(const FInputActionValue& Value);
|
||||
void HandleFire(const FInputActionValue& Value);
|
||||
|
||||
private:
|
||||
// Movement state
|
||||
float CurrentThrust;
|
||||
float TargetThrust;
|
||||
bool bThrottlePressed;
|
||||
FVector CurrentVelocity;
|
||||
FRotator TargetRotation;
|
||||
FQuat CurrentRotation;
|
||||
};
|
||||
Reference in New Issue
Block a user