From 0942a3a1c6382eec09398d4e89e784d7fbe5bb34 Mon Sep 17 00:00:00 2001 From: Kevin Date: Sun, 16 Jan 2022 21:38:43 -0500 Subject: [PATCH] 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 --- .../Private/Character/KOFBaseCharacter.cpp | 32 +++----- .../KOFCharacterMovementComponent.cpp | 76 +++++++++++++++++++ .../Private/GameModes/KOFDefaultGameMode.cpp | 5 +- .../Public/Character/KOFBaseCharacter.h | 19 ++++- .../KOFCharacterMovementComponent.h | 22 ++++++ .../Public/GameModes/KOFDefaultGameMode.h | 6 +- 6 files changed, 133 insertions(+), 27 deletions(-) create mode 100644 KOFForever/Source/KOFForever/Private/Componenets/KOFCharacterMovementComponent.cpp create mode 100644 KOFForever/Source/KOFForever/Public/Componenets/KOFCharacterMovementComponent.h diff --git a/KOFForever/Source/KOFForever/Private/Character/KOFBaseCharacter.cpp b/KOFForever/Source/KOFForever/Private/Character/KOFBaseCharacter.cpp index 000fc00..0ba3926 100644 --- a/KOFForever/Source/KOFForever/Private/Character/KOFBaseCharacter.cpp +++ b/KOFForever/Source/KOFForever/Private/Character/KOFBaseCharacter.cpp @@ -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(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)); - } - } - */ -} \ No newline at end of file +} + \ No newline at end of file diff --git a/KOFForever/Source/KOFForever/Private/Componenets/KOFCharacterMovementComponent.cpp b/KOFForever/Source/KOFForever/Private/Componenets/KOFCharacterMovementComponent.cpp new file mode 100644 index 0000000..87f401e --- /dev/null +++ b/KOFForever/Source/KOFForever/Private/Componenets/KOFCharacterMovementComponent.cpp @@ -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(GetOwner()); + if(!Owner) + { + UE_LOG(LogTemp, Error, TEXT("AKOFCharacterMovementComponent::PostPhysicsTickComponent - could not get the owner")); + return; + } + + AKOFDefaultGameMode* GameMode = Cast(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(GetOwner()); + if(!Owner) + { + UE_LOG(LogTemp, Error, TEXT("AKOFCharacterMovementComponent::PostPhysicsTickComponent - could not get the owner")); + return; + } + + AKOFDefaultGameMode* GameMode = Cast(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)); + } +} diff --git a/KOFForever/Source/KOFForever/Private/GameModes/KOFDefaultGameMode.cpp b/KOFForever/Source/KOFForever/Private/GameModes/KOFDefaultGameMode.cpp index cb54cbd..5b91d5e 100644 --- a/KOFForever/Source/KOFForever/Private/GameModes/KOFDefaultGameMode.cpp +++ b/KOFForever/Source/KOFForever/Private/GameModes/KOFDefaultGameMode.cpp @@ -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 CharacterTemplate : P1TeamTemplate) { AKOFBaseCharacter* Temp = GetWorld()->SpawnActor(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 CharacterTemplate : P2TeamTemplate) { AKOFBaseCharacter* Temp = GetWorld()->SpawnActor(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); diff --git a/KOFForever/Source/KOFForever/Public/Character/KOFBaseCharacter.h b/KOFForever/Source/KOFForever/Public/Character/KOFBaseCharacter.h index e9f7099..21fb04f 100644 --- a/KOFForever/Source/KOFForever/Public/Character/KOFBaseCharacter.h +++ b/KOFForever/Source/KOFForever/Public/Character/KOFBaseCharacter.h @@ -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; } }; diff --git a/KOFForever/Source/KOFForever/Public/Componenets/KOFCharacterMovementComponent.h b/KOFForever/Source/KOFForever/Public/Componenets/KOFCharacterMovementComponent.h new file mode 100644 index 0000000..d1c789c --- /dev/null +++ b/KOFForever/Source/KOFForever/Public/Componenets/KOFCharacterMovementComponent.h @@ -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; +}; diff --git a/KOFForever/Source/KOFForever/Public/GameModes/KOFDefaultGameMode.h b/KOFForever/Source/KOFForever/Public/GameModes/KOFDefaultGameMode.h index 700e020..4a21c11 100644 --- a/KOFForever/Source/KOFForever/Public/GameModes/KOFDefaultGameMode.h +++ b/KOFForever/Source/KOFForever/Public/GameModes/KOFDefaultGameMode.h @@ -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")