Implement better throttle system
This commit is contained in:
Binary file not shown.
BIN
Content/Input/IA_MouseControl.uasset
LFS
Normal file
BIN
Content/Input/IA_MouseControl.uasset
LFS
Normal file
Binary file not shown.
BIN
Content/Input/IA_Throttle.uasset
LFS
Normal file
BIN
Content/Input/IA_Throttle.uasset
LFS
Normal file
Binary file not shown.
Binary file not shown.
@@ -10,20 +10,32 @@ ASpaceshipPawn::ASpaceshipPawn()
|
|||||||
{
|
{
|
||||||
PrimaryActorTick.bCanEverTick = true;
|
PrimaryActorTick.bCanEverTick = true;
|
||||||
|
|
||||||
// Create and setup the ship's mesh
|
// Create ship mesh
|
||||||
ShipMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ShipMesh"));
|
ShipMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ShipMesh"));
|
||||||
RootComponent = 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 = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));
|
||||||
CameraSpringArm->SetupAttachment(RootComponent);
|
CameraSpringArm->SetupAttachment(RootComponent);
|
||||||
CameraSpringArm->TargetArmLength = 400.0f;
|
CameraSpringArm->TargetArmLength = 400.0f;
|
||||||
CameraSpringArm->bEnableCameraLag = true;
|
CameraSpringArm->bEnableCameraLag = true;
|
||||||
CameraSpringArm->CameraLagSpeed = 3.0f;
|
CameraSpringArm->CameraLagSpeed = 3.0f;
|
||||||
|
CameraSpringArm->bEnableCameraRotationLag = true;
|
||||||
|
CameraSpringArm->CameraRotationLagSpeed = 10.0f;
|
||||||
|
|
||||||
// Create and setup the camera
|
// Create camera
|
||||||
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
|
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
|
||||||
Camera->SetupAttachment(CameraSpringArm, USpringArmComponent::SocketName);
|
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()
|
void ASpaceshipPawn::BeginPlay()
|
||||||
@@ -44,10 +56,42 @@ void ASpaceshipPawn::Tick(float DeltaTime)
|
|||||||
{
|
{
|
||||||
Super::Tick(DeltaTime);
|
Super::Tick(DeltaTime);
|
||||||
|
|
||||||
if (!CurrentVelocity.IsZero())
|
// Handle thrust deceleration when not pressing throttle
|
||||||
|
if (!bThrottlePressed)
|
||||||
{
|
{
|
||||||
|
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);
|
FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);
|
||||||
SetActorLocation(NewLocation);
|
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))
|
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
|
||||||
{
|
{
|
||||||
// Binding the Movement action
|
// Bind both Hold and Released events for throttle
|
||||||
EnhancedInputComponent->BindAction(MovementAction, ETriggerEvent::Triggered, this, &ASpaceshipPawn::Move);
|
EnhancedInputComponent->BindAction(ThrottleAction, ETriggerEvent::Started, this, &ASpaceshipPawn::HandleThrottleStarted);
|
||||||
|
EnhancedInputComponent->BindAction(ThrottleAction, ETriggerEvent::Completed, this, &ASpaceshipPawn::HandleThrottleReleased);
|
||||||
|
|
||||||
// Binding the Look action
|
// Bind mouse control
|
||||||
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ASpaceshipPawn::Look);
|
EnhancedInputComponent->BindAction(MouseControlAction, ETriggerEvent::Started, this, &ASpaceshipPawn::HandleMouseControl);
|
||||||
|
|
||||||
// Binding the Fire action
|
// Bind fire action
|
||||||
EnhancedInputComponent->BindAction(FireAction, ETriggerEvent::Triggered, this, &ASpaceshipPawn::Fire);
|
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>();
|
const float ThrottleValue = Value.Get<float>();
|
||||||
|
bThrottlePressed = true;
|
||||||
CurrentVelocity = FVector(
|
TargetThrust = ThrottleValue * MaxThrust;
|
||||||
MovementVector.X * MovementSpeed,
|
|
||||||
MovementVector.Y * MovementSpeed,
|
|
||||||
0.0f
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASpaceshipPawn::Look(const FInputActionValue& Value)
|
void ASpaceshipPawn::HandleThrottleReleased(const FInputActionValue& Value)
|
||||||
{
|
{
|
||||||
const FVector2D LookAxisVector = Value.Get<FVector2D>();
|
bThrottlePressed = false;
|
||||||
|
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
UWorld* World = GetWorld();
|
||||||
if (World)
|
if (World)
|
||||||
{
|
{
|
||||||
@@ -110,7 +163,7 @@ void ASpaceshipPawn::Fire(const FInputActionValue& Value)
|
|||||||
SpawnParams.Owner = this;
|
SpawnParams.Owner = this;
|
||||||
SpawnParams.Instigator = GetInstigator();
|
SpawnParams.Instigator = GetInstigator();
|
||||||
|
|
||||||
ASpaceshipProjectile* Projectile = World->SpawnActor<ASpaceshipProjectile>(
|
World->SpawnActor<ASpaceshipProjectile>(
|
||||||
ASpaceshipProjectile::StaticClass(),
|
ASpaceshipProjectile::StaticClass(),
|
||||||
SpawnLocation,
|
SpawnLocation,
|
||||||
SpawnRotation,
|
SpawnRotation,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void BeginPlay() override;
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
|
// Components
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
|
||||||
class UStaticMeshComponent* ShipMesh;
|
class UStaticMeshComponent* ShipMesh;
|
||||||
|
|
||||||
@@ -32,25 +33,42 @@ protected:
|
|||||||
class UInputMappingContext* DefaultMappingContext;
|
class UInputMappingContext* DefaultMappingContext;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
||||||
class UInputAction* MovementAction;
|
class UInputAction* ThrottleAction;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
||||||
class UInputAction* LookAction;
|
class UInputAction* MouseControlAction;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
||||||
class UInputAction* FireAction;
|
class UInputAction* FireAction;
|
||||||
|
|
||||||
|
// Movement Parameters
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
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")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||||
float RotationSpeed = 100.0f;
|
float RotationSpeed = 100.0f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
|
||||||
|
float DragCoefficient = 0.1f;
|
||||||
|
|
||||||
// Input functions
|
// Input functions
|
||||||
void Move(const FInputActionValue& Value);
|
void HandleThrottleStarted(const FInputActionValue& Value);
|
||||||
void Look(const FInputActionValue& Value);
|
void HandleThrottleReleased(const FInputActionValue& Value);
|
||||||
void Fire(const FInputActionValue& Value);
|
void HandleMouseControl(const FInputActionValue& Value);
|
||||||
|
void HandleFire(const FInputActionValue& Value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Movement state
|
||||||
|
float CurrentThrust;
|
||||||
|
float TargetThrust;
|
||||||
|
bool bThrottlePressed;
|
||||||
FVector CurrentVelocity;
|
FVector CurrentVelocity;
|
||||||
|
FRotator TargetRotation;
|
||||||
|
FQuat CurrentRotation;
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user