SubwaySurf minigame, bugfixes

This commit is contained in:
Oleg Petruny 2024-07-24 21:57:25 +02:00
parent 4037fe3f1a
commit d8933a111b
25 changed files with 162 additions and 51 deletions

Binary file not shown.

View File

@ -10,12 +10,9 @@
#include "LevelSequencePlayer.h"
#include "CutsceneManager.h"
#include "MainGameModeBase.h"
void ALevel1::BeginPlay()
{
AMainGameModeBase::leadLevel = this;
ALevelBase::BeginPlay();
TurnLight(false);

View File

@ -3,20 +3,9 @@
#include "Level2.h"
#include "Atmosphere/AtmosphericFog.h"
#include "Components/LightComponent.h"
#include "Engine/DirectionalLight.h"
#include "Engine/SkyLight.h"
#include "LevelSequencePlayer.h"
#include "CutsceneManager.h"
#include "MainGameModeBase.h"
void ALevel2::BeginPlay()
{
AMainGameModeBase::leadLevel = this;
ALevelBase::BeginPlay();
CallNextState();
}

View File

@ -4,17 +4,33 @@
#include "LevelBase.h"
#include "EngineUtils.h"
#include "InputMappingContext.h"
#include "LevelSequencePlayer.h"
#include "CommonFunctions.h"
#include "CustomGameInstanceBase.h"
#include "Interactable/Interactable.h"
#include "Levels/Checkpoint.h"
#include "MainGameModeBase.h"
#include "Minigame/Minigame.h"
#include "PlayerBase.h"
#include "SaveData.h"
void ALevelBase::BeginPlay()
{
AMainGameModeBase::leadLevel = this;
if(auto world = GetWorld())
{
if(auto GI = Cast<UCustomGameInstanceBase>(world->GetGameInstance()))
{
for(TActorIterator<AMinigame> it(GetWorld()); it; ++it)
{
GI->inputContexts.Add(it->GetInputMappings());
}
}
}
ALevelScriptActor::BeginPlay();
BroadcastNewLevelBeginPlay();

View File

@ -15,6 +15,9 @@ public:
UFUNCTION(BlueprintCallable)
inline void CallNextState() { ++state; NextState(); }
UFUNCTION(BlueprintImplementableEvent)
void CallEvent(int32 id);
inline int32 GetState() { return state; };
protected:

View File

@ -76,6 +76,12 @@ void AMainGameModeBase::CallNextLevelState()
leadLevel->CallNextState();
}
void AMainGameModeBase::CallLevelEvent(int32 id)
{
if(leadLevel)
leadLevel->CallEvent(id);
}
void AMainGameModeBase::SwitchCameraMode()
{
static TWeakObjectPtr<APawn> _playerPawn = nullptr;

View File

@ -27,6 +27,8 @@ public:
UFUNCTION(BlueprintCallable)
static void CallNextLevelState();
UFUNCTION(BlueprintCallable)
static void CallLevelEvent(int32 id);
void SwitchCameraMode();

View File

@ -3,14 +3,26 @@
#include "Minigame.h"
#include "InputMappingContext.h"
AMinigame::AMinigame()
: AActor()
{
//PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = false;
PrimaryActorTick.bCanEverTick = true;
}
void AMinigame::End()
{}
void AMinigame::Restart()
{}
UInputMappingContext* AMinigame::GetInputMappings()
{
return input.LoadSynchronous();
}
void AMinigame::Start(class APlayerBase* playerPawn, FMinigameEndCallback delegate)
{
player = playerPawn;

View File

@ -29,8 +29,11 @@ public:
UFUNCTION(BlueprintCallable)
virtual void End();
UFUNCTION(BlueprintCallable)
virtual void Restart();
UFUNCTION(BlueprintPure)
inline class UInputMappingContext* GetInputMappings() { return input.LoadSynchronous(); }
class UInputMappingContext* GetInputMappings();
protected:
FMinigameEndCallback callback;
@ -39,6 +42,9 @@ protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 score = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
bool ended = false;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TSoftObjectPtr<class UInputMappingContext> input = nullptr;
};

View File

@ -3,23 +3,46 @@
#include "SubwaySurfManager.h"
#include "Camera/CameraComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "Components/SplineComponent.h"
#include "EnhancedInputComponent.h"
#include "InputMappingContext.h"
#include "CustomGameInstanceBase.h"
#include "MainGameModeBase.h"
#include "PlayerBase.h"
#include "SubwaySurfObstacle.h"
#include "Widgets/WidgetsManager.h"
ASubwaySurfManager::ASubwaySurfManager()
: AMinigame()
{
input = { FSoftObjectPath{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/Minigame/IMC_SubwaySurf.IMC_SubwaySurf'") } };
auto root = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
playerPos = CreateDefaultSubobject<USceneComponent>(TEXT("PlayerPos"));
playerPos->AttachToComponent(root, FAttachmentTransformRules::KeepRelativeTransform);
camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
camera->AttachToComponent(root, FAttachmentTransformRules::KeepRelativeTransform);
mannequin = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Mannequin"));
mannequin->AttachToComponent(root, FAttachmentTransformRules::KeepRelativeTransform);
}
void ASubwaySurfManager::Start(APlayerBase* playerPawn, FMinigameEndCallback delegate)
{
if(!playerPawn)
return;
AMinigame::Start(playerPawn, delegate);
AMainGameModeBase::GetWidgetsManager()->HideInteractionHints(nullptr);
player->LockPlayer(FPlayerLock::All());
player->SwitchToView(this);
for(auto& mapping : input.LoadSynchronous()->GetMappings())
{
@ -33,27 +56,34 @@ void ASubwaySurfManager::Start(APlayerBase* playerPawn, FMinigameEndCallback del
inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Right).GetHandle());
}
playerPos.SetRelativeLocation(lines[0]->GetLocationAtTime(lines[0]->Duration * 0.2f, ESplineCoordinateSpace::Local));
player->SetActorLocation(playerPos.GetComponentLocation());
player->Controller->SetControlRotation(GetActorRotation());
playerPos->SetRelativeLocation(lines[1]->GetLocationAtTime(lines[1]->Duration * 0.01f, ESplineCoordinateSpace::Local));
mannequin->SetWorldLocationAndRotation(playerPos->GetComponentLocation(), playerPos->GetComponentRotation());
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.SetTickFunctionEnable(true);
}
void ASubwaySurfManager::End()
{
PrimaryActorTick.bCanEverTick = false;
PrimaryActorTick.SetTickFunctionEnable(false);
for(int32 handler : inputHandlers)
player->inputComponent->RemoveActionBindingForHandle(handler);
AMainGameModeBase::GetWidgetsManager()->ShowInteractionHints(nullptr);
player->UnlockPlayer(FPlayerLock::All());
player->ReturnPlayerView();
AMinigame::End();
}
void ASubwaySurfManager::Hit()
{
if(ended)
return;
ended = true;
if(score > 1000)
{
Finish();
@ -98,7 +128,7 @@ void ASubwaySurfManager::Tick(float deltaTime)
obstacles[i].actor->Destroy();
obstacles.RemoveAt(i);
//CreateObstacle();
speed += 0.1;
speed += 0.15;
score += 100 * speed;
}
else
@ -108,7 +138,22 @@ void ASubwaySurfManager::Tick(float deltaTime)
}
}
player->SetActorLocation(FMath::VInterpTo(player->GetActorLocation(), playerPos.GetComponentLocation(), deltaTime, 1));
FVector targetpos = playerPos->GetComponentLocation();
FVector actualpos = mannequin->GetComponentLocation();
FVector newpos{
FMath::FInterpTo(actualpos.X, targetpos.X, deltaTime, 20),
FMath::FInterpTo(actualpos.Y, targetpos.Y, deltaTime, 20),
FMath::FInterpTo(actualpos.Z, targetpos.Z, deltaTime, (FMath::Abs(actualpos.Z - targetpos.Z) < 20 ? 2.5f : 5.0f) * (speed / 2))
};
mannequin->SetWorldLocation(newpos, false, nullptr, ETeleportType::ResetPhysics);
if(vertical != 1 && FMath::IsNearlyEqual(actualpos.Z, targetpos.Z, 1.0))
{
if(vertical == 0)
Up();
else
Down();
}
}
void ASubwaySurfManager::CreateObstacle(int32 index)
@ -130,7 +175,6 @@ void ASubwaySurfManager::CreateObstacle(int32 index)
lastSpawnedLine = lineId;
auto obstacle = GetWorld()->SpawnActor<ASubwaySurfObstacle>(*obstacleClass, spline->GetComponentLocation(), GetActorRotation(), spawnParams);
obstacle->subwaySurf = this;
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("v: %f, %f, %f"), obstacle->GetActorLocation().X, obstacle->GetActorLocation().Y, obstacle->GetActorLocation().Z));
if(index < 0)
{
@ -147,40 +191,40 @@ void ASubwaySurfManager::CreateObstacle(int32 index)
void ASubwaySurfManager::Up()
{
if(playerUp)
if(vertical == 2)
return;
playerUp = true;
++vertical;
playerPos.AddLocalOffset(FVector::UpVector * 300);
playerPos->AddLocalOffset(FVector::UpVector * 150);
}
void ASubwaySurfManager::Down()
{
if(!playerUp)
if(vertical == 0)
return;
playerUp = false;
--vertical;
playerPos.AddLocalOffset(FVector::DownVector * 300);
playerPos->AddLocalOffset(FVector::DownVector * 150);
}
void ASubwaySurfManager::Left()
{
if(playerLine == 0)
if(horizontal == 0)
return;
--playerLine;
--horizontal;
playerPos.AddLocalOffset(FVector::LeftVector * 300);
playerPos->AddLocalOffset(FVector::LeftVector * 200);
}
void ASubwaySurfManager::Right()
{
if(playerLine == lines.Num() - 1)
if(horizontal == 2)
return;
++playerLine;
++horizontal;
playerPos.AddLocalOffset(FVector::RightVector * 300);
playerPos->AddLocalOffset(FVector::RightVector * 200);
}

View File

@ -41,6 +41,12 @@ protected:
UPROPERTY(EditDefaultsOnly)
TSet<TSubclassOf<class ASubwaySurfObstacle>> obstacleClasses;
UPROPERTY(EditAnywhere)
class UCameraComponent* camera;
UPROPERTY(EditAnywhere)
class USkeletalMeshComponent* mannequin;
UPROPERTY(EditDefaultsOnly)
float speed = 2;
@ -48,11 +54,13 @@ protected:
float spawnDelay = 3;
float time = spawnDelay;
UPROPERTY(EditDefaultsOnly)
TArray<class USplineComponent*> lines;
TArray<ObstacleData> obstacles;
int32 lastSpawnedLine = -1;
TArray<int32> inputHandlers;
class USceneComponent playerPos;
bool playerUp = false;
int32 playerLine = 0;
class USceneComponent* playerPos;
int32 vertical = 1;
int32 horizontal = 1;
};

View File

@ -20,20 +20,25 @@
#include "MainGameModeBase.h"
#include "Widgets/WidgetsManager.h"
namespace
{
const FVector cameraLocation = { 10, 0, 70 };
}
APlayerBase::APlayerBase()
: ACharacter()
{
PrimaryActorTick.bCanEverTick = true;
camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
camera->SetRelativeLocation(FVector{ 10, 0, 70 });
camera->SetRelativeLocation(cameraLocation);
camera->SetRelativeScale3D(FVector{ 0.25, 0.25, 0.25 });
camera->bUsePawnControlRotation = true;
camera->SetupAttachment(RootComponent);
cameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));
cameraSpringArm->TargetArmLength = -200;
cameraSpringArm->SetupAttachment(camera);
itemDropSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("ItemDropSpringArm"));
itemDropSpringArm->TargetArmLength = -200;
itemDropSpringArm->SetupAttachment(camera);
}
void APlayerBase::Tick(float DeltaTime)
@ -130,6 +135,11 @@ void APlayerBase::UnlockPlayer(FPlayerLock lock)
inventoryLocked -= lock.inventory;
}
void APlayerBase::FlyMode(bool on)
{
GetCharacterMovement()->GravityScale = on ? 0.0f : 1.0f;
}
FVector APlayerBase::GetCameraDirection()
{
return camera->GetForwardVector();
@ -150,6 +160,16 @@ void APlayerBase::SwitchToCameraPawn()
}
}
void APlayerBase::SwitchToView(AActor* target)
{
((APlayerController*)Controller)->SetViewTargetWithBlend(target, 0.3f);
}
void APlayerBase::ReturnPlayerView()
{
((APlayerController*)Controller)->SetViewTargetWithBlend(this, 0.3f);
}
void APlayerBase::MoveCamera(FVector2D value)
{
if(cameraLocked)
@ -261,7 +281,7 @@ void APlayerBase::TakeToInventory(AActor* actor)
actor->SetActorHiddenInGame(true);
actor->SetActorEnableCollision(false);
actor->SetActorTickEnabled(false);
actor->AttachToComponent(cameraSpringArm, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
actor->AttachToComponent(itemDropSpringArm, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
}
void APlayerBase::TakeItemToLeftHand(AActor* actor)
@ -270,7 +290,7 @@ void APlayerBase::TakeItemToLeftHand(AActor* actor)
return;
TakeToInventory(actor);
cameraSpringArm->TickComponent(0, ELevelTick::LEVELTICK_All, nullptr);
itemDropSpringArm->TickComponent(0, ELevelTick::LEVELTICK_All, nullptr);
DropLeftHandItem();
leftPocketItem = actor;
itemDropLocked = true;
@ -283,7 +303,7 @@ void APlayerBase::TakeItemToRightHand(AActor* actor)
return;
TakeToInventory(actor);
cameraSpringArm->TickComponent(0, ELevelTick::LEVELTICK_All, nullptr);
itemDropSpringArm->TickComponent(0, ELevelTick::LEVELTICK_All, nullptr);
DropRightHandItem();
rightPocketItem = actor;
itemDropLocked = true;
@ -340,6 +360,6 @@ void APlayerBase::ShowJournal()
FPlayerLock FPlayerLock::All()
{
FPlayerLock lock;
std::memset(&lock, 1, sizeof(FPlayerLock));
std::memset(&lock, 0xFF, sizeof(FPlayerLock));
return std::move(lock);
}

View File

@ -45,6 +45,12 @@ public:
FVector GetCameraDirection();
void LockPlayer(const FPlayerLock lock);
void UnlockPlayer(const FPlayerLock lock);
void FlyMode(bool on);
UFUNCTION(BlueprintCallable, Category = Character)
void SwitchToView(class AActor* target);
UFUNCTION(BlueprintCallable, Category = Character)
void ReturnPlayerView();
UFUNCTION(BlueprintCallable, Category = Character)
void TakeItemToLeftHand(class AActor* actor);
@ -118,7 +124,7 @@ protected:
bool bIsMoving = false;
class AInteractable* lastInteractable = nullptr;
class USpringArmComponent* cameraSpringArm;
class USpringArmComponent* itemDropSpringArm;
private:
void LoadInteractablesActivators();

View File

@ -21,8 +21,10 @@ public:
void HideWidgets();
void UpdateWidgetsOwner();
void ShowInteractionHints(const class UInteractableModificator* modificator);
void HideInteractionHints(const class UInteractableModificator* modificator);
UFUNCTION(BlueprintCallable, Category = WidgetsManager)
void ShowInteractionHints(const class UInteractableModificator* modificator = nullptr);
UFUNCTION(BlueprintCallable, Category = WidgetsManager)
void HideInteractionHints(const class UInteractableModificator* modificator = nullptr);
void AnimateInteractionHint(const class UInteractableModificator* modificator, const int32 index, const EInputAnimatedWidgetAnimation animation);
void EnableCutsceneWidget(class FSkipCutsceneDelegate& skipCutsceneDelegate);