-
블루아카이브 루트슈터 팬게임 프로젝트(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); }
그리고 웨이브가 시작할때에도 위젯을 새로고침 해줍니다.
웨이브 위젯의 블루프린트 입니다. 웨이브와 남은 적들의 수를 표시해주는 간단한 위젯입니다.
결과물입니다. 적을 처치하면 남은 적이 줄어드는 것을 확인할 수 있습니다. 웨이브 모드 만들기는 이것으로 일단락 된 것 같고.. 이제 게임 메인 메뉴 레벨을 만들어서 게임 시작 버튼을 누를 수 있게 하고 플레이어 상태를 저장할 수 있도록 하고싶습니다. 이거는 좀 더 방법을 찾아보아야 할 것 같습니다.
'루트슈터 프로젝트' 카테고리의 다른 글
블루아카이브 루트슈터 팬게임 프로젝트(20) - 인벤토리 아이템 판매 시스템 (1) 2024.01.21 블루아카이브 루트슈터 팬게임 프로젝트(19) - 체력 회복 시스템 (1) 2024.01.21 블루아카이브 루트슈터 팬게임 프로젝트(18) - 적 스폰 시스템 & 웨이브 게임모드(2) (0) 2024.01.19 블루아카이브 루트슈터 팬게임 프로젝트(17) - 체력 컴포넌트 교체 (0) 2024.01.17 블루아카이브 루트슈터 팬게임 프로젝트(16) - 플레이어 캐릭터 모델링 교체 & 리타겟팅 (0) 2024.01.14