Files
Rainer LeitandClaude Fable 5.1 4f2c55cd2a Step 1: the Salty project, two modules, tests and the gym
Salty.uproject (UE 5.8) from the Third Person template with class redirects, the SaltyCore and Salty modules,
the three build targets, USaltyAssetManager calling InitGlobalData, Config/Tags with the 23 root namespaces,
Scripts/run-tests.sh, build.sh and Authoring/create_gym.py, L_Gym, Git LFS attributes and the placeholder test.
Template variants kept as reference (D-41). The four Fab packs stay out of the repository for now (~10 GB).
The editor serves the engine MCP plugin on 127.0.0.1:8000 through DefaultEditorPerProjectUserSettings.ini.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 20:10:43 +03:00

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);
}
}