전체 코드 : https://github.com/HyangRim/DirectX11-Engine-Client
GitHub - HyangRim/DirectX11-Engine-Client
Contribute to HyangRim/DirectX11-Engine-Client development by creating an account on GitHub.
github.com
실시간 HUD와 셰이더 기반 상태바 구현
1. 전체 UI 시스템 구조
1.1 UIManager - 중앙 집중식 UI 관리
UIManager는 모든 UI 패널을 중앙에서 관리하며, 플레이어와의 연결점 역할을 한다.
// UI 시스템의 최상위 관리자
class UIManager : public Component
{
private:
shared_ptr<GameHUDPanelUI> m_gameHUD;
shared_ptr<SkillLevelUpPanelUI> m_skillLevelUp;
shared_ptr<PlayerStatusPanelUI> m_playerStatus;
shared_ptr<InventoryPanelUI> m_inventory;
shared_ptr<EquipmentPanelUI> m_equipment;
// ... 기타 UI 패널들
public:
void InitializeUI();
void Update();
};
// 모든 UI 패널의 기본 인터페이스
class IBasePanelUI
{
public:
virtual void Initialize() = 0;
virtual void Update() = 0;
virtual void SetVisible(bool visible) = 0;
virtual void Cleanup() = 0;
protected:
virtual void CreatePanels() = 0;
shared_ptr<GameObject> m_panel;
bool m_isVisible = true;
};
1.2 싱글톤 패턴을 활용한 리소스 관리
// UI 리소스 전용 관리자
class UIResourceManager
{
DECLARE_SINGLE(UIResourceManager);
private:
unordered_map<wstring, shared_ptr<Material>> m_materials;
unordered_map<wstring, shared_ptr<Texture>> m_textures;
public:
// 리소스 로딩 및 설정
shared_ptr<Material> LoadUIMaterial(const wstring& name, const wstring& texturePath);
void SetupUIMaterial(shared_ptr<Material> material);
// 특화된 UI 리소스 로딩
void LoadSkillIcons();
void LoadStatusBarResources();
void LoadEquipmentResources();
};
2. 주요 UI 시스템
2.1 게임 HUD 시스템
class GameHUDPanelUI : public IBasePanelUI
{
public:
void CreateSkillIcons(); // 스킬 아이콘 생성
void CreateStatBars(); // HP/SP/EXP 바 생성
void UpdateSkillCoolDown(); // 스킬 쿨다운 실시간 업데이트
void UpdateSkillLevelBar(int skillIndex); // 스킬 레벨업 시 UI 반영
private:
void CreateCharacterImage(); // 캐릭터별 초상화 표시
};
스탯바 업데이트
void GameHUDPanelUI::UpdateStatBar()
{
if (!m_player) return;
const auto& status = m_player->GetStatus();
// HP 바 업데이트 - 쉐이더에 비율 전송
float hpRatio = static_cast<float>(status.hp) / static_cast<float>(status.max_HP);
if (m_hpBarImage)
{
auto material = m_hpBarImage->GetLayers()[0].material;
if (material && material->GetShader())
{
material->GetShader()->PushHealthBarData(hpRatio, 0.0f, 0);
}
}
// MP 바 업데이트
float mpRatio = static_cast<float>(status.stamina) / static_cast<float>(status.max_Stamina);
if (m_mpBarImage)
{
auto material = m_mpBarImage->GetLayers()[0].material;
if (material && material->GetShader())
{
material->GetShader()->PushHealthBarData(0.0f, mpRatio, 0);
}
}
UpdateStatText(); // 수치 텍스트 업데이트
}

위의 사진에서 빨간색 사각형 부분이 GameHUDPanelUI 다.
특징
- 실시간 스킬 쿨다운 표시
- 동적 HP/SP/EXP 바 업데이트
- 캐릭터별 스킬 아이콘 동적 로딩
- Character Select Scene에서 선택한 캐릭터의 초상화 출력
- 캐릭터 레벨 표시
2.2 인벤토리 & 장비 시스템
class InventoryManager
{
DECLARE_SINGLE(InventoryManager);
public:
// 슬롯 간 아이템 이동
bool MoveItem(int fromSlot, int toSlot, SLOTTYPE fromType, SLOTTYPE toType);
// 장비 착용/해제
bool EquipItem(int inventorySlotIndex);
bool UnequipItem(int equipmentSlotIndex);
// 이벤트 기반 UI 업데이트
Delegate::Delegate<> OnInventoryChanged;
private:
vector<shared_ptr<ItemSlot>> m_inventorySlots;
vector<shared_ptr<ItemSlot>> m_equipmentSlots;
};

동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.
몬스터를 처치 한 후 아이템을 획득하면 인벤토리 창에 표시가 되고 인벤토리 창을 기준으로 조합 가능한 조합식이 상단에 표시된다.
특징
- 델리게이트 패턴으로 UI 자동 갱신
- 자동 장비 타입 검증 ( 무기는 무기 슬롯에만, 상의는 상의 슬롯에만 )
- 클릭을 통합 장비 장착 및 해제
2.3 스탯 표시 시스템
class PlayerStatusPanelUI : public IBasePanelUI
{
private:
// 스탯별 색상과 표시 방식 정의
vector<StatTextConfig> statConfigs = {
{0, 0, [&]() { return to_wstring((int)playerStatus.hitAttack); },
ColorNormalize(Vec4(218, 187, 102, 255)), L"AttackPower"},
// ... 각 스탯별 설정
};
public:
void UpdatePlayerStatus(); // 실시간 스탯 업데이트
};
위의 영상과 같이 장비 장착과 해제시 스탯이 반영됨.
3. 동적 UI 업데이트 시스템
3.1 이벤트 기반 UI 갱신
// 인벤토리 변화 시 자동 UI 갱신
inventoryManager->OnInventoryChanged.Push([this]() {
if (m_isVisible) {
UpdateCraftableItems();
}
});
// 스킬 레벨업 시 UI 반영
skill->SkillLevelUp();
m_uiManager->GetGameHUD()->UpdateSkillLevelBar(skillIndex);
3.2 실시간 데이터 바인딩
void GameHUDPanelUI::UpdateStatBar()
{
PlayerStatus& playerStatus = m_player->GetStatus();
// HP 바 실시간 업데이트
float ratio = ((float)playerStatus.hp / (float)playerStatus.max_HP);
Vec2 newSize = Vec2(253.f * ratio, 10.f);
hpImageUI->SetLayerSize(0, newSize);
}
4. 백그라운드 로딩 시스템
// 메인 스레드 블로킹 방지를 위한 백그라운드 UI 로딩
DWORD __stdcall LumiaIsland::BackgroundLoadingThread(LPVOID _param)
{
// 백그라운드에서 리소스 로딩
ItemManager::GetInstance()->Initialize();
RecipeManager::GetInstance()->Initialize();
scene->m_uiManager->InitializeUI();
// 메인 스레드에서 실행할 작업 큐에 추가
scene->m_mainThreadTasks.push([scene]() {
scene->CreateItemBoxPanel();
scene->m_objectsCreated = true;
});
}
5. 경험치 바와 레벨업 시스템
5.1 Player클래스의 경험치 시스템
void Player::AddExp(int _exp)
{
m_status.exp += _exp;
// 레벨업 체크
while (m_status.exp >= GetRequiredExp())
{
LevelUp();
}
// UI 업데이트 요청
if (auto manager = m_uiManager.lock())
{
manager->GetGameHUD()->UpdateExpBar();
}
}
int Player::GetRequiredExp() const
{
// 레벨에 따른 필요 경험치 계산 (지수적 증가)
return static_cast<int>(100 * pow(1.5f, m_status.level - 1));
}
void Player::LevelUp()
{
m_status.level++;
m_status.exp -= GetRequiredExp();
// 레벨업 시 스탯 증가
int hpIncrease = 20 + (m_status.level * 5);
int staminaIncrease = 10 + (m_status.level * 3);
m_status.max_HP += hpIncrease;
m_status.max_Stamina += staminaIncrease;
// 현재 HP/MP 회복
m_status.hp = m_status.max_HP;
m_status.stamina = m_status.max_Stamina;
// 레벨업 효과 및 UI 업데이트
PlayLevelUpEffect();
cout << "레벨업! 새로운 레벨: " << m_status.level << endl;
}
5.2 경험치 바 시각화
void GameHUDPanelUI::UpdateExpBar()
{
if (!m_player) return;
const auto& status = m_player->GetStatus();
// 현재 레벨에서의 경험치 진행률 계산
int requiredExp = m_player->GetRequiredExp();
int currentLevelExp = status.exp;
float expRatio = static_cast<float>(currentLevelExp) / static_cast<float>(requiredExp);
expRatio = max(0.0f, min(1.0f, expRatio)); // 0~1 범위로 제한
// 경험치 바에 쉐이더 데이터 전송
if (m_expBarImage)
{
auto material = m_expBarImage->GetLayers()[0].material;
if (material && material->GetShader())
{
material->GetShader()->PushHealthBarData(expRatio, 0.0f, 2); // type=2는 경험치바
}
}
// 경험치 텍스트 업데이트
wstring expText = std::to_wstring(currentLevelExp) + L"/" + std::to_wstring(requiredExp);
if (m_expText)
m_expText->SetText(expText);
}
동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.
결론
- 모듈화된 UI 구조
- 각 UI 패널이 독립적으로 동작
- IBasePanelUI 인터페이스로 일관된 생명주기 관리
- 리소스 최적화
- UIResourceManager로 텍스쳐 / Material 중복 로딩 방지
- 백그라운드 로딩으로 초기화 시간 단축
- 이벤트 기반 설계
- Delegate 패턴으로 느슨한 결합
- 데이터 변경 시 관련 UI 자동 갱신 ( 변경 될때 갱신 함수 호출 )
- 확장 가능한 구조
- 새로운 UI 패널 추가 시 기존 코드 수정 최소화
- 캐릭터별 / 아이템별 동적 UI 생성 가능
'DirectX11 > Eternal Return 모작' 카테고리의 다른 글
| [DirectX 11 Eternal Return 모작] 17. QuadTree (0) | 2025.09.03 |
|---|---|
| [DirectX 11 Eternal Return 모작] 16. Direct2D 텍스트 렌더링 (0) | 2025.09.03 |
| [DirectX 11 Eternal Return 모작] 14. UI (0) | 2025.09.03 |
| [DirectX 11 Eternal Return 모작] 13. 전투 , 데미지 시스템 (0) | 2025.09.03 |
| [DirectX 11 Eternal Return 모작] 12. NavMesh (0) | 2025.09.03 |