C++ 팀 과제 TIL (4)

정완훈·2025년 2월 25일

언리얼 엔진 C++ HUD 업데이트 기능 추가 (탄약, 체력 색상 변화)

이번 포스팅에서는 언리얼 엔진 C++로 만든 HUD에서 탄약과 체력 텍스트의 색상을 동적으로 변화시키는 기능을 추가했다. 데미지를 받거나 탄약이 줄어들수록 텍스트 색상이 빨간색에 가까워지도록 하여 플레이어에게 위기감을 주는 효과를 넣은 것이다.

//PlayerHUD.h
#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Components/TextBlock.h"
#include "CP_PlayerHUD.generated.h"

UCLASS()
class CYBERPUNK_API UCP_PlayerHUD : public UUserWidget
{
    GENERATED_BODY()

public:
    UCP_PlayerHUD(const FObjectInitializer& ObjectInitializer);

    // 개별 업데이트 함수들
    UFUNCTION(BlueprintCallable, Category = "HUD")
    void UpdateWave(int32 Wave);

    UFUNCTION(BlueprintCallable, Category = "HUD")
    void UpdateWeaponName(const FString& WeaponName);

    UFUNCTION(BlueprintCallable, Category = "HUD")
    void UpdateAmmo(int32 Ammo); // 최대 탄약 추가

    UFUNCTION(BlueprintCallable, Category = "HUD")
    void UpdateMaxAmmo(int32 MaxAmmo); // 최대 탄약량 업데이트 함수

    UFUNCTION(BlueprintCallable, Category = "HUD")
    void UpdateHealth(int32 Health, int32 MaxHealth); // 최대 체력 추가

    UFUNCTION(BlueprintCallable, Category = "HUD")
    void UpdateEnemiesRemaining(int32 EnemiesRemaining);

    UFUNCTION(BlueprintCallable, Category = "HUD")
    void UpdateKillCount(int32 KillCount); // 킬카운트 업데이트 함수

protected:
    virtual void NativeConstruct() override;

    // UMG 위젯 바인딩
    UPROPERTY(meta = (BindWidget))
    UTextBlock* WaveText;

    UPROPERTY(meta = (BindWidget))
    UTextBlock* WeaponNameText;

    UPROPERTY(meta = (BindWidget))
    UTextBlock* AmmoText;

    UPROPERTY(meta = (BindWidget))
    UTextBlock* MaxAmmoText; // 최대 탄약량 텍스트 블록

    UPROPERTY(meta = (BindWidget))
    UTextBlock* HealthText;

    UPROPERTY(meta = (BindWidget))
    UTextBlock* EnemiesRemainingText;

    UPROPERTY(meta = (BindWidget))
    UTextBlock* KillCountText; // 킬카운트 텍스트 블록
};

//PlayerHUD.cpp

#include "CP_PlayerHUD.h"
#include "Components/TextBlock.h"
#include "Math/Color.h" // FLinearColor와 색상 보간을 위해 필요

UCP_PlayerHUD::UCP_PlayerHUD(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
}

void UCP_PlayerHUD::NativeConstruct()
{
    Super::NativeConstruct();
    if (WaveText) WaveText->SetText(FText::AsNumber(0));
    if (WeaponNameText) WeaponNameText->SetText(FText::FromString("No Weapon"));
    if (AmmoText) AmmoText->SetText(FText::AsNumber(0));
    if (MaxAmmoText) MaxAmmoText->SetText(FText::AsNumber(0)); // 최대 탄약량 초기값 설정
    if (HealthText) HealthText->SetText(FText::AsNumber(100));
    if (EnemiesRemainingText) EnemiesRemainingText->SetText(FText::AsNumber(0));
    if (KillCountText) KillCountText->SetText(FText::AsNumber(0)); // 킬카운트 초기값 설정
}

void UCP_PlayerHUD::UpdateWave(int32 Wave)
{
    if (WaveText)
    {
        WaveText->SetText(FText::AsNumber(Wave));
    }
}

void UCP_PlayerHUD::UpdateWeaponName(const FString& WeaponName)
{
    if (WeaponNameText)
    {
        WeaponNameText->SetText(FText::FromString(WeaponName));
    }
}

void UCP_PlayerHUD::UpdateAmmo(int32 Ammo)
{
    if (AmmoText)
    {
        // 현재 탄약 수 텍스트 업데이트
        AmmoText->SetText(FText::AsNumber(Ammo));

        // 탄약 비율 계산 (0.0 ~ 1.0)
        float ammoRatio = static_cast<float>(Ammo);

        // 흰색에서 빨간색으로 색상 보간
        FLinearColor newColor = FLinearColor::LerpUsingHSV(FLinearColor::White, FLinearColor::Red, 1.0f - ammoRatio);

        // 색상 적용
        AmmoText->SetColorAndOpacity(newColor);
    }
}

void UCP_PlayerHUD::UpdateMaxAmmo(int32 MaxAmmo)
{
    if (MaxAmmoText)
    {
        MaxAmmoText->SetText(FText::AsNumber(MaxAmmo)); // 최대 탄약량 업데이트
    }
}

void UCP_PlayerHUD::UpdateHealth(int32 Health, int32 MaxHealth)
{
    if (HealthText)
    {
        // 체력 텍스트 업데이트
        HealthText->SetText(FText::AsNumber(Health));

        // 체력 비율 계산 (0.0 ~ 1.0)
        float healthRatio = static_cast<float>(Health) / static_cast<float>(MaxHealth);

        // 흰색에서 빨간색으로 색상 보간
        FLinearColor newColor = FLinearColor::LerpUsingHSV(FLinearColor::White, FLinearColor::Red, 1.0f - healthRatio);

        // 색상 적용
        HealthText->SetColorAndOpacity(newColor);
    }
}

void UCP_PlayerHUD::UpdateEnemiesRemaining(int32 EnemiesRemaining)
{
    if (EnemiesRemainingText)
    {
        EnemiesRemainingText->SetText(FText::AsNumber(EnemiesRemaining));
    }
}

void UCP_PlayerHUD::UpdateKillCount(int32 KillCount)
{
    if (KillCountText)
    {
        KillCountText->SetText(FText::AsNumber(KillCount)); // 킬카운트 업데이트
    }
}

핵심 기능

  • 탄약 및 체력 색상 변화:
    • UpdateAmmo() 함수와 UpdateHealth() 함수에서 탄약과 체력 비율에 따라 텍스트 색상을 동적으로 변경하도록 구현했다.
    • FLinearColor::LerpUsingHSV() 함수를 사용하여 흰색에서 빨간색으로 색상을 부드럽게 보간했다.
  • 최대 탄약량 및 킬 카운트 추가:
    • MaxAmmoText 텍스트 블록을 추가하여 최대 탄약량을 표시하도록 했다.
    • KillCountText 텍스트 블록을 추가하여 킬 카운트를 표시하도록 했다.
    • UpdateMaxAmmo() 함수와 UpdateKillCount() 함수를 추가하여 해당 텍스트 블록을 업데이트하도록 했다.
  • 개별 업데이트 함수 추가:
    • UpdateWave(), UpdateWeaponName(), UpdateEnemiesRemaining() 함수를 추가하여 각 HUD 요소들을 개별적으로 업데이트할 수 있도록 했다.

구현 방법

  1. 헤더 파일 수정:
    • MaxAmmoTextKillCountText 텍스트 블록 변수를 추가했다.
    • UpdateMaxAmmo()UpdateKillCount() 함수를 추가했다.
    • 개별 업데이트 함수들을 추가했다.
  2. 소스 파일 수정:
    • NativeConstruct() 함수에서 최대 탄약량과 킬 카운트 텍스트 블록의 초기값을 설정했다.
    • UpdateAmmo() 함수와 UpdateHealth() 함수에서 색상 보간 로직을 추가했다.
    • UpdateMaxAmmo() 함수와 UpdateKillCount() 함수를 구현했다.
    • 개별 업데이트 함수들을 구현했다.
  3. 색상 보간:
    • FLinearColor::LerpUsingHSV() 함수를 사용하여 흰색에서 빨간색으로 색상을 보간했다.
    • 탄약 또는 체력 비율을 함수의 Alpha 값으로 사용하여 색상을 동적으로 변화시켰다.
  4. 최대 탄약량 및 킬 카운트 업데이트:
    • UpdateMaxAmmo() 함수와 UpdateKillCount() 함수를 호출하여 해당 텍스트 블록을 업데이트했다.

주의사항

  • FLinearColor::LerpUsingHSV() 함수를 사용하려면 #include "Math/Color.h" 헤더 파일을 포함해야 한다.
  • 색상 보간 범위를 적절하게 설정하여 시각적으로 자연스럽게 보이도록 해야 한다.
  • 최대 탄약량과 킬 카운트 텍스트 블록을 위젯 블루프린트에 바인딩해야 한다.

0개의 댓글