Setup game mode so characters are spawned automatically rather than placing them in the world

Setup game mode so characters are spawned automatically rather than placing them in the world
This commit is contained in:
Kevin Poretti 2022-01-15 23:41:56 -05:00
parent 6e0c181014
commit 4d10d9cb32
13 changed files with 278 additions and 24 deletions

View File

@ -1,7 +1,7 @@
[/Script/EngineSettings.GameMapsSettings]
EditorStartupMap=/Game/Maps/TestMap.TestMap
EditorStartupMap=/Game/Maps/DebugStage.DebugStage
LocalMapOptions=
TransitionMap=
bUseSplitscreen=True

Binary file not shown.

BIN
KOFForever/Content/Debug/BP_DebugGameMode.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
KOFForever/Content/Maps/DebugStage.umap (Stored with Git LFS) Normal file

Binary file not shown.

BIN
KOFForever/Content/Maps/TrainingStage.umap (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -10,7 +10,8 @@
"LoadingPhase": "Default",
"AdditionalDependencies": [
"Paper2D",
"Engine"
"Engine",
"CoreUObject"
]
}
]

View File

@ -5,6 +5,8 @@
#include "DrawDebugHelpers.h"
#include "Camera/CameraComponent.h"
#include "Character/KOFBaseCharacter.h"
#include "GameModes/KOFDefaultGameMode.h"
AKOFDefaultCamera::AKOFDefaultCamera()
{
@ -16,12 +18,23 @@ AKOFDefaultCamera::AKOFDefaultCamera()
HeightOffset = 60.0f;
ZAveragingFactor = 2.0f;
MovementYDistanceThreshold = 500.0f;
}
void AKOFDefaultCamera::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
// NOTE(kevin): This will only return the game mode if we are the server. Since this game is local only we should always
// be both server and client
AKOFDefaultGameMode* GameMode = Cast<AKOFDefaultGameMode>(GetWorld()->GetAuthGameMode());
if(GameMode)
{
AKOFBaseCharacter* P1 = GameMode->GetP1CurrentCharacter();
AKOFBaseCharacter* P2 = GameMode->GetP2CurrentCharacter();
check(P1);
check(P2);
@ -34,3 +47,50 @@ void AKOFDefaultCamera::Tick(float DeltaSeconds)
// set FOV
}
}
void AKOFDefaultCamera::UpdateCamera()
{
// NOTE(kevin): This will only return the game mode if we are the server. Since this game is local only we should always
// be both server and client
AKOFDefaultGameMode* GameMode = Cast<AKOFDefaultGameMode>(GetWorld()->GetAuthGameMode());
if(GameMode)
{
AKOFBaseCharacter* P1 = GameMode->GetP1CurrentCharacter();
AKOFBaseCharacter* P2 = GameMode->GetP2CurrentCharacter();
FVector P1Loc = P1->GetActorLocation();
FVector P2Loc = P2->GetActorLocation();
FVector CameraLoc = GetActorLocation();
float HalfMoveYThreshold = MovementYDistanceThreshold / 2.0f;
float YDistance = FMath::Abs(P1Loc.Y - P2Loc.Y);
/**
* If one of the characters starts to move far enough to either side of the camera (determined by Movement Y distance threshold),
* then start pushing the camera in that same direction
*/
/*
if((P1Loc.Y < CameraLoc.Y - HalfMoveYThreshold || P2Loc.Y < CameraLoc.Y - HalfMoveYThreshold) ||
(P1Loc.Y > CameraLoc.Y + HalfMoveYThreshold || P2Loc.Y > CameraLoc.Y + HalfMoveYThreshold))
{
//FVector MidPoint = FVector(CameraLoc.X, (P1Loc.Y + P2Loc.Y) / 2.0f, ((P1Loc.Z + P2Loc.Z) / ZAveragingFactor) + HeightOffset);
FVector MidPoint = FVector(CameraLoc.X, (P1Loc.Y + P2Loc.Y) / 2.0f, CameraLoc.Z);
SetActorLocation(MidPoint);
}
*/
// leftest = MaxF(float32(Min(s.stage.p[0].startx, s.stage.p[1].startx))*s.stage.localscl,-(float32(s.gameWidth)/2)/s.cam.BaseScale()+s.screenleft) - ox
// rightest = MinF(float32(Max(s.stage.p[0].startx, s.stage.p[1].startx))*s.stage.localscl, (float32(s.gameWidth)/2)/s.cam.BaseScale()-s.screenright) - ox
float MoveRightVal = P1Loc.Y > CameraLoc.Y + HalfMoveYThreshold ? P1Loc.Y - (CameraLoc.Y + HalfMoveYThreshold) : 0.0f;
float MoveLeftVal = P1Loc.Y < CameraLoc.Y - HalfMoveYThreshold ? P1Loc.Y - (CameraLoc.Y - HalfMoveYThreshold) : 0.0f;
FVector NewLocation = FVector(CameraLoc.X, (CameraLoc.Y + MoveRightVal - MoveLeftVal), CameraLoc.Z);
}
}

View File

@ -85,11 +85,11 @@ void AKOFBaseCharacter::UpdateAnimation()
UPaperFlipbook* DesiredAnimation = IdleAnimation;
if(PlayerSpeedSqr > 0.0f)
{
if (TravelDirection < 0.0f)
if (TravelDirection > 0.0f)
{
DesiredAnimation = WalkFwdAnimation;
}
else if (TravelDirection > 0.0f)
else if (TravelDirection < 0.0f)
{
DesiredAnimation = WalkBackAnimation;
}
@ -152,7 +152,7 @@ void AKOFBaseCharacter::MoveRight(float Value)
/*UpdateChar();*/
// Apply the input to the character motion
AddMovementInput(FVector(0.0f, -1.0f, 0.0f), Value);
AddMovementInput(FVector(0.0f, 1.0f, 0.0f), Value);
}
void AKOFBaseCharacter::UpdateCharacter()

View File

@ -0,0 +1,64 @@
#include "GameModes/KOFDefaultGameMode.h"
#include "Kismet/GameplayStatics.h"
AKOFDefaultGameMode::AKOFDefaultGameMode()
{
NumCharactersPerTeam = 3;
MaxDistance = 700.0f;
StartY = 250.0f;
}
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));
if(Temp)
{
P1Team.Add(Temp);
}
}
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;
if(Temp)
{
P2Team.Add(Temp);
}
}
}
void AKOFDefaultGameMode::StartPlay()
{
Super::StartPlay();
InitTeams();
// is this the right place to do this?
APlayerController* PC1 = UGameplayStatics::GetPlayerController(GetWorld(), 0);
if(PC1)
{
AKOFBaseCharacter* P1 = GetP1CurrentCharacter();
if(P1)
{
PC1->Possess(P1);
}
}
APlayerController* PC2 = UGameplayStatics::GetPlayerController(GetWorld(), 1);
if(PC2)
{
AKOFBaseCharacter* P2 = GetP1CurrentCharacter();
if(P2)
{
PC2->Possess(P2);
}
}
}

View File

@ -0,0 +1,23 @@
#include "GameModes/KOFTeam.h"
#include "Character/KOFBaseCharacter.h"
AKOFBaseCharacter* UKOFTeam::GetCurrentCharacter()
{
return Characters.Num() > 0 ? Characters[0] : nullptr;
}
void UKOFTeam::InitTeam()
{
for (TSubclassOf<AKOFBaseCharacter> CharacterTemplate : CharacterTemplates)
{
AKOFBaseCharacter* Temp = NewObject<AKOFBaseCharacter>(CharacterTemplate);
if(Temp)
{
Characters.Add(Temp);
}
}
}

View File

@ -44,13 +44,10 @@ protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = CameraSettings)
float ZAveragingFactor;
/**
* How far the character's have to be apart before the camera moves to keep both in frame
*/
float MovementYDistanceThreshold;
// References to player main character's
// eventually we want to spawn all the player's characters from game mode? and then we can get the references to
// P1 and P2 from there. For now we'll just set the references manually in the level
UPROPERTY(EditAnywhere)
AActor* P1;
UPROPERTY(EditAnywhere)
AActor* P2;
void UpdateCamera();
};

View File

@ -0,0 +1,62 @@
#pragma once
#include "CoreMinimal.h"
#include "KOFTeam.h"
#include "Character/KOFBaseCharacter.h"
#include "GameFramework/GameModeBase.h"
#include "KOFDefaultGameMode.generated.h"
/**
*
*/
UCLASS()
class KOFFOREVER_API AKOFDefaultGameMode : public AGameModeBase
{
GENERATED_BODY()
public:
AKOFDefaultGameMode();
TArray<AKOFBaseCharacter*>& GetP1Team() { return P1Team; }
TArray<AKOFBaseCharacter*>& GetP2Team() { return P2Team; }
// this will need to change when we actually have real time character switching
AKOFBaseCharacter* GetP1CurrentCharacter() { return P1Team.Num() > 0 ? P1Team[0] : nullptr; }
// this will need to change when we actually have real time character switching
AKOFBaseCharacter* GetP2CurrentCharacter() { return P2Team.Num() > 0 ? P2Team[0] : nullptr; }
protected:
/** Number of characters on a single player's team */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Settings|Team")
int32 NumCharactersPerTeam;
/** Max distance the currently controlled player characters can be from one another */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Stage")
float MaxDistance;
/** Y offset from origin where character's will be spawned */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Stage")
float StartY;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Settings|Team")
TArray<TSubclassOf<AKOFBaseCharacter>> P1TeamTemplate;
/** List of references to the player's team members */
UPROPERTY(BlueprintReadOnly)
TArray<AKOFBaseCharacter*> P1Team;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Settings|Team")
TArray<TSubclassOf<AKOFBaseCharacter>> P2TeamTemplate;
/** List of references to the player's team members */
UPROPERTY(BlueprintReadOnly)
TArray<AKOFBaseCharacter*> P2Team;
void InitTeams();
virtual void StartPlay() override;
};

View File

@ -0,0 +1,38 @@
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "KOFTeam.generated.h"
class AKOFBaseCharacter;
/**
*
*/
UCLASS(BlueprintType, Blueprintable)
class KOFFOREVER_API UKOFTeam : public UObject
{
GENERATED_BODY()
public:
/**
* Returns the character on this team that is currently on stage being controlled by the player
*/
AKOFBaseCharacter* GetCurrentCharacter();
void InitTeam();
protected:
/**
* List of character templates to spawn the player's team when the match begins.
*
* This will eventually get set by the player's choices in the character select menu
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Characters")
TArray<TSubclassOf<AKOFBaseCharacter>> CharacterTemplates;
/** List of references to the player's team members */
UPROPERTY(BlueprintReadOnly, Category="Characters")
TArray<AKOFBaseCharacter*> Characters;
};