tengri/Source/TengriPlatformer/Movement/TengriMovementComponent.h

104 lines
3.7 KiB
C++

// Source/TengriPlatformer/Movement/TengriMovementComponent.h
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "TengriPlatformer/Movement/Core/TengriMovementConfig.h"
#include "TengriMovementComponent.generated.h"
class UCapsuleComponent;
/**
* Custom movement component for deterministic 3D platformer physics.
* Handles acceleration, friction, gravity, collision, and ground snapping.
*/
UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class TENGRIPLATFORMER_API UTengriMovementComponent : public UActorComponent
{
GENERATED_BODY()
public:
UTengriMovementComponent();
protected:
virtual void BeginPlay() override;
public:
virtual void TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction) override;
// ========================================================================
// BLUEPRINT API
// ========================================================================
/**
* Sets the movement input vector. Call every frame from PlayerController.
* @param NewInput - Raw input (will be clamped to 1.0 and Z zeroed)
*/
UFUNCTION(BlueprintCallable, Category = "Tengri Movement")
void SetInputVector(FVector NewInput);
// ========================================================================
// CONFIGURATION
// ========================================================================
/** Movement parameters data asset */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tengri Movement")
TObjectPtr<UTengriMovementConfig> MovementConfig;
// ========================================================================
// RUNTIME STATE
// ========================================================================
/** Current velocity in cm/s */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Tengri Movement|State")
FVector Velocity;
/** True when character is on walkable ground */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Tengri Movement|State")
bool bIsGrounded = false;
/** Cached surface thresholds (cosines) for performance */
UPROPERTY(VisibleAnywhere, Category = "Tengri Movement|Debug")
FSurfaceThresholds CachedThresholds;
private:
// ========================================================================
// INTERNAL STATE
// ========================================================================
UPROPERTY()
TObjectPtr<UCapsuleComponent> OwnerCapsule;
/** Normalized input vector (Z always 0) */
FVector InputVector = FVector::ZeroVector;
// ========================================================================
// INITIALIZATION
// ========================================================================
void InitializeSystem();
// ========================================================================
// MOVEMENT PHASES
// ========================================================================
/** Phase 1: Apply acceleration toward input direction or friction to stop */
void ApplyAccelerationAndFriction(float DeltaTime);
/** Phase 2: Rotate character to face movement direction */
void ApplyRotation(float DeltaTime) const;
/** Phase 3: Apply gravity when airborne */
void ApplyGravity(float DeltaTime);
/** Phase 4: Resolve movement with collision */
FVector ResolveMovementWithCollision(float DeltaTime);
/** Phase 5: Snap to ground to prevent slope jitter */
bool PerformGroundSnapping(FVector& InOutLocation, FHitResult& OutSnapHit) const;
/** Phase 6: Update grounded state based on collision results */
void UpdateGroundedState(bool bMoveBlocked, float HitNormalZ, bool bJustSnapped);
};