test/Source/MyProject/Variant_SideScrolling/SideScrollingCameraManager.cpp

105 lines
3.0 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SideScrollingCameraManager.h"
#include "GameFramework/Pawn.h"
#include "Engine/HitResult.h"
#include "CollisionQueryParams.h"
#include "Engine/World.h"
void ASideScrollingCameraManager::UpdateViewTarget(FTViewTarget& OutVT, float DeltaTime)
{
// ensure the view target is a pawn
APawn* TargetPawn = Cast<APawn>(OutVT.Target);
// is our target valid?
if (IsValid(TargetPawn))
{
// set the view target FOV and rotation
OutVT.POV.Rotation = FRotator(0.0f, -90.0f, 0.0f);
OutVT.POV.FOV = 65.0f;
// cache the current location
FVector CurrentActorLocation = OutVT.Target->GetActorLocation();
// copy the current camera location
FVector CurrentCameraLocation = GetCameraLocation();
// calculate the "zoom distance" - in reality the distance we want to keep to the target
float CurrentY = CurrentZoom + CurrentActorLocation.Y;
// do first-time setup
if (bSetup)
{
// lower the setup flag
bSetup = false;
// initialize the camera viewpoint and return
OutVT.POV.Location.X = CurrentActorLocation.X;
OutVT.POV.Location.Y = CurrentY;
OutVT.POV.Location.Z = CurrentActorLocation.Z + CameraZOffset;
// save the current camera height
CurrentZ = OutVT.POV.Location.Z;
// skip the rest of the calculations
return;
}
// check if the camera needs to update its height
bool bZUpdate = false;
// is the character moving vertically?
if (FMath::IsNearlyZero(TargetPawn->GetVelocity().Z))
{
// determine if we need to do a height update
bZUpdate = FMath::IsNearlyEqual(CurrentZ, CurrentCameraLocation.Z, 25.0f);
} else {
// run a trace below the character to determine if we need to do a height update
FHitResult OutHit;
const FVector End = CurrentActorLocation + FVector(0.0f, 0.0f, -1000.0f);
FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredActor(TargetPawn);
// only update height if we're not about to hit ground
bZUpdate = !GetWorld()->LineTraceSingleByChannel(OutHit, CurrentActorLocation, End, ECC_Visibility, QueryParams);
}
// do we need to do a height update?
if (bZUpdate)
{
// set the height goal from the actor location
CurrentZ = CurrentActorLocation.Z;
} else {
// are we close enough to the target height?
if (FMath::IsNearlyEqual(CurrentZ, CurrentActorLocation.Z, 100.0f))
{
// set the height goal from the actor location
CurrentZ = CurrentActorLocation.Z;
} else {
// blend the height towards the actor location
CurrentZ = FMath::FInterpTo(CurrentZ, CurrentActorLocation.Z, DeltaTime, 2.0f);
}
}
// clamp the X axis to the min and max camera bounds
float CurrentX = FMath::Clamp(CurrentActorLocation.X, CameraXMinBounds, CameraXMaxBounds);
// blend towards the new camera location and update the output
FVector TargetCameraLocation(CurrentX, CurrentY, CurrentZ);
OutVT.POV.Location = FMath::VInterpTo(CurrentCameraLocation, TargetCameraLocation, DeltaTime, 2.0f);
}
}