Post

[Portfolio] 게임개발 프로젝트 포트폴리오.

Windows API와 DirectX 9, 11 기반의 프로젝트 4개 기록

[Portfolio] 게임개발 프로젝트 포트폴리오.

개요

이 글은 게임개발 학원 재원 당시 진행했던 프로젝트들에 관해 작성한 글입니다.

저는 2025년과 그 전후로 게임 개발에 대해 학습하면서, C++을 통해 Windows API / DirectX 9 / 11 사용법을 익혔고, 이를 기반으로 간단한 엔진 구현부터 클라이언트 개발까지 진행해봤습니다.

(이후 현재는 부족하다 느꼈던 기초 CS지식들과 상용 게임엔진을 학습중이며, 개인적으로 보드게임 프로젝트도 제작해보고 있습니다.)

아래는 그 4개의 프로젝트들에 대한 글입니다.


순서 및 요약

시간 순서입니다! (아래로 갈 수록 최신)

  1. Windows API 기반 2D 게임 모작. (개인 프로젝트)
    • 모작 대상은 동방 루나 나이츠입니다.
    • 유명한 IP인 동방프로젝트를 기반으로 한, 2D 기반의 횡스크롤 메트로바니아 게임입니다.
    • 주요 구현점은 WinAPI 기반 엔진 루프 구현, 맵 데이터/입출력 구현, 스테이지 4개 제작, 일반 몬스터 2종 구현, 보스 1종 구현, 시간 기믹 구현 정도입니다.
    • 제대로 된 개발을 해본 경험은 처음이었고, 각종 디자인패턴이나, 설계 원칙 등에 대해서는 아직 알지 못하던 시기였습니다. 때문에 코드에 아쉬운 점이 많고, 엔진과 클라이언트의 경계가 없습니다.
  2. DirectX 9 기반 2.5D 게임 모작. (팀 프로젝트)
    • 모작 대상은 세피리아입니다. 2D 리소스를 이용, 3D 상에서 플레이 가능하게 제작했습니다.
    • 다만 리소스와 게임 방식에 Bleak Sword DX라는 게임의 요소를 차용해서, 로그라이트 3D 게임으로 구현했습니다.
    • 저는 플레이어 및 몬스터 담당으로써, 플레이어와 몬스터 3종, 보스 2종을 작업했습니다.
    • 지금 다시보면, 몬스터나 플레이어의 상태 구조를 제작할 때 FSM이나 Behavior Tree를 쓰면 됐을 텐데, 당시에는 이를 몰라서 많이 어렵게 만들었습니다.
  3. DirectX 11 기반 3D 게임 모작. (개인 프로젝트)
    • 모작 대상은 슈퍼핫입니다. 시간 정지를 기믹으로 하는 싱글 FPS 게임입니다.
    • 주요 구현점은 DirectX 11 기반 엔진 루프 구현, Ray Picking을 통한 3D 맵 에디터/입출력 구현, FSM 기반 몬스터 애니메이션 및 AI 구현, 시간 기믹 구현, 파티클 구현, 스테이지 4개 제작 등입니다.
    • 지금 봐도 결과물이 별로 좋아보이진 않습니다. 그래서 되돌아보면 많이 부끄럽네요.
    • 그래도 3D 리소스를 직접 다뤄보고, 제어시켜본 만큼 배운 건 많았습니다. 성공적이라고 하긴 어렵겠지만 어쨌든 마무리는 지었기도 하고요.
  4. DirectX 11 기반 3D 게임 최종 프로젝트. (팀 프로젝트)
    • 모작 대상은 명조입니다. 여기서는 팀 각자의 역할에 따라, 개인 에디터 우선 제작 후 구현 작업에 들어갔습니다.
    • 저는 UI 담당으로써, UI 배치 및 애니메이션 에디터에 더해, HUD와 미니맵 / QTE / UI의 GPU 인스턴싱 / FreeType을 통한 폰트 렌더링 및 셰이더 (SDF, Outline) 및 UI 셰이더 구현(9-Slicing, Dissolve) 등을 작업했습니다.
    • 이 기간동안 많은 시간을 셰이더에 쏟았는데(인스턴싱, UI 효과, 폰트 등 때문에..), 셰이더 참 재밌는 물건이구나 싶었습니다.
    • 파트 특성상 다른 파트와 합을 맞출 일이 많았었는데, 요청에 따라 내가 제작한 기능들을, 다른 개발자가 사용하기 좋은 형태로 래핑해서 제공해주고 피드백을 받는 즐거움도 있었습니다.

본문

Media Group 창 상단의 탭을 통해 영상으로의 전환이 가능합니다!
또한 접기 처리된 내용을 펼쳐 상세 내용을 확인할 수 있습니다.

WinAPI 2D : 동방 루나 나이츠

portfolio_01_image
인원1인 (개인 프로젝트)
모작 대상동방 루나 나이츠
개발기간25. 2. 7. ~ 2. 26. (20일)
사용 언어C++
사용 라이브러리Windows API, FMOD
깃허브 링크Github : ProjectTH
상세 내용 펼치기

1. 맵 에디터 구현

2026-09-07-02-42-19

  • 지형 및 몬스터 배치를 위해 간단한 맵 에디터를 제작했습니다.
  • 지형은 편집 단계에서는 타일 텍스쳐 형태로 표시되며, 실제 플레이 시 해당 형태에 대응하는 콜라이더로 변환됩니다.
  • 단축키를 통해 맵 뷰어 모드와 지형 편집 모드를 전환할 수 있습니다.
  • 편집한 지형 및 오브젝트 배치 정보는 파일로 저장하고, 스테이지 진입 시 다시 불러오도록 구성했습니다.
  • 해당 에디터를 통해 스테이지를 4개 제작했습니다.

2. NPC 구현

touhounpc

  • 상호작용이 가능한 NPC 두 종을 구현했습니다.
  • 한 명은 시간 정지 능력의 해금 수단, 다른 한 명은 보스 방까지 가는 매개체로써 구성했습니다.
  • 일정 좌표 내에 들어가있을 시, 상호작용이 가능하도록 제작했습니다.

3. 시간 기믹 구현

gif-2026-09-07-오전-3-04-49

  • 시간 느려짐(SNAIL), 시간 정지(STOP) 기믹을 구현했습니다.
  • 느려짐 상태에서는 Player, UI, Effect 레이어를 제외한 모든 오브젝트가 1/2배속으로, 정지 상태에서는 멈추게 제작했습니다. ObjMgr에서 단순히 Update 빈도를 제어하는 방식입니다.
  • 단, 보여야 하므로 RenderGroup 삽입은 항시 돕니다.

4. 몬스터 및 보스 구현

2026-09-07-02-48-52

  • 몬스터는 간단한 행동 패턴을 가진 두 종류(늑대와 위습)를, 보스로는 홍 메이링을 제작했습니다.
  • 보스는 경과 프레임에 따라 패턴이 변화하는 방식으로 제작했습니다. 등장/퇴장 연출도 있고요.

DX9 2.5D : 세피리아 + Bleak Sword DX

portfolio_02_image
인원4인 (Framework, UI, Player & Monster, Map)
모작 대상세피리아 + Bleak Sword DX
개발기간25. 5. 19. ~ 6. 16. (29일)
사용 언어C++
사용 라이브러리DirectX 9, FMOD, ImGui
깃허브 링크Github : DX9_SR_PROJECT_Archive
상세 내용 펼치기

1. 플레이어 구현

gif-2025-05-28-오후-11-24-14 플레이어 구현 당시 GIF

  • 플레이어의 전반적인 조작을 구현했습니다. (이동, 대시, 평타, 패리, 퓨리)
  • 마우스 위치를 기준으로 공격 방향을 결정하고, 짧은 시간 내 연속 입력 시 다음 동작이 이어지도록 제작했습니다.
  • 대시는 WASD 조작 중이라면 해당 방향으로, 아니라면 마우스 방향으로 돌진합니다.

1-A. 무기 애니메이션 구현

2026-09-07-03-38-08

실제 구현 애니메이션 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
HRESULT CAnim_Player_Parry::Initialize()
{
	// Setting : 변환용 행렬 선언 및 초기화
	/* 중략 */

	// desmos : https://www.desmos.com/calculator/hqkn67hpjk
	// keyStart (0~17) *********
	for (size_t i = 0; i < iMaxKeyFrame; i++)
	{
		// transform
		vecTrans = {
			static_cast<_float>(-0.5 * cosf( 0.4 * iKeyFrame - 0.7 ) + 0.5),
			static_cast<_float>(0.6 * sinf(- 0.35 * iKeyFrame)),
			0
		};

		// rotation
		_float3 vAxis = { 0, 0, 1 };
		D3DXQuaternionRotationAxis(&quatRot, &vAxis, D3DXToRadian(130 -iKeyFrame * -15));

		// scale
		vecScale = {
			float(7) / 18,
			float(15) / 19,
			1
		};

		// 반영
		Insert_KeyFrames(iKeyFrame, vecScale, quatRot, vecTrans);
		iKeyFrame++;
	}
	// End key *********

    /* 중략 */
}
  • 제한된 환경에서의 애니메이션을 구현하기 위해, Transform 애니메이션 체계를 구축했습니다.
  • 수식 그래프에 착안해, 실제 수식을 기반으로 Initialize 시점에 Keyframe을 생성하고, 생성된 Keyframe을 기준으로 로컬 좌표를 Update하는 방식입니다.
  • 플레이어에게 종속되는 무기와 같이 Owner에 대해 상대적으로 반영됩니다.

2. 몬스터 구현

2026-09-07-03-54-05

  • 몬스터는 간단한 행동 패턴을 가진 3종(두더지, 돼지, 레이저 몹)을 제작했습니다.
  • 레이저 몹의 경우, 플레이어 방향으로 락온 이후 해당 방향으로 레이저가 따라 돌아갑니다.

3. 보스 구현

2026-09-07-03-57-19

  • 보스는 경과 프레임에 따라 패턴이 변화하는 방식으로 제작했습니다.
  • Erma의 경우 두더지 본체와 양 손, 머리 객체가 분리되어있고, 본체에 의해 동작이 제어되는 구조입니다.
  • Askard는 두 개의 페이즈로 구성했으며, 촉수/레이저/충격파 등의 패턴과 2페이즈용 강화 패턴을 구현했습니다. 또한 간헐적으로 고정된 촉수 오브젝트를 소환합니다.
  • QTE 패턴은 UI를 담당한 팀원분께서 제작해주셨습니다.

DX11 3D : 슈퍼핫

portfolio_03_image
인원1인 (개인 프로젝트)
모작 대상슈퍼핫
개발기간25. 7. 7. ~ 9. 26. (82일)1
사용 언어C++, HLSL
사용 라이브러리DirectX 11, DirectX Tool Kit, FMOD, ImGui, Assimp
깃허브 링크Github : PSN_PROJECT
상세 내용 펼치기

1. 3D 맵 에디터 구현

2026-09-07-06-18-57

  • 레벨 제작 및 편집을 용이하게 하기 위해 3D 모델 배치기를 구현했습니다.
  • Ray Picking을 통한 클릭 지점 배치 or 임의 위치 모델 배치 및 Transform 수정, 모델 입출력 등이 가능합니다.
  • 추가로 Navmesh 편집 기능 및 배치 시 Snap이 가능하도록 제작해, 추후 인게임에서 낮은 부하로 지형 위를 걸을 수 있도록 했습니다.
  • 편집기 UI 제작에는 ImGui 라이브러리를, 모델 입출력 시 .fbx 데이터를 읽어오는 데에는 Assimp 라이브러리를 사용했습니다.

2. FSM 기반 AI

2026-09-07-06-25-03

  • 유니티의 Animator 시스템에 착안하여, FSM(유한 상태 기계) 방식으로 적의 AI를 구현했습니다.
  • 유니티의 Animator Parameter와 유사하게, 상태 제어에 필요한 변수들(사진의 tAIParam)을 사전에 정의해두고, 이를 외부에서 조작 가능하도록 제작했습니다.
  • 이를 통해 적은 사진과 같은 6개의 상태를 가지며, 상태마다 다른 행동 패턴을 보입니다.
  • 지금 다시보니 Blackboard 패턴이라고 부르긴 힘든 것 같습니다.

3. 무기 구현 및 상호작용

gif-2026-09-07-오전-6-30-24

  • 빈손인 경우, 중앙 커서의 Raycast에 걸리는 무기 Box Collider가 존재한다면 중앙의 아이콘이 바뀝니다.
  • 이후 클릭 시, 해당 무기를 장착합니다. 플레이어가 주운 무기는 탄환의 제한이 존재합니다.
  • 우클릭으로 던질 수도 있으며, 이 경우 레이어가 변경됩니다. (=플레이어와 적이 Pickup할 수 없고, 충돌 판정을 갖게 됩니다.)
  • 장착/투척 시 시작점과 목표점 간 보간을 통해, 자연스럽게 Transform이 전환되도록 제작했습니다.

4. 시간 제어

실제 구현 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void CGameInstance::Update_Engine(_float fTimeDelta)
{
    // 시간 조절 기믹용 매니저
    m_pTimeSpeed_Manager->Update_TimeSpeed(fTimeDelta);
    
    _float fSpeedMultiply = m_pTimeSpeed_Manager->Get_TimeSpeed();
    _float fCalcedTimeDelta = fTimeDelta * fSpeedMultiply;
    
    
    m_pInput_Device->Update();
    
    m_pObject_Manager->Priority_Update(fCalcedTimeDelta);
    
    m_pPicking->Update();
    m_pPipeLine->Update();
    
    m_pObject_Manager->Update(fCalcedTimeDelta);
    m_pCollision_Manager->Update();
    m_pObject_Manager->Late_Update(fCalcedTimeDelta);
    
    m_pLevel_Manager->Update(fCalcedTimeDelta);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class ENGINE_DLL CTimeSpeed_Manager final : public CBase
{
    // 특수한 시간 배율 기믹같이,
    // 중요도가 높은 글로벌 변수를 제어하기 위한 매니저

    // 제어 요청을 받아 시간 경과에 따라 보간하여 제어되도록 의도
    // 사용 방식? : 플레이어 행동 시 force change, 이후 정상화 과정에는 req 사용..
private:
    CTimeSpeed_Manager() = default;
    virtual ~CTimeSpeed_Manager() = default;

public:
    void Update_TimeSpeed(_float fRawTimeDelta)
    {
        const _float followSpeed = 7.0f; // 클수록 더 빨리 목표에 붙음
        _float factor = 1.0f - expf(-followSpeed * fRawTimeDelta);
        m_fRawTimeDelta = fRawTimeDelta;

        fTimeSpeed_Multiplier = fTimeSpeed_Multiplier * (1.0f - factor)
            + fTimeSpeed_ReqTarget * factor;

        if (fTimeSpeed_Multiplier < fTimeSpeed_Min) fTimeSpeed_Multiplier = fTimeSpeed_Min;
        if (fTimeSpeed_Multiplier > fTimeSpeed_Max) fTimeSpeed_Multiplier = fTimeSpeed_Max;
    };

    void Req_EditTimeSpeed(_float fEditValue)           {   fTimeSpeed_ReqTarget = fEditValue;  }
    void Set_EditTimeSpeed(_float fEditValue)           {   fTimeSpeed_ReqTarget = fEditValue; 
                                                            fTimeSpeed_Multiplier = fEditValue; }
    
    _float Get_RawTimeDelta()                           {   return m_fRawTimeDelta; }
    _float Get_TimeSpeed()                              {   return fTimeSpeed_Multiplier;   }

private:
    _float fTimeSpeed_Multiplier = 1.f;     // 현재 수치
    _float fTimeSpeed_ReqTarget = 1.f;      // 목표 수치

    const _float fTimeSpeed_Min = 0.01f;
    const _float fTimeSpeed_Max = 1.f;

    _float m_fRawTimeDelta = {};

public:
    static CTimeSpeed_Manager* Create()                 { return new CTimeSpeed_Manager(); }
    virtual void Free() override                        { __super::Free(); }
};
  • 엔진 단계에 시간 배율을 관리하는 TimeSpeed_Manager 를 제작해, 본래 시간인 TimeDelta와, 배율이 적용된 CalcedTimeDelta를 나눠 구분 사용이 가능하도록 제작했습니다.
  • 기본적으로 Update 루프에는 CalcedTimeDelta를 사용하도록 뿌렸습니다.
  • 단, 플레이어 조작과 같이 원본 시간 배율이 필요한 일부 예외 경우에 사용 가능하도록, Get_RawTimeDelta() 함수를 두었습니다.

Etc.

  • 플레이어와 적의 애니메이션은 상/하체별로 분리했으며, 애니메이션 루프/전환 시 방금까지의 Transform을 기준으로 보간이 일어나 자연스럽게 전환되도록 제작했습니다.
  • 총알 발사/피격 시 간단한 형태의 Particle도 붙였습니다.
  • 메뉴 텍스트 구현에는 DXTK의 SpriteFont 기능을 사용했습니다.

DX11 3D Final : 명조

portfolio_04_image
인원7인 (Framework, UI, Player, Monster, Map, Effect, Shader)
모작 대상명조
개발기간25. 10. 1. ~ 12. 15. (76일)
사용 언어C++, HLSL
사용 라이브러리DirectX 11, FMOD, ImGui, Assimp, Jolt Physics, FreeType, Nlohmann JSON
깃허브 링크Github : Wuthring-Wave-Final
상세 내용 펼치기

1. UI 부모 구조 구현

2026-09-07-08-20-00 Root_Dialog.json 파일의 구조 도식화

2026-09-07-08-23-03 해당 json 파일의 내부 구조.
현재 보이는 부분이 상기 사진의 Line_Bar 부분입니다.

  • 연관성이 있는 UI들을 모아, 계층 관계를 갖도록 컴포지트 패턴을 적용했습니다.
  • Initialize() 시 json 파일로부터 부모 구조를 읽어와 조립합니다.
  • 이를 통해 UI 애니메이션 등에서 부모를 통해, 하위 자식들을 일관적으로 제어할 수 있게 됩니다.

1-A. 공통 부모를 통한 컴포지트 구조

2026-09-07-08-33-26

  • 모든 UI는 Custom_UI Class를 상속받습니다. 이는 곧, 모든 UI가 부모와 자식 정보를 가짐을 의미합니다.
  • 상기 사진과 같이, Local Matrix와 별개로, 매 프레임 갱신되는 Combined World Matrix를 갖습니다. 이를 통해 부모 대비 상대좌표가 갱신됩니다.
  • 이 Combined World Matrix는 컴포지트 구조의 특성을 통해, 자식들에게 연쇄적으로 내려가 반영되게 됩니다. 이는 애니메이션에서도 마찬가지입니다.

1-B. UI Animator 컴포넌트

2026-09-07-08-40-31

  • UI Animator에서는 로드된 애니메이션 정보에 기반해, Keyframe과 Lerp Type에 따라 보간 비율을 다르게 가져갑니다.
  • 애니메이션으로 최종 계산된 행렬은 Local Matrix에 반영되게 됩니다.
  • 해당 애니메이션은 자체 에디터에서 제작, 편집이 가능합니다.

1-C. UI 배치 / 애니메이션 에디터

2026-09-07-08-44-26

  • Load Image를 통해 이미지를 오브젝트로서 Load가 가능합니다. Load 이전에, 해당 오브젝트가 일반 오브젝트일지, 인스턴스 오브젝트일지를 선택해야 합니다.
  • 유니티의 Hierarchy 창에 착안하여, 부모 구조를 직관적으로 확인할 수 있는 UI Hierarchy 창을 제작했습니다.
  • 여기에서는 Transform 제어부터, 셰이더 Pass Type, 부모 수정, 이름 수정, 입출력까지 가능합니다.
  • 실수로 Parent를 잘못 기입하면 안보이는 불상사가 생겨서.. 부모가 없는 Object는 최하단의 Missing Parent Objects에 표시되게 만들었습니다.

2026-09-07-08-44-43

  • 인스턴스 오브젝트로 생성 시, 같은 리소스를 이용해 여러 개의 인스턴스를 생성할 수 있습니다.
  • 인스턴스별로 추가적인 Transform, 이미지 컷팅/클리핑(Atlas 지원용)과 같은 기능을 사용 가능합니다. 이는 코드를 통해서도 각 인스턴스 별로 제어가 가능합니다.

2026-09-07-08-40-17

  • 애니메이션은 오브젝트 단위로 적용이 가능하며, 지원되는 Keyframe 유형은 Transform, Clipping, Lerp Type, Alpha 정도입니다.
  • Instant Load Anim - Play Animation을 통해 에디터상에서 애니메이션의 미리보기가 가능합니다. Load도 가능합니다.

2. 폰트 시스템 구현

flowchart LR
    A["Update_Description()"]
        --> B["Get_GlyphAndAdvance()"]
        --> C["BakeOneGlyph()<br/>(필요 시)"]
        --> D["Render()"]
  • 로딩 시 FreeType 라이브러리를 통해 사용할 폰트를 불러오고, 런타임 중에 빈 Font Atlas를 생성합니다.
  • 이후 텍스트 출력 필요 시, 사전 로드된 폰트로부터 글자별 SDF 텍스쳐를 생성해 Atlas에 그리고, 이를 사용하는 방식입니다. 만약 이미 생성되어 있다면, 그쪽을 우선적으로 사용합니다.

3. UI Shader 구현

3-A. 일반 UI Shader

2026-09-07-09-47-51

  • 셰이더는 기본 오브젝트, 인스턴스 오브젝트 별로 각각 1개씩 사용하며, 필요에 따라 Pass를 전환하는 방식입니다.
  • 기본 Pass는 위와 같이, Normal, Cutout, Transparent 와 같은 유형이 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
float2 Calc_NineSectorUV(float2 originPos, float2 modSize, float2 border, float2 imageSize)
{
  // 전체 대비 왼쪽/위 로부터 얼마나 오른쪽/아래에 있는지의 비율
  float2 resultUV;
  
  // x축 계산
  if (originPos.x < border.x)                    // 왼쪽.
    resultUV.x = originPos.x / imageSize.x;
  else if ((modSize.x - border.x) < originPos.x)      // 오른쪽. 
    resultUV.x = (originPos.x - (modSize.x - imageSize.x)) / imageSize.x;
  else
  {
    // [ originPos.x - border.x ] ~ [ originPos.x ] 의 사잇값인 originPosX_OnMod 를
    // [ border.x ] ~ [ modSize.x - border.x ] 사이로 비율을 맞춰야 함 
    float originPosX_OnMod = originPos.x - border.x;

    float startX = border.x;
    float endX = modSize.x - border.x;
    
    float resultRatio = originPosX_OnMod / (endX - startX);
    
    resultUV.x = (border.x + (resultRatio * (imageSize.x - border.x * 2))) / imageSize.x;
  }

  // y축 계산
  if (originPos.y < border.y)                    // 위쪽
    resultUV.y = originPos.y / imageSize.y;
  else if ((modSize.y - border.y) < originPos.y)      // 아래쪽.
    resultUV.y = (originPos.y - (modSize.y - imageSize.y)) / imageSize.y;
  else
  {
    float originPosX_OnMod = originPos.y - border.y;

    float startY = border.y;
    float endY = modSize.y - border.y;
    
    float resultRatio = originPosX_OnMod / (endY - startY);
    
    resultUV.y = (border.y + (resultRatio * (imageSize.y - border.y * 2))) / imageSize.y;
  }
  
  return resultUV;
}
  • 체력바와 같이 외곽부의 형태가 유지되어야 하는 가변형 UI를 위해, 9-Slicing을 위한 Pass도 구현했습니다.
  • 이외 각 용도마다 다른 효과를 주기 위해, UI마다 전용 Pass를 구현했습니다.
  • 지금 생각해보면 여러 UI 케이스마다 Pass를 새로 만들지 말고, 다른 상용 셰이더들처럼 일관되게 효과를 줄 수 있는 변수 버퍼 체계를 만들어서 통합하는 게 훨씬 나았을 것 같습니다. 한 Pass에 9-Slicing, Dissolve, VS Transform 조절 등을 선택적으로 조합 가능하게끔요.

2026-09-07-09-59-18

  • 인스턴스 오브젝트에서 Atlas 텍스쳐도 사용 가능하도록, X/Y Range값을 통해 UV 범위를 조절할 수 있게 제작했습니다.
  • 이 방식은 미니맵, 스킬 아이콘, 단축키 아이콘 등에서 사용되었습니다.

3-B. 폰트 SDF Shader

2026-09-07-10-02-44

  • Glyph를 그릴 때, FT_RENDER_MODE_SDF 옵션을 통해 SDF 텍스쳐로 그려지도록 했습니다.
  • 셰이더로 넘어간 SDF 텍스쳐를 샘플링해서, R 채널 값의 구간에 따라 색을 다르게 입히도록 해서 글자 색과 Outline을 구현했습니다.
  • 이후 해당 과정을 색상 프리셋 지정이 가능한 형태로 래핑해서, 다른 팀원들이 간편히 이용 가능한 형태로 제공했습니다.

4. 미니게임 구현

2026-09-07-10-08-55 2026-09-07-10-12-35

  • 미니게임 다채화를 구현했습니다. 이는 제한된 횟수의 클릭으로, 모든 칸을 특정 색상으로 바꾸는 퍼즐입니다.
  • std::queue를 통한 BFS 알고리즘을 사용하여, 클릭 시 동일 색상의 인접 타일들을 탐색합니다.
  • 이후 가까운 타일부터, Dissolve 및 색상전환 효과를 재생합니다.
  • 레벨 데이터는 .csv 파일로 관리했습니다.

Etc.

  • 몬스터 HP 바도 파동 형태로 제작했는데, 이는 기존 HP바가 너무 단조로워보인다는 피드백을 받아 어떻게하면 좀 특이해보일까 하고 만든 결과물입니다.
  • HUD 하단의 에너지 게이지도 열심히 만들었습니다. 인스턴스마다 일렁이는 효과 주는게 재밌었습니다.
  • 투척 궤적을 미리 보여주는 가이드 UI도 만들었습니다. 이는 매 프레임마다 위치, 속도, 가속도 정보를 받아 해당 경로에 맞는 리본메쉬를 생성하고, 각 리본메쉬 구간마다 Raycast를 검사하여 충돌이 감지되는 구간에 리본메쉬를 끊기 + 해당 교차점에 구체를 생성하는 방식으로 구현했습니다. 구체에는 카메라와 구체 메쉬의 노말벡터를 계산해서 셰이더로 프레넬 효과도 줬어요.
  • 컷씬이나 NPC와의 대화 상황을 상정해서, 대화 창(Dialog) UI도 제작했습니다. 한 글자씩 순차적으로 Fade In 효과를 주게 했어요. 그리고 키 입력을 막고 함수 호출로 대화를 넘기거나, 입력으로 대화를 넘길 수 있게 옵션을 대응해뒀습니다. (대화 데이터는 .csv로 관리했습니다.)
  • 이외 데미지 폰트, 미니맵, 도구선택 UI(Tab UI), HP바 등도 만들었습니다.

  1. DirectX 11 학습과 병행한 기간입니다. ↩︎

This post is licensed under CC BY 4.0 by the author.

댓글

불러오는 중...