UI는 총 크게 2가지로 구성하였습니다. 추후에 필요에 따라 더 제작할수도 있습니다.
1. 시작 화면
테스트용 배경 사진이며, 맵이 완성되면 맵을 캡쳐해서 시작 화면에 활용할 계획입니다.
Play와 Exit 두가지 버튼으로 간단하게 제작하였습니다.
// WidgetStartLevel.cpp
#include "WidgetStartLevel.h"
#include "Components/Button.h"
#include "EscapeGameInstance.h"
void UWidgetStartLevel::NativeConstruct()
{
Super::NativeConstruct();
ButtonPlay = Cast<UButton>(GetWidgetFromName(TEXT("ButtonPlay")));
ButtonExit = Cast<UButton>(GetWidgetFromName(TEXT("ButtonExit")));
ButtonPlay->OnClicked.AddDynamic(this, &UWidgetStartLevel::ButtonPlayCallback);
ButtonExit->OnClicked.AddDynamic(this, &UWidgetStartLevel::ButtonExitCallback);
}
void UWidgetStartLevel::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
Super::NativeTick(MyGeometry, InDeltaTime);
}
void UWidgetStartLevel::ButtonPlayCallback()
{
UEscapeGameInstance* GameInst = Cast<UEscapeGameInstance>(GetGameInstance());
if (IsValid(GameInst))
{
GameInst->SetLevelIndex();
UGameplayStatics::OpenLevel(GetWorld(), GameInst->LevelArray[GameInst->GetLevelIndex()]);
}
}
void UWidgetStartLevel::ButtonExitCallback()
{
UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
}
델리게이트로 버튼이 눌렸을 때, 수행할 함수를 매칭해주었습니다.
// StartGameMode.cpp
#include "StartGameMode.h"
#include "WidgetStartLevel.h"
AStartGameMode::AStartGameMode()
{
static ConstructorHelpers::FClassFinder<UUserWidget> StartWidgetClass(TEXT("WidgetBlueprint'/Game/GameContent/UI/UIStartLevel.UIStartLevel_C'"));
if (StartWidgetClass.Succeeded())
{
StartLevelWidgetClass = StartWidgetClass.Class;
}
}
void AStartGameMode::BeginPlay()
{
Super::BeginPlay();
if (IsValid(StartLevelWidgetClass))
{
StartLevelWidget = Cast<UWidgetStartLevel>(CreateWidget(GetWorld(), StartLevelWidgetClass));
if (IsValid(StartLevelWidget))
{
StartLevelWidget->AddToViewport();
}
}
}
블루프린트로 만든 UI 애셋을 AddToViewport() 함수를 이용해서 화면에 띄워줍니다.
2. Main HUD
Main HUD에는 플레이 타임, 죽은 횟수, 사망 메세지를 구현해봤습니다.
플레이 타임과 죽은 횟수는 계속 표시해줄 것이고, 사망 메세지는 장애물에 닿으면 표시해줍니다.
// WidgetMainHUD.cpp
#include "WidgetMainHUD.h"
#include "Components/TextBlock.h"
void UWidgetMainHUD::NativeConstruct()
{
Super::NativeConstruct();
// 위젯 블루프린트의 텍스트 블럭을 이름을 통해 가져온다
PlayTime = Cast<UTextBlock>(GetWidgetFromName(TEXT("PlayTime")));
DeathCount = Cast<UTextBlock>(GetWidgetFromName(TEXT("DeathCount")));
DeathMessage = Cast<UTextBlock>(GetWidgetFromName(TEXT("DeathMessage")));
}
void UWidgetMainHUD::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
Super::NativeTick(MyGeometry, InDeltaTime);
}
void UWidgetMainHUD::SetPlayTime(const FString& strName)
{
PlayTime->SetText(FText::FromString(strName));
}
void UWidgetMainHUD::SetDeathCount(const FString& strName)
{
DeathCount->SetText(FText::FromString(strName));
}
void UWidgetMainHUD::SetDeathMessage(bool boolen)
{
if (boolen)
{
DeathMessage->SetVisibility(ESlateVisibility::Visible);
}
else
{
DeathMessage->SetVisibility(ESlateVisibility::Collapsed);
}
}
SetVisibility 함수를 이용해서 해당 조건일때만 메세지를 보여줍니다.
// EscapeGameInstance.cpp
#include "EscapeGameInstance.h"
#include "MainGameMode.h"
#include "WidgetMainHUD.h"
#include "MyPlayerCharacter.h"
#include "MyPlayerController.h"
UEscapeGameInstance::UEscapeGameInstance()
{
LevelIndex = 0;
LevelArray = { "Start", "Level1-1", "Level1-2", "Level1-3","Level2-1", "Level2-2", "Level2-3","Level3-1", "Level3-2", "Level3-3" };
fPlayTime = 1800.f;
iDeathCount = 0;
}
UEscapeGameInstance::~UEscapeGameInstance()
{
}
uint8 UEscapeGameInstance::GetLevelIndex()
{
return LevelIndex;
}
void UEscapeGameInstance::SetLevelIndex()
{
++LevelIndex;
}
void UEscapeGameInstance::SetPlayTime(float DeltaTime)
{
AMainGameMode* GameMode = Cast<AMainGameMode>(GetWorld()->GetAuthGameMode());
if (IsValid(GameMode))
{
UWidgetMainHUD* MainHUD = GameMode->GetWidgetMainHUD();
if (IsValid(MainHUD))
{
if (fPlayTime < 0.f)
{
AMyPlayerController* pController = Cast<AMyPlayerController>(GetWorld()->GetFirstPlayerController());
if (IsValid(pController))
{
AMyPlayerCharacter* pCharacter = Cast<AMyPlayerCharacter>(pController->GetPawn());
if (IsValid(pCharacter))
{
pCharacter->GameOver();
}
}
}
fPlayTime -= DeltaTime;
FString strText = FString::Printf(TEXT("%2d:%2d"), (int32)fPlayTime/60,(int32)fPlayTime%60);
MainHUD->SetPlayTime(strText);
}
}
}
void UEscapeGameInstance::SetDeathCount()
{
AMainGameMode* GameMode = Cast<AMainGameMode>(GetWorld()->GetAuthGameMode());
if (IsValid(GameMode))
{
UWidgetMainHUD* MainHUD = GameMode->GetWidgetMainHUD();
if (IsValid(MainHUD))
{
iDeathCount += 1;
FString strText = FString::Printf(TEXT("%d"), iDeathCount);
MainHUD->SetDeathCount(strText);
}
}
}
int32 UEscapeGameInstance::GetDeathCount()
{
return iDeathCount;
}
레벨이 바뀌어도 플레이타임과 죽은 횟수는 바뀌면 안되므로, 게임 인스턴스에 구현했습니다.
'게임 개발 (언리얼 엔진)' 카테고리의 다른 글
UE4 게임 개발 EscapeGame - 11 : 좀비 애셋 추가 (0) | 2020.12.15 |
---|---|
UE4 게임 개발 EscapeGame - 10 : 카메라 페이드 (0) | 2020.12.13 |
UE4 게임 개발 EscapeGame - 8 : 애니메이션 블루프린트와 재질기반사운드 (0) | 2020.12.07 |
UE4 게임 개발 EscapeGame - 7 : 카메라쉐이크(CameraShake) (0) | 2020.12.04 |
UE4 게임 개발 EscapeGame - 6 : 디스트럭터블 메시(Destructible Mesh) (0) | 2020.12.01 |