Clamp position when character's reach max distance apart so they are always in camera view

Clamp position when character's reach max distance apart so they are always in camera view
This commit is contained in:
Kevin Poretti 2022-01-16 21:38:43 -05:00
parent 4d10d9cb32
commit 0942a3a1c6
6 changed files with 133 additions and 27 deletions

View File

@ -8,17 +8,20 @@
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "PaperFlipbookComponent.h"
#include "Componenets/KOFCharacterMovementComponent.h"
#include "GameModes/KOFDefaultGameMode.h"
DEFINE_LOG_CATEGORY_STATIC(SideScrollerCharacter, Log, All);
//////////////////////////////////////////////////////////////////////////
// ASideScroller2DCharacter
AKOFBaseCharacter::AKOFBaseCharacter()
AKOFBaseCharacter::AKOFBaseCharacter(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer.SetDefaultSubobjectClass<UKOFCharacterMovementComponent>(ACharacter::CharacterMovementComponentName))
{
// Use only Yaw from the controller and ignore the rest of the rotation.
bUseControllerRotationPitch = false;
bUseControllerRotationYaw = true;
bUseControllerRotationYaw = false;
bUseControllerRotationRoll = false;
// Set the size of our collision capsule.
@ -29,7 +32,7 @@ AKOFBaseCharacter::AKOFBaseCharacter()
// Configure character movement
GetCharacterMovement()->GravityScale = 2.0f;
GetCharacterMovement()->AirControl = 0.80f;
GetCharacterMovement()->AirControl = 0.0f;
GetCharacterMovement()->JumpZVelocity = 1000.f;
GetCharacterMovement()->GroundFriction = 3.0f;
GetCharacterMovement()->MaxWalkSpeed = 600.0f;
@ -150,7 +153,7 @@ void AKOFBaseCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerI
void AKOFBaseCharacter::MoveRight(float Value)
{
/*UpdateChar();*/
// Apply the input to the character motion
AddMovementInput(FVector(0.0f, 1.0f, 0.0f), Value);
}
@ -159,22 +162,5 @@ void AKOFBaseCharacter::UpdateCharacter()
{
// Update animation to match the motion
UpdateAnimation();
/*
// Now setup the rotation of the controller based on the direction we are travelling
const FVector PlayerVelocity = GetVelocity();
float TravelDirection = PlayerVelocity.Y;
// Set the rotation so that the character faces his direction of travel.
if (Controller != nullptr)
{
if (TravelDirection < 0.0f)
{
Controller->SetControlRotation(FRotator(0.0, -90.0f, 0.0f));
}
else if (TravelDirection > 0.0f)
{
Controller->SetControlRotation(FRotator(0.0f, 90.0f, 0.0));
}
}
*/
}
}

View File

@ -0,0 +1,76 @@
#include "Componenets/KOFCharacterMovementComponent.h"
#include "GameModes/KOFDefaultGameMode.h"
UKOFCharacterMovementComponent::UKOFCharacterMovementComponent()
{
PrimaryComponentTick.bCanEverTick = true;
}
void UKOFCharacterMovementComponent::TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
AKOFBaseCharacter* Owner = Cast<AKOFBaseCharacter>(GetOwner());
if(!Owner)
{
UE_LOG(LogTemp, Error, TEXT("AKOFCharacterMovementComponent::PostPhysicsTickComponent - could not get the owner"));
return;
}
AKOFDefaultGameMode* GameMode = Cast<AKOFDefaultGameMode>(GetWorld()->GetAuthGameMode());
if(!GameMode)
{
UE_LOG(LogTemp, Error, TEXT("AKOFCharacterMovementComponent::PostPhysicsTickComponent - could not get the game mode"));
return;
}
AKOFBaseCharacter* Opponent = GameMode->GetCurrentOpponent(Owner->IsPossessedByPlayer1());
if(Opponent)
{
float HalfYDistance = GameMode->GetMaxAllowedDistanceFromOpponent() / 2.0f;
float YMidpoint = (Owner->GetActorLocation().Y + Opponent->GetActorLocation().Y) / 2.0f;
float AdjustedY = FMath::Clamp(Owner->GetActorLocation().Y, YMidpoint - HalfYDistance, YMidpoint + HalfYDistance);
FVector CurrentLoc = Owner->GetActorLocation();
Owner->SetActorLocation(FVector(CurrentLoc.X, AdjustedY, CurrentLoc.Z));
}
}
void UKOFCharacterMovementComponent::PostPhysicsTickComponent(float DeltaTime,
FCharacterMovementComponentPostPhysicsTickFunction& ThisTickFunction)
{
Super::PostPhysicsTickComponent(DeltaTime, ThisTickFunction);
AKOFBaseCharacter* Owner = Cast<AKOFBaseCharacter>(GetOwner());
if(!Owner)
{
UE_LOG(LogTemp, Error, TEXT("AKOFCharacterMovementComponent::PostPhysicsTickComponent - could not get the owner"));
return;
}
AKOFDefaultGameMode* GameMode = Cast<AKOFDefaultGameMode>(GetWorld()->GetAuthGameMode());
if(!GameMode)
{
UE_LOG(LogTemp, Error, TEXT("AKOFCharacterMovementComponent::PostPhysicsTickComponent - could not get the game mode"));
return;
}
AKOFBaseCharacter* Opponent = GameMode->GetCurrentOpponent(Owner->IsPossessedByPlayer1());
if(Opponent)
{
float YDistance = FMath::Abs(Opponent->GetActorLocation().Y - Owner->GetActorLocation().Y);
float HalfYDistance = YDistance / 2.0f;
float YMidpoint = (Owner->GetActorLocation().Y + Opponent->GetActorLocation().Y) / 2.0f;
float AdjustedY = FMath::Clamp(Owner->GetActorLocation().Y, YMidpoint - HalfYDistance, YMidpoint + HalfYDistance);
FVector CurrentLoc = Owner->GetActorLocation();
Owner->SetActorLocation(FVector(CurrentLoc.X, AdjustedY, CurrentLoc.Z));
}
}

View File

@ -9,7 +9,7 @@ AKOFDefaultGameMode::AKOFDefaultGameMode()
{
NumCharactersPerTeam = 3;
MaxDistance = 700.0f;
MaxAllowedDistanceFromOpponent = 700.0f;
StartY = 250.0f;
}
@ -18,6 +18,7 @@ void AKOFDefaultGameMode::InitTeams()
for (TSubclassOf<AKOFBaseCharacter> CharacterTemplate : P1TeamTemplate)
{
AKOFBaseCharacter* Temp = GetWorld()->SpawnActor<AKOFBaseCharacter>(CharacterTemplate, FVector(0.0f, -StartY, 204.6241f), FRotator(0.0f, 90.0f, 0.0f));
Temp->SetIsPossesedByPlayer1(true);
if(Temp)
{
P1Team.Add(Temp);
@ -27,7 +28,7 @@ void AKOFDefaultGameMode::InitTeams()
for (TSubclassOf<AKOFBaseCharacter> CharacterTemplate : P2TeamTemplate)
{
AKOFBaseCharacter* Temp = GetWorld()->SpawnActor<AKOFBaseCharacter>(CharacterTemplate, FVector(0.0f, StartY, 204.6241f), FRotator(0.0f, -90.0f, 0.0f));
Temp->AutoPossessPlayer = EAutoReceiveInput::Player1;
Temp->SetIsPossesedByPlayer1(false);
if(Temp)
{
P2Team.Add(Temp);

View File

@ -51,6 +51,9 @@ protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Animations)
class UPaperFlipbook* IdleAnimation;
UPROPERTY(BlueprintReadOnly)
bool bIsPossesedByPlayer1;
/** Called to choose the correct animation to play based on the character's movement state */
void UpdateAnimation();
@ -64,7 +67,21 @@ protected:
// End of APawn interface
public:
AKOFBaseCharacter();
AKOFBaseCharacter(const FObjectInitializer& ObjectInitializer);
FORCEINLINE class UPaperFlipbookComponent* GetShadow() const { return Shadow; }
/**
* Returns whether or not this player is possessed by player 1
*
* @returns true is possessed by player 1, false if possessed by player 2
*/
FORCEINLINE bool IsPossessedByPlayer1() const { return bIsPossesedByPlayer1; }
/**
* Sets which player this character is possesed by.
*
* @param bIsPlayer1 true is possessed by player 1, false if possessed by player 2
*/
FORCEINLINE void SetIsPossesedByPlayer1(bool bIsPlayer1) { bIsPossesedByPlayer1 = bIsPlayer1; }
};

View File

@ -0,0 +1,22 @@
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "KOFCharacterMovementComponent.generated.h"
/**
*
*/
UCLASS()
class KOFFOREVER_API UKOFCharacterMovementComponent : public UCharacterMovementComponent
{
GENERATED_BODY()
UKOFCharacterMovementComponent();
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
virtual void PostPhysicsTickComponent(float DeltaTime, FCharacterMovementComponentPostPhysicsTickFunction& ThisTickFunction) override;
};

View File

@ -28,6 +28,10 @@ public:
// this will need to change when we actually have real time character switching
AKOFBaseCharacter* GetP2CurrentCharacter() { return P2Team.Num() > 0 ? P2Team[0] : nullptr; }
AKOFBaseCharacter* GetCurrentOpponent(bool bIsPlayer1) { return bIsPlayer1 ? GetP2CurrentCharacter() : GetP1CurrentCharacter(); }
FORCEINLINE float GetMaxAllowedDistanceFromOpponent() { return MaxAllowedDistanceFromOpponent; }
protected:
/** Number of characters on a single player's team */
@ -36,7 +40,7 @@ protected:
/** Max distance the currently controlled player characters can be from one another */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Stage")
float MaxDistance;
float MaxAllowedDistanceFromOpponent;
/** Y offset from origin where character's will be spawned */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Stage")