SubwaySurf minigame
This commit is contained in:
parent
f7b9942b5a
commit
346f2b22ef
BIN
Content/Input/Minigame/Actions/IA_SubwaySurf_Down.uasset
Normal file
BIN
Content/Input/Minigame/Actions/IA_SubwaySurf_Down.uasset
Normal file
Binary file not shown.
BIN
Content/Input/Minigame/Actions/IA_SubwaySurf_Left.uasset
Normal file
BIN
Content/Input/Minigame/Actions/IA_SubwaySurf_Left.uasset
Normal file
Binary file not shown.
BIN
Content/Input/Minigame/Actions/IA_SubwaySurf_Right.uasset
Normal file
BIN
Content/Input/Minigame/Actions/IA_SubwaySurf_Right.uasset
Normal file
Binary file not shown.
BIN
Content/Input/Minigame/Actions/IA_SubwaySurf_Up.uasset
Normal file
BIN
Content/Input/Minigame/Actions/IA_SubwaySurf_Up.uasset
Normal file
Binary file not shown.
BIN
Content/Input/Minigame/IMC_SubwaySurf.uasset
Normal file
BIN
Content/Input/Minigame/IMC_SubwaySurf.uasset
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -38,6 +38,8 @@ void UCommonFunctions::DestroyActorRecursively(AActor* actor)
|
||||
actor->Destroy();
|
||||
}
|
||||
|
||||
|
||||
|
||||
ALevelBase* UCommonFunctions::GetCurrentLevelScript(UObject* obj)
|
||||
{
|
||||
if(auto world = obj->GetWorld())
|
||||
|
@ -18,9 +18,12 @@ public:
|
||||
UFUNCTION(BlueprintCallable, Category = Actor)
|
||||
static void DestroyActorRecursively(class AActor* actor);
|
||||
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = Level)
|
||||
static class ALevelBase* GetCurrentLevelScript(class UObject* obj);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = Player)
|
||||
static class APlayerBase* GetPlayer(class UObject* obj);
|
||||
|
||||
};
|
||||
|
@ -220,6 +220,16 @@ void UDialogueManager::LockCallback(bool lock)
|
||||
_lockCallback = lock;
|
||||
}
|
||||
|
||||
void UDialogueManager::BeginDestroy()
|
||||
{
|
||||
_timersLock.Lock();
|
||||
for(auto& timer : _timers)
|
||||
GetWorld()->GetTimerManager().ClearTimer(timer);
|
||||
_timersLock.Unlock();
|
||||
|
||||
UObject::BeginDestroy();
|
||||
}
|
||||
|
||||
void UDialogueManager::OnDialogueEnd()
|
||||
{
|
||||
_dialoguesLock.Lock();
|
||||
|
@ -84,6 +84,9 @@ public:
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void LockCallback(bool lock);
|
||||
|
||||
protected:
|
||||
virtual void BeginDestroy() override;
|
||||
|
||||
private:
|
||||
void PlayNextDialogue();
|
||||
UFUNCTION()
|
||||
|
18
Source/Lost_Edge/Private/Minigame/Minigame.cpp
Normal file
18
Source/Lost_Edge/Private/Minigame/Minigame.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
// Oleg Petruny proprietary.
|
||||
|
||||
|
||||
#include "Minigame.h"
|
||||
|
||||
AMinigame::AMinigame()
|
||||
{
|
||||
//PrimaryActorTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
void AMinigame::End()
|
||||
{}
|
||||
|
||||
void AMinigame::Start(class APlayerBase* playerPawn, FMinigameEndCallback delegate)
|
||||
{
|
||||
player = playerPawn;
|
||||
callback = delegate;
|
||||
}
|
45
Source/Lost_Edge/Private/Minigame/Minigame.h
Normal file
45
Source/Lost_Edge/Private/Minigame/Minigame.h
Normal file
@ -0,0 +1,45 @@
|
||||
// Oleg Petruny proprietary.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GameFramework/Actor.h"
|
||||
|
||||
#include "Minigame.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EMinigameResult : uint8
|
||||
{
|
||||
Loss,
|
||||
Win,
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_DELEGATE_TwoParams(FMinigameEndCallback, EMinigameResult, result, int32, score);
|
||||
|
||||
UCLASS(Blueprintable, BlueprintType, MinimalAPI, Abstract)
|
||||
class AMinigame : public AActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AMinigame();
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
virtual void Start(class APlayerBase* playerPawn, FMinigameEndCallback delegate);
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
virtual void End();
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
inline class UInputMappingContext* GetInputMappings() { return input.LoadSynchronous(); }
|
||||
|
||||
protected:
|
||||
FMinigameEndCallback callback;
|
||||
class APlayerBase* player;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 score = 0;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
TSoftObjectPtr<class UInputMappingContext> input = nullptr;
|
||||
};
|
||||
|
@ -0,0 +1,186 @@
|
||||
// Oleg Petruny proprietary.
|
||||
|
||||
|
||||
#include "SubwaySurfManager.h"
|
||||
|
||||
#include "Components/SplineComponent.h"
|
||||
#include "EnhancedInputComponent.h"
|
||||
#include "InputMappingContext.h"
|
||||
|
||||
#include "PlayerBase.h"
|
||||
#include "SubwaySurfObstacle.h"
|
||||
|
||||
ASubwaySurfManager::ASubwaySurfManager()
|
||||
{
|
||||
input = { FSoftObjectPath{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/Minigame/IMC_SubwaySurf.IMC_SubwaySurf'") } };
|
||||
}
|
||||
|
||||
void ASubwaySurfManager::Start(APlayerBase* playerPawn, FMinigameEndCallback delegate)
|
||||
{
|
||||
AMinigame::Start(playerPawn, delegate);
|
||||
|
||||
player->LockPlayer(FPlayerLock::All());
|
||||
|
||||
for(auto& mapping : input.LoadSynchronous()->GetMappings())
|
||||
{
|
||||
if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Up"))))
|
||||
inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Up).GetHandle());
|
||||
else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Down"))))
|
||||
inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Down).GetHandle());
|
||||
else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Left"))))
|
||||
inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Left).GetHandle());
|
||||
else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Right"))))
|
||||
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());
|
||||
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
void ASubwaySurfManager::End()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = false;
|
||||
|
||||
for(int32 handler : inputHandlers)
|
||||
player->inputComponent->RemoveActionBindingForHandle(handler);
|
||||
|
||||
player->UnlockPlayer(FPlayerLock::All());
|
||||
|
||||
AMinigame::End();
|
||||
}
|
||||
|
||||
void ASubwaySurfManager::Hit()
|
||||
{
|
||||
if(score > 1000)
|
||||
{
|
||||
Finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if(callback.IsBound())
|
||||
callback.Execute(EMinigameResult::Loss, score);
|
||||
End();
|
||||
}
|
||||
|
||||
void ASubwaySurfManager::Finish()
|
||||
{
|
||||
if(callback.IsBound())
|
||||
callback.Execute(EMinigameResult::Win, score);
|
||||
End();
|
||||
}
|
||||
|
||||
void ASubwaySurfManager::PostInitializeComponents()
|
||||
{
|
||||
AMinigame::PostInitializeComponents();
|
||||
|
||||
GetComponents<USplineComponent>(lines);
|
||||
}
|
||||
|
||||
void ASubwaySurfManager::Tick(float deltaTime)
|
||||
{
|
||||
AMinigame::Tick(deltaTime);
|
||||
|
||||
time += deltaTime;
|
||||
|
||||
if(time >= spawnDelay / speed)
|
||||
{
|
||||
time = 0; // (time -= spawnDelay) is not good on lags
|
||||
CreateObstacle();
|
||||
}
|
||||
|
||||
for(int32 i = 0; i < obstacles.Num(); ++i)
|
||||
{
|
||||
if(obstacles[i].time > lines[obstacles[i].lineId]->Duration)
|
||||
{
|
||||
obstacles[i].actor->Destroy();
|
||||
obstacles.RemoveAt(i);
|
||||
//CreateObstacle();
|
||||
speed += 0.1;
|
||||
score += 100 * speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
obstacles[i].time += deltaTime * speed;
|
||||
obstacles[i].actor->SetActorLocation(lines[obstacles[i].lineId]->GetWorldLocationAtTime(obstacles[i].time));
|
||||
}
|
||||
}
|
||||
|
||||
player->SetActorLocation(FMath::VInterpTo(player->GetActorLocation(), playerPos.GetComponentLocation(), deltaTime, 1));
|
||||
}
|
||||
|
||||
void ASubwaySurfManager::CreateObstacle(int32 index)
|
||||
{
|
||||
auto obstacleClass = obstacleClasses.CreateIterator();
|
||||
for(int32 i = 0; i < FMath::RandRange(0, obstacleClasses.Num() - 1); ++i) // std::advance not works :(
|
||||
++obstacleClass;
|
||||
|
||||
int32 lineId;
|
||||
do
|
||||
{
|
||||
lineId = FMath::RandRange(0, lines.Num() - 1);
|
||||
} while(lineId == lastSpawnedLine);
|
||||
auto spline = lines[lineId];
|
||||
|
||||
FActorSpawnParameters spawnParams{};
|
||||
spawnParams.Owner = this;
|
||||
|
||||
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)
|
||||
{
|
||||
obstacles.Add({ .actor = obstacle, .lineId = lineId, .time = 0 });
|
||||
}
|
||||
else
|
||||
{
|
||||
obstacles[index].actor->Destroy();
|
||||
obstacles[index].actor = obstacle;
|
||||
obstacles[index].lineId = lineId;
|
||||
obstacles[index].time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ASubwaySurfManager::Up()
|
||||
{
|
||||
if(playerUp)
|
||||
return;
|
||||
|
||||
playerUp = true;
|
||||
|
||||
playerPos.AddLocalOffset(FVector::UpVector * 300);
|
||||
}
|
||||
|
||||
void ASubwaySurfManager::Down()
|
||||
{
|
||||
if(!playerUp)
|
||||
return;
|
||||
|
||||
playerUp = false;
|
||||
|
||||
playerPos.AddLocalOffset(FVector::DownVector * 300);
|
||||
}
|
||||
|
||||
void ASubwaySurfManager::Left()
|
||||
{
|
||||
if(playerLine == 0)
|
||||
return;
|
||||
|
||||
--playerLine;
|
||||
|
||||
playerPos.AddLocalOffset(FVector::LeftVector * 300);
|
||||
}
|
||||
|
||||
void ASubwaySurfManager::Right()
|
||||
{
|
||||
if(playerLine == lines.Num() - 1)
|
||||
return;
|
||||
|
||||
++playerLine;
|
||||
|
||||
playerPos.AddLocalOffset(FVector::RightVector * 300);
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
// Oleg Petruny proprietary.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Minigame/Minigame.h"
|
||||
|
||||
#include "SubwaySurfManager.generated.h"
|
||||
|
||||
struct ObstacleData
|
||||
{
|
||||
class ASubwaySurfObstacle* actor;
|
||||
int32 lineId;
|
||||
float time;
|
||||
};
|
||||
|
||||
UCLASS(Blueprintable, BlueprintType, MinimalAPI)
|
||||
class ASubwaySurfManager : public AMinigame
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
ASubwaySurfManager();
|
||||
|
||||
virtual void Start(class APlayerBase* playerPawn, FMinigameEndCallback delegate) override;
|
||||
virtual void End() override;
|
||||
|
||||
void Hit();
|
||||
void Finish();
|
||||
|
||||
protected:
|
||||
virtual void PostInitializeComponents() override;
|
||||
virtual void Tick(float deltaTime) override;
|
||||
|
||||
void CreateObstacle(int32 index = -1);
|
||||
|
||||
void Up();
|
||||
void Down();
|
||||
void Left();
|
||||
void Right();
|
||||
|
||||
UPROPERTY(EditDefaultsOnly)
|
||||
TSet<TSubclassOf<class ASubwaySurfObstacle>> obstacleClasses;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly)
|
||||
float speed = 2;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly)
|
||||
float spawnDelay = 3;
|
||||
float time = spawnDelay;
|
||||
|
||||
TArray<class USplineComponent*> lines;
|
||||
TArray<ObstacleData> obstacles;
|
||||
int32 lastSpawnedLine = -1;
|
||||
TArray<int32> inputHandlers;
|
||||
class USceneComponent playerPos;
|
||||
bool playerUp = false;
|
||||
int32 playerLine = 0;
|
||||
};
|
@ -0,0 +1,17 @@
|
||||
// Oleg Petruny proprietary.
|
||||
|
||||
|
||||
#include "SubwaySurfObstacle.h"
|
||||
|
||||
#include "SubwaySurfManager.h"
|
||||
|
||||
void ASubwaySurfObstacle::Hit()
|
||||
{
|
||||
if(!subwaySurf)
|
||||
{
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
subwaySurf->Hit();
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
// Oleg Petruny proprietary.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GameFramework/Actor.h"
|
||||
|
||||
#include "SubwaySurfObstacle.generated.h"
|
||||
|
||||
UCLASS(Blueprintable, BlueprintType, MinimalAPI, Abstract)
|
||||
class ASubwaySurfObstacle : public AActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void Hit();
|
||||
|
||||
class ASubwaySurfManager* subwaySurf = nullptr;
|
||||
|
||||
};
|
||||
|
@ -336,3 +336,10 @@ void APlayerBase::ShowJournal()
|
||||
if(auto WM = AMainGameModeBase::GetWidgetsManager())
|
||||
WM->ShowJournal();
|
||||
}
|
||||
|
||||
FPlayerLock FPlayerLock::All()
|
||||
{
|
||||
FPlayerLock lock;
|
||||
std::memset(&lock, 1, sizeof(FPlayerLock));
|
||||
return std::move(lock);
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ struct FPlayerLock
|
||||
uint8 interaction : 1;
|
||||
uint8 camera : 1;
|
||||
uint8 inventory : 1;
|
||||
|
||||
static FPlayerLock All();
|
||||
};
|
||||
|
||||
UCLASS(Blueprintable, BlueprintType)
|
||||
|
Loading…
Reference in New Issue
Block a user