ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 블루아카이브 루트슈터 팬게임 프로젝트(18) - 적 스폰 시스템 & 웨이브 게임모드(3)
    루트슈터 프로젝트 2024. 1. 20. 01:02

    안녕하세요. 오늘은 웨이브, 남은 적 정보를 UI로 보여주고 웨이브 간 시간차를 설정해서 모든 적을 처치하면 5초 후 다음 웨이브가 시작되도록 하겠습니다. 

     

     

    WaveWidget.h

    UCLASS()
    class PROJECTBLUELANDS_API UWaveWidget : public UUserWidget
    {
    	GENERATED_BODY()
    
    public:
    	UPROPERTY(BlueprintReadWrite, meta=(BindWidget))
    	TObjectPtr<class UTextBlock> WaveRound;
    	UPROPERTY(BlueprintReadWrite, meta=(BindWidget))
    	TObjectPtr<class UTextBlock> EnemyLeft;
    
    	void RefreshWidget(int Wave, int enemyLeft);
    
    
    };

     

    웨이브 정보들을 보여주는 위젯 클래스를 하나 생성해줍니다. WaveRound는 몇웨이브인지 알려주는 텍스트 블록 이고 EnemyLeft는 남은 적들을 보여주는 텍스트 블록입니다. 

     

     

    WaveWidget.h

    void UWaveWidget::RefreshWidget(int Wave, int enemyLeft)
    {
        WaveRound->SetText(FText::FromString(FString::FromInt(Wave)));
        EnemyLeft->SetText(FText::FromString(FString::FromInt(enemyLeft)));
    }

     

    위젯의 정보를 초기화하는 함수입니다. 이 함수는 1. 새로운 웨이브가 시작될 때, 2. 적을 처치해서 남은 적이 줄어들었을때 호출됩니다. 

     

     

    WaveGameMode.h

    private:
    	FTimerHandle WaveStartTimerHandle;

     

    게임 모드 클래스입니다. 웨이브가 5초의 딜레이를 가지고 시작할 수 있도록 타임 핸들러 변수를 하나 선언해줍니다. 

     

     

     

     

    WaveGameMode.cpp

    void ABluelandsGameWaveMode::BeginPlay()
    {
        Super::BeginPlay();
        WaveWidget = Cast<UWaveWidget>(CreateWidget(GetWorld(), WaveWidgetClass));
        if(WaveWidget) 
        {
            WaveWidget->AddToViewport();
        }
        waveRound = 1;
        SpawnEnemy();
    }
    
    
    void ABluelandsGameWaveMode::ActorDied(AActor *DeadActor)
    {
        Super::ActorDied(DeadActor);
    
        if(Cast<AEnemyCharacter>(DeadActor))
        {
            enemyLeft--;
            UE_LOG(LogTemp, Error, TEXT("%d enemy left!"), enemyLeft);
            if(WaveWidget) WaveWidget->RefreshWidget(waveRound, enemyLeft);
        }
        if(enemyLeft == 0)
        {
            UE_LOG(LogTemp, Error, TEXT("Next Wave!!"));
            waveRound++;
            if(waveRound < 8) GetWorldTimerManager().SetTimer(WaveStartTimerHandle,this, &ABluelandsGameWaveMode::SpawnEnemy, 5.0, false, 5.0);
        }
    }

     

    게임 시작시 위젯을 불러와 뷰포트에 추가하고, 새로운 웨이브가 시작될 때(남은 적이 0이 됐을때) 5초의 텀을 가지고 웨이브가 시작되도록 타이머를 설정해줍니다.  그리고 적이 죽을때에는 웨이브 정보 위젯을 새로고침 해줍니다. 

     

     

    void ABluelandsGameWaveMode::SpawnEnemy() //각 라운드 시작시 발동됨
    {
        int normal, middle, boss;
        normal = 5, middle = 2, boss = 2;
    
        enemyLeft = 0;
        TArray<AActor*> spawners;
        UGameplayStatics::GetAllActorsOfClass(GetWorld(), spawnerClass, spawners);
    
        for(int i=0; i<(normal + middle + boss); i++)
        {
            AEnemySpawner* spawner = Cast<AEnemySpawner>(spawners[i]);
            if(spawner && player) 
            {
                FEnemyTableRow* enemyRow = nullptr; 
                if(i < normal)
                {
                    enemyRow = arNormalEnemyDataTable->FindRow<FEnemyTableRow>(FName(*(FString::FormatAsNumber(player->GetCharacterLevel()))), FString(""));
                } else if(i < normal + middle)  enemyRow = arMiddleEnemyDataTable->FindRow<FEnemyTableRow>(FName(*(FString::FormatAsNumber(player->GetCharacterLevel()))), FString(""));
                else enemyRow = arBossEnemyDataTable->FindRow<FEnemyTableRow>(FName(*(FString::FormatAsNumber(player->GetCharacterLevel()))), FString(""));
                
                if(enemyRow == nullptr) continue;
    
                spawner->SpawnEnemy((*enemyRow).enemyLevel, (*enemyRow).itemDropRate, (*enemyRow).legendDropRate, 
                    (*enemyRow).rareDropRate, (*enemyRow).uncommonDropRate, (*enemyRow).enemyHP, (*enemyRow).enemyDamage, (*enemyRow).enemyEXP);
                enemyLeft++;
            }
        }
        if(WaveWidget) WaveWidget->RefreshWidget(waveRound, enemyLeft);
    }

     

    그리고 웨이브가 시작할때에도 위젯을 새로고침 해줍니다. 

     

     

     

    웨이브 위젯의 블루프린트 입니다. 웨이브와 남은 적들의 수를 표시해주는 간단한 위젯입니다. 

     

     

     

     

     

    결과물입니다. 적을 처치하면 남은 적이 줄어드는 것을 확인할 수 있습니다. 웨이브 모드 만들기는 이것으로 일단락 된 것 같고.. 이제 게임 메인 메뉴 레벨을 만들어서 게임 시작 버튼을 누를 수 있게 하고 플레이어 상태를 저장할 수 있도록 하고싶습니다. 이거는 좀 더 방법을 찾아보아야 할 것 같습니다. 

     

     

Designed by Tistory.