개요
이전 포스팅까지 랜덤한 맵의 구조를 생성하는 것에 대해 정리하였습니다. 이번에는 랜덤하게 생성된 방에 맞춰 알맞는 미니맵을 제작하는 방법에 대해 정리해보도록 하겠습니다.
미니맵 구현 아이디어


결과적으로 목표는 던파의 미니맵과 같은 형태를 제작하는 것이였으며, 최대한 비슷하게 제작해보기 위해 노력했습니다.
이전 포스팅에서 방의 정보를 Dungeon Generator Component에서 TArray로 관리하고 있기에 해당 정보를 사용해 미니맵에 알맞는 이미지를 넣기로 생각했습니다.
즉, 방의 모든 문이 열렸다면(OpenDir = 1 1 1 1) 4방향 이미지로 해당 칸을 채우는 방식으로 구현하게 되었습니다.
또한, 처음부터 미니맵이 전부 열려있지 않게 하기 위해서 미니맵 이미지 위에 더미 이미지를 두어 방문한 방들만을 확인할 수 있도록 하였으며 현재 위치한 방을 밝게 표현하였습니다.
UserWidget Design

기본적으로 기획했던 4 x 3 크기의 미니맵을 제작하게 되어 디자인한 결과물입니다.
각 칸별로 overlay를 사용하여 Road(길) 이미지 위에 Hide(가림판) 이미지를 노출시켜 방문하지 않은 맵을 막아주었는 방식으로 구현하게 되었습니다.
각 Road에 들어갈 이미지는 방의 OpenDir(비트 플래그)를 토대로 매핑해주었으며, Hide 이미지도 플레이어가 현재 위치해있는지 아닌지를 판별해 이미지를 교체해줄 수 있도록 배열로 추가해주었습니다.

UserWidget C++
위와 같이 디자인을 끝낸 이후 UserWidget을 상속받은 클래스를 제작하였습니다.
가장 중요한 것은 해당 위젯에 들어가는 이미지 수가 너무 많기에 하나씩 매핑해주는 것이 아닌, 코드에서 위젯을 찾아 내부에 있는 모든 요소를 가져오는 작업이였습니다.
구글링을 통해 찾아보니 "WidgetTree"라는 클래스가 존재하며, 해당 클래스를 사용해 제작한 위젯에 있는 모든 UWidget(요소)를 가지고 올 수 있었습니다.
Widget Tree를 사용하려면 다음과 같은 헤더를 포함해야 합니다.
#include "Blueprint/WidgetTree.h"
저의 경우 Widget Tree를 사용하여 모든 위젯을 가져온 뒤 설정했던 이름들을 기반으로 정보를 구분하여 저장하였으며, 플레이어가 특정 방에 입장했을 때 해당 위젯의 이미지를 업데이트 하는 함수를 제작하였습니다.
PlayerHUD Class 코드
HP와 관련된 부분도 포함되어 있지만, 그리 중요한 것은 아니기에 본문에서는 다루지 않았습니다.
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "PlayerHUD.generated.h"
/**
*
*/
UCLASS()
class SHOOTINGGAME3D_API UPlayerHUD : public UUserWidget
{
GENERATED_BODY()
public:
void InitWidget();
void SetCurrentRoom(int32 InIdx, uint8 OpenFlag);
void SetHp(int32 CurrentHp);
private:
UPROPERTY(VisibleAnywhere, Category = "Minimap")
TArray<TObjectPtr<class UImage>> Roads;
UPROPERTY(VisibleAnywhere, Category = "Minimap")
TArray<TObjectPtr<class UImage>> Hides;
UPROPERTY(VisibleAnywhere, Category = "Minimap")
TArray<TObjectPtr<class UImage>> Hps;
private:
UPROPERTY(EditAnywhere, Category = "Texture")
TMap<uint8, TObjectPtr<class UTexture2D>> RoadTexture;
UPROPERTY(EditAnywhere, Category = "Texture")
TMap<FName, TObjectPtr<class UTexture2D>> HideTexture;
UPROPERTY(EditAnywhere, Category = "Texture")
TMap<int32, TObjectPtr<class UTexture2D>> HpTexture;
UPROPERTY(VisibleAnywhere)
int32 CurrentRoomIdx = 0;
bool bIsStart = true;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "PlayerHUD.h"
#include "Blueprint/WidgetTree.h"
#include "Components/Image.h"
void UPlayerHUD::InitWidget()
{
TArray<UWidget*> TempWidgets;
WidgetTree->GetAllWidgets(TempWidgets);
for (UWidget* Widget : TempWidgets)
{
if (Widget->GetName().Contains(TEXT("Road")))
{
UImage* RoadImage = Cast<UImage>(Widget);
if (RoadImage)
{
Roads.Push(RoadImage);
}
}
else if (Widget->GetName().Contains(TEXT("Hide")))
{
UImage* HideImage = Cast<UImage>(Widget);
if (HideImage)
{
Hides.Push(HideImage);
}
}
else if (Widget->GetName().Contains(TEXT("Hp")))
{
UImage* HpImage = Cast<UImage>(Widget);
if (HpImage)
{
Hps.Push(HpImage);
}
}
}
UE_LOG(LogTemp, Warning, TEXT("%d, %d, %d"), Roads.Num(), Hides.Num(), Hps.Num());
}
void UPlayerHUD::SetCurrentRoom(int32 InIdx, uint8 OpenFlag)
{
if (bIsStart && InIdx == 0)
{
// 현재 방 설정
CurrentRoomIdx = InIdx;
// 현재 방 밝은 화면으로 변환
Hides[CurrentRoomIdx]->SetBrushFromTexture(HideTexture[TEXT("Visible")]);
bIsStart = false;
}
if (CurrentRoomIdx != InIdx)
{
// 이전 방 어두운 화면으로 변환
Hides[CurrentRoomIdx]->SetBrushFromTexture(HideTexture[TEXT("Hide")]);
// 현재 방 설정
CurrentRoomIdx = InIdx;
// 현재 방 밝은 화면으로 변환
Hides[CurrentRoomIdx]->SetBrushFromTexture(HideTexture[TEXT("Visible")]);
}
// 방의 이미지 설정
Roads[CurrentRoomIdx]->SetBrushFromTexture(RoadTexture[OpenFlag]);
}
void UPlayerHUD::SetHp(int32 CurrentHp)
{
if (CurrentHp > 6 || CurrentHp < 0) return;
// 그림 : 1: half, 2: full, 3: empty
// 하트 인덱스 : 0 1 2
// 체력 0 1 2 3 4 5 6
// 인덱스
// 현재 인덱스 구하기
int32 Idx = (CurrentHp - 1) / 2;
if (CurrentHp == 0)
{
for (UImage* HpImg : Hps)
{
HpImg->SetBrushFromTexture(HpTexture[3]);
}
}
else
{
for (int i = Idx; i < Hps.Num(); i++)
{
if (i == Idx)
{
Hps[i]->SetBrushFromTexture(HpTexture[((CurrentHp - 1) % 2) + 1]);
}
else
{
Hps[i]->SetBrushFromTexture(HpTexture[3]);
}
}
}
}
'프로젝트 > Isaac 3D' 카테고리의 다른 글
[UE Team Project/Issac 3D] 5. 프로젝트 마무리 (최종) (0) | 2024.09.09 |
---|---|
[UE Team Project/Issac 3D] 3. 랜덤 맵 생성 - 2 (완) (0) | 2024.09.06 |
[UE Team Project/Issac 3D] 2. 랜덤 맵 생성 - 1 (0) | 2024.09.06 |
[UE Team Project/Issac 3D] 1. 프로젝트 역할 분담 (0) | 2024.09.06 |