작성 코드
.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameState.h"
#include "SpartaGameState.generated.h"
UCLASS()
class COINGAME_API ASpartaGameState : public AGameState
{
GENERATED_BODY()
public:
ASpartaGameState();
virtual void BeginPlay() override;
UPROPERTY(VisibleAnyWhere, BlueprintReadWrite, Category = "Score")
int32 Score;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Coin")
int32 SpawnedCoinCount;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Coin")
int32 CollectedCoinCount;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Level")
float LevelDuration;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Level")
int32 CurrentLevelIndex;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Level")
int32 MaxLevels;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Level")
TArray<FName> LevelMapNames;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Wave")
int32 CurrentWaveIndex;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Wave")
int32 MaxWaves;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Wave")
TArray<float> WaveDurations;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Wave")
TArray<int32> WaveSpawnLimits;
int32 CurrentWaveSpawnCount;
FTimerHandle LevelTimerHandle;
FTimerHandle HUDUpdateTimerHandle;
UFUNCTION(BlueprintPure, Category = "Score")
int32 GetScore() const;
UFUNCTION(BlueprintCallable, Category = "Score")
void AddScore(int32 Amount);
UFUNCTION(BlueprintCallable, Category = "Level")
void OnGameOver();
void StartLevel();
void StartWave();
void SpawnCoins();
void EndWave();
void OnLevelTimeUp();
void OnCoinCollected();
void EndLevel();
void UpdateHUD();
};
.cpp
#include "SpartaGameState.h"
#include "SpartaGameInstance.h"
#include "SpartaPlayerController.h"
#include "SpawnVolume.h"
#include "CoinItem.h"
#include "Kismet/GameplayStatics.h"
#include "Components/TextBlock.h"
#include "Blueprint/UserWidget.h"
ASpartaGameState::ASpartaGameState()
{
Score = 0;
SpawnedCoinCount = 0;
CollectedCoinCount = 0;
LevelDuration = 30.0f;
CurrentLevelIndex = 0;
MaxLevels = 3;
CurrentWaveIndex = 0;
MaxWaves = 3;
WaveDurations = {60.0f, 40.0f, 30.0f};
WaveSpawnLimits = {3, 2, 1};
CurrentWaveSpawnCount = 0;
}
void ASpartaGameState::BeginPlay()
{
Super::BeginPlay();
FString CurrentMapName = GetWorld()->GetMapName();
if (!CurrentMapName.Contains("MenuLevel"))
{
StartLevel();
}
GetWorldTimerManager().SetTimer(
HUDUpdateTimerHandle,
this,
&ASpartaGameState::UpdateHUD,
0.1f,
true
);
}
int32 ASpartaGameState::GetScore() const
{
return Score;
}
void ASpartaGameState::AddScore(int32 Amount)
{
if (UGameInstance* GameInstance = GetGameInstance())
{
USpartaGameInstance* SpartaGameInstance = Cast<USpartaGameInstance>(GameInstance);
if (SpartaGameInstance)
{
SpartaGameInstance->AddToScore(Amount);
}
}
}
void ASpartaGameState::StartLevel()
{
if (APlayerController* PlayerController = GetWorld()->GetFirstPlayerController())
{
if (ASpartaPlayerController* SpartaPlayerController = Cast<ASpartaPlayerController>(PlayerController))
{
SpartaPlayerController->ShowGameHUD();
}
}
if (UGameInstance* GameInstance = GetGameInstance())
{
USpartaGameInstance* SpartaGameInstance = Cast<USpartaGameInstance>(GameInstance);
if (SpartaGameInstance)
{
CurrentLevelIndex = SpartaGameInstance->CurrentLevelIndex;
}
}
CurrentWaveIndex = 0;
StartWave();
}
void ASpartaGameState::StartWave()
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString::Printf(TEXT("Level %d Wave %d 시작!"), CurrentLevelIndex + 1, CurrentWaveIndex + 1));
// 이전 웨이브의 남은 코인들 정리
TArray<AActor*> FoundCoins;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), ACoinItem::StaticClass(), FoundCoins);
for (AActor* Coin : FoundCoins)
{
Coin->Destroy();
}
CurrentWaveSpawnCount = 0;
if (WaveDurations.IsValidIndex(CurrentWaveIndex))
{
LevelDuration = WaveDurations[CurrentWaveIndex];
}
else
{
LevelDuration = 30.0f;
}
SpawnCoins();
GetWorldTimerManager().SetTimer(
LevelTimerHandle,
this,
&ASpartaGameState::OnLevelTimeUp,
LevelDuration,
false
);
}
void ASpartaGameState::SpawnCoins()
{
CurrentWaveSpawnCount++;
TArray<AActor*> FoundVolumes;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), ASpawnVolume::StaticClass(), FoundVolumes);
const int32 ItemToSpawn = 40;
SpawnedCoinCount = 0;
CollectedCoinCount = 0;
if (FoundVolumes.Num() > 0)
{
ASpawnVolume* SpawnVolume = Cast<ASpawnVolume>(FoundVolumes[0]);
if (SpawnVolume)
{
for (int32 i = 0; i < ItemToSpawn; i++)
{
AActor* SpawnedActor = SpawnVolume->SpawnRandomItem();
if (SpawnedActor && SpawnedActor->IsA(ACoinItem::StaticClass()))
{
SpawnedCoinCount++;
}
}
}
}
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("이번 회차 스폰된 코인: %d"), SpawnedCoinCount));
}
void ASpartaGameState::OnLevelTimeUp()
{
EndWave();
}
void ASpartaGameState::OnCoinCollected()
{
CollectedCoinCount++;
if (SpawnedCoinCount > 0 && CollectedCoinCount >= SpawnedCoinCount)
{
if (WaveSpawnLimits.IsValidIndex(CurrentWaveIndex) && CurrentWaveSpawnCount < WaveSpawnLimits[CurrentWaveIndex])
{
SpawnCoins();
}
else
{
EndWave();
}
}
}
void ASpartaGameState::EndWave()
{
GetWorldTimerManager().ClearTimer(LevelTimerHandle);
CurrentWaveIndex++;
if (CurrentWaveIndex >= MaxWaves)
{
EndLevel();
}
else
{
StartWave();
}
}
void ASpartaGameState::EndLevel()
{
GetWorldTimerManager().ClearTimer(LevelTimerHandle);
if (UGameInstance* GameInstance = GetGameInstance())
{
USpartaGameInstance* SpartaGameInstance = Cast<USpartaGameInstance>(GameInstance);
if (SpartaGameInstance)
{
AddScore(Score);
CurrentLevelIndex++;
SpartaGameInstance->CurrentLevelIndex = CurrentLevelIndex;
if (CurrentLevelIndex >= MaxLevels)
{
OnGameOver();
return;
}
if (LevelMapNames.IsValidIndex(CurrentLevelIndex))
{
UGameplayStatics::OpenLevel(GetWorld(), LevelMapNames[CurrentLevelIndex]);
}
else
{
OnGameOver();
}
}
}
}
void ASpartaGameState::OnGameOver()
{
if (APlayerController* PlayerController = GetWorld()->GetFirstPlayerController())
{
if (ASpartaPlayerController* SpartaPlayerController = Cast<ASpartaPlayerController>(PlayerController))
{
SpartaPlayerController->SetPause(true);
SpartaPlayerController->ShowMainMenu(true);
}
}
}
void ASpartaGameState::UpdateHUD()
{
if (APlayerController* PlayerController = GetWorld()->GetFirstPlayerController())
{
ASpartaPlayerController* SpartaPlayerController = Cast<ASpartaPlayerController>(PlayerController);
{
if (UUserWidget* HUDWidget = SpartaPlayerController->GetHUDWidget())
{
if (UTextBlock* TimeText = Cast<UTextBlock>(HUDWidget->GetWidgetFromName(TEXT("Time"))))
{
float RemainingTime = GetWorldTimerManager().GetTimerRemaining(LevelTimerHandle);
TimeText->SetText(FText::FromString(FString::Printf(TEXT("Time: %.1f"), RemainingTime)));
}
if (UTextBlock* ScoreText = Cast<UTextBlock>(HUDWidget->GetWidgetFromName(TEXT("Score"))))
{
if (UGameInstance* GameInstance = GetGameInstance())
{
USpartaGameInstance* SpartaGameInstance = Cast<USpartaGameInstance>(GameInstance);
if (SpartaGameInstance)
{
ScoreText->SetText(FText::FromString(FString::Printf(TEXT("Score: %d"), SpartaGameInstance->TotalScore)));
}
}
}
if (UTextBlock* LevelIndexText = Cast<UTextBlock>(HUDWidget->GetWidgetFromName(TEXT("Level"))))
{
LevelIndexText->SetText(FText::FromString(FString::Printf(TEXT("Level: %d"), CurrentLevelIndex + 1)));
}
if (UTextBlock* WaveIndexText = Cast<UTextBlock>(HUDWidget->GetWidgetFromName(TEXT("Wave"))))
{
WaveIndexText->SetText(FText::FromString(FString::Printf(TEXT("Wave: %d"), CurrentWaveIndex + 1)));
}
if (UTextBlock* SpawnCountText = Cast<UTextBlock>(HUDWidget->GetWidgetFromName(TEXT("Spawn"))))
{
SpawnCountText->SetText(FText::FromString(FString::Printf(TEXT("Spawn: %d"), CurrentWaveSpawnCount)));
}
}
}
}
}
자세한 설명
.h
.cpp