[Portfolio] 게임개발 프로젝트 포트폴리오.
Windows API와 DirectX 9, 11 기반의 프로젝트 4개 기록
[Portfolio] 게임개발 프로젝트 포트폴리오.
개요
이 글은 게임개발 학원 재원 당시 진행했던 프로젝트들에 관해 작성한 글입니다.
저는 2025년과 그 전후로 게임 개발에 대해 학습하면서, C++을 통해 Windows API / DirectX 9 / 11 사용법을 익혔고, 이를 기반으로 간단한 엔진 구현부터 클라이언트 개발까지 진행해봤습니다.
(이후 현재는 부족하다 느꼈던 기초 CS지식들과 상용 게임엔진을 학습중이며, 개인적으로 보드게임 프로젝트도 제작해보고 있습니다.)
아래는 그 4개의 프로젝트들에 대한 글입니다.
순서 및 요약
시간 순서입니다! (아래로 갈 수록 최신)
- Windows API 기반 2D 게임 모작. (개인 프로젝트)
- 모작 대상은 동방 루나 나이츠입니다.
- 유명한 IP인 동방프로젝트를 기반으로 한, 2D 기반의 횡스크롤 메트로바니아 게임입니다.
- 주요 구현점은
WinAPI기반 엔진 루프 구현, 맵 데이터/입출력 구현, 스테이지 4개 제작, 일반 몬스터 2종 구현, 보스 1종 구현, 시간 기믹 구현 정도입니다. - 제대로 된 개발을 해본 경험은 처음이었고, 각종 디자인패턴이나, 설계 원칙 등에 대해서는 아직 알지 못하던 시기였습니다. 때문에 코드에 아쉬운 점이 많고, 엔진과 클라이언트의 경계가 없습니다.
- DirectX 9 기반 2.5D 게임 모작. (팀 프로젝트)
- 모작 대상은 세피리아입니다. 2D 리소스를 이용, 3D 상에서 플레이 가능하게 제작했습니다.
- 다만 리소스와 게임 방식에 Bleak Sword DX라는 게임의 요소를 차용해서, 로그라이트 3D 게임으로 구현했습니다.
- 저는 플레이어 및 몬스터 담당으로써, 플레이어와 몬스터 3종, 보스 2종을 작업했습니다.
- 지금 다시보면, 몬스터나 플레이어의 상태 구조를 제작할 때
FSM이나Behavior Tree를 쓰면 됐을 텐데, 당시에는 이를 몰라서 많이 어렵게 만들었습니다.
- DirectX 11 기반 3D 게임 모작. (개인 프로젝트)
- 모작 대상은 슈퍼핫입니다. 시간 정지를 기믹으로 하는 싱글 FPS 게임입니다.
- 주요 구현점은
DirectX 11기반 엔진 루프 구현,Ray Picking을 통한 3D 맵 에디터/입출력 구현,FSM기반 몬스터 애니메이션 및 AI 구현, 시간 기믹 구현, 파티클 구현, 스테이지 4개 제작 등입니다. - 지금 봐도 결과물이 별로 좋아보이진 않습니다. 그래서 되돌아보면 많이 부끄럽네요.
- 그래도 3D 리소스를 직접 다뤄보고, 제어시켜본 만큼 배운 건 많았습니다.
성공적이라고 하긴 어렵겠지만어쨌든 마무리는 지었기도 하고요.
- DirectX 11 기반 3D 게임 최종 프로젝트. (팀 프로젝트)
- 모작 대상은 명조입니다. 여기서는 팀 각자의 역할에 따라, 개인 에디터 우선 제작 후 구현 작업에 들어갔습니다.
- 저는 UI 담당으로써, UI 배치 및 애니메이션 에디터에 더해, HUD와 미니맵 / QTE / UI의 GPU 인스턴싱 / FreeType을 통한 폰트 렌더링 및 셰이더 (SDF, Outline) 및 UI 셰이더 구현(9-Slicing, Dissolve) 등을 작업했습니다.
- 이 기간동안 많은 시간을 셰이더에 쏟았는데(인스턴싱, UI 효과, 폰트 등 때문에..), 셰이더 참 재밌는 물건이구나 싶었습니다.
- 파트 특성상 다른 파트와 합을 맞출 일이 많았었는데, 요청에 따라 내가 제작한 기능들을, 다른 개발자가 사용하기 좋은 형태로 래핑해서 제공해주고 피드백을 받는 즐거움도 있었습니다.
본문
Media Group 창 상단의 탭을 통해 영상으로의 전환이 가능합니다!
또한 접기 처리된 내용을 펼쳐 상세 내용을 확인할 수 있습니다.
WinAPI 2D : 동방 루나 나이츠
| 인원 | 1인 (개인 프로젝트) |
| 모작 대상 | 동방 루나 나이츠 |
| 개발기간 | 25. 2. 7. ~ 2. 26. (20일) |
| 사용 언어 | C++ |
| 사용 라이브러리 | Windows API, FMOD |
| 깃허브 링크 | Github : ProjectTH |
상세 내용 펼치기
1. 맵 에디터 구현
- 지형 및 몬스터 배치를 위해 간단한 맵 에디터를 제작했습니다.
- 지형은 편집 단계에서는 타일 텍스쳐 형태로 표시되며, 실제 플레이 시 해당 형태에 대응하는 콜라이더로 변환됩니다.
- 단축키를 통해 맵 뷰어 모드와 지형 편집 모드를 전환할 수 있습니다.
- 편집한 지형 및 오브젝트 배치 정보는 파일로 저장하고, 스테이지 진입 시 다시 불러오도록 구성했습니다.
- 해당 에디터를 통해 스테이지를 4개 제작했습니다.
2. NPC 구현
- 상호작용이 가능한 NPC 두 종을 구현했습니다.
- 한 명은 시간 정지 능력의 해금 수단, 다른 한 명은 보스 방까지 가는 매개체로써 구성했습니다.
- 일정 좌표 내에 들어가있을 시, 상호작용이 가능하도록 제작했습니다.
3. 시간 기믹 구현
- 시간 느려짐(SNAIL), 시간 정지(STOP) 기믹을 구현했습니다.
- 느려짐 상태에서는 Player, UI, Effect 레이어를 제외한 모든 오브젝트가 1/2배속으로, 정지 상태에서는 멈추게 제작했습니다.
ObjMgr에서 단순히 Update 빈도를 제어하는 방식입니다. - 단, 보여야 하므로 RenderGroup 삽입은 항시 돕니다.
4. 몬스터 및 보스 구현
- 몬스터는 간단한 행동 패턴을 가진 두 종류(늑대와 위습)를, 보스로는 홍 메이링을 제작했습니다.
- 보스는 경과 프레임에 따라 패턴이 변화하는 방식으로 제작했습니다. 등장/퇴장 연출도 있고요.
DX9 2.5D : 세피리아 + Bleak Sword DX
| 인원 | 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. 플레이어 구현
- 플레이어의 전반적인 조작을 구현했습니다. (이동, 대시, 평타, 패리, 퓨리)
- 마우스 위치를 기준으로 공격 방향을 결정하고, 짧은 시간 내 연속 입력 시 다음 동작이 이어지도록 제작했습니다.
- 대시는 WASD 조작 중이라면 해당 방향으로, 아니라면 마우스 방향으로 돌진합니다.
1-A. 무기 애니메이션 구현
실제 구현 애니메이션 코드
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. 몬스터 구현
- 몬스터는 간단한 행동 패턴을 가진 3종(두더지, 돼지, 레이저 몹)을 제작했습니다.
- 레이저 몹의 경우, 플레이어 방향으로 락온 이후 해당 방향으로 레이저가 따라 돌아갑니다.
3. 보스 구현
- 보스는 경과 프레임에 따라 패턴이 변화하는 방식으로 제작했습니다.
- Erma의 경우 두더지 본체와 양 손, 머리 객체가 분리되어있고, 본체에 의해 동작이 제어되는 구조입니다.
- Askard는 두 개의 페이즈로 구성했으며, 촉수/레이저/충격파 등의 패턴과 2페이즈용 강화 패턴을 구현했습니다. 또한 간헐적으로 고정된 촉수 오브젝트를 소환합니다.
- QTE 패턴은 UI를 담당한 팀원분께서 제작해주셨습니다.
DX11 3D : 슈퍼핫
| 인원 | 1인 (개인 프로젝트) |
| 모작 대상 | 슈퍼핫 |
| 개발기간 | 25. 7. 7. ~ 9. 26. (82일)1 |
| 사용 언어 | C++, HLSL |
| 사용 라이브러리 | DirectX 11, DirectX Tool Kit, FMOD, ImGui, Assimp |
| 깃허브 링크 | Github : PSN_PROJECT |
상세 내용 펼치기
1. 3D 맵 에디터 구현
- 레벨 제작 및 편집을 용이하게 하기 위해 3D 모델 배치기를 구현했습니다.
- Ray Picking을 통한 클릭 지점 배치 or 임의 위치 모델 배치 및 Transform 수정, 모델 입출력 등이 가능합니다.
- 추가로 Navmesh 편집 기능 및 배치 시 Snap이 가능하도록 제작해, 추후 인게임에서 낮은 부하로 지형 위를 걸을 수 있도록 했습니다.
- 편집기 UI 제작에는
ImGui라이브러리를, 모델 입출력 시.fbx데이터를 읽어오는 데에는Assimp라이브러리를 사용했습니다.
2. FSM 기반 AI
- 유니티의
Animator시스템에 착안하여, FSM(유한 상태 기계) 방식으로 적의 AI를 구현했습니다. - 유니티의
Animator Parameter와 유사하게, 상태 제어에 필요한 변수들(사진의tAIParam)을 사전에 정의해두고, 이를 외부에서 조작 가능하도록 제작했습니다. - 이를 통해 적은 사진과 같은 6개의 상태를 가지며, 상태마다 다른 행동 패턴을 보입니다.
지금 다시보니 Blackboard 패턴이라고 부르긴 힘든 것 같습니다.
3. 무기 구현 및 상호작용
- 빈손인 경우, 중앙 커서의 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 : 명조
| 인원 | 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 부모 구조 구현
해당 json 파일의 내부 구조.
현재 보이는 부분이 상기 사진의 Line_Bar 부분입니다.
- 연관성이 있는 UI들을 모아, 계층 관계를 갖도록 컴포지트 패턴을 적용했습니다.
Initialize()시json파일로부터 부모 구조를 읽어와 조립합니다.- 이를 통해 UI 애니메이션 등에서 부모를 통해, 하위 자식들을 일관적으로 제어할 수 있게 됩니다.
1-A. 공통 부모를 통한 컴포지트 구조
- 모든 UI는
Custom_UIClass를 상속받습니다. 이는 곧, 모든 UI가 부모와 자식 정보를 가짐을 의미합니다. - 상기 사진과 같이,
Local Matrix와 별개로, 매 프레임 갱신되는Combined World Matrix를 갖습니다. 이를 통해 부모 대비 상대좌표가 갱신됩니다. - 이
Combined World Matrix는 컴포지트 구조의 특성을 통해, 자식들에게 연쇄적으로 내려가 반영되게 됩니다. 이는 애니메이션에서도 마찬가지입니다.
1-B. UI Animator 컴포넌트
- UI Animator에서는 로드된 애니메이션 정보에 기반해,
Keyframe과Lerp Type에 따라 보간 비율을 다르게 가져갑니다. - 애니메이션으로 최종 계산된 행렬은
Local Matrix에 반영되게 됩니다. - 해당 애니메이션은 자체 에디터에서 제작, 편집이 가능합니다.
1-C. UI 배치 / 애니메이션 에디터
Load Image를 통해 이미지를 오브젝트로서 Load가 가능합니다. Load 이전에, 해당 오브젝트가 일반 오브젝트일지, 인스턴스 오브젝트일지를 선택해야 합니다.- 유니티의
Hierarchy창에 착안하여, 부모 구조를 직관적으로 확인할 수 있는 UI Hierarchy 창을 제작했습니다. - 여기에서는 Transform 제어부터, 셰이더 Pass Type, 부모 수정, 이름 수정, 입출력까지 가능합니다.
- 실수로 Parent를 잘못 기입하면 안보이는 불상사가 생겨서.. 부모가 없는 Object는 최하단의 Missing Parent Objects에 표시되게 만들었습니다.
- 인스턴스 오브젝트로 생성 시, 같은 리소스를 이용해 여러 개의 인스턴스를 생성할 수 있습니다.
- 인스턴스별로 추가적인
Transform, 이미지 컷팅/클리핑(Atlas지원용)과 같은 기능을 사용 가능합니다. 이는 코드를 통해서도 각 인스턴스 별로 제어가 가능합니다.
- 애니메이션은 오브젝트 단위로 적용이 가능하며, 지원되는
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
- 셰이더는 기본 오브젝트, 인스턴스 오브젝트 별로 각각 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 조절 등을 선택적으로 조합 가능하게끔요.
- 인스턴스 오브젝트에서 Atlas 텍스쳐도 사용 가능하도록, X/Y Range값을 통해 UV 범위를 조절할 수 있게 제작했습니다.
- 이 방식은 미니맵, 스킬 아이콘, 단축키 아이콘 등에서 사용되었습니다.
3-B. 폰트 SDF Shader
- Glyph를 그릴 때, FT_RENDER_MODE_SDF 옵션을 통해 SDF 텍스쳐로 그려지도록 했습니다.
- 셰이더로 넘어간 SDF 텍스쳐를 샘플링해서, R 채널 값의 구간에 따라 색을 다르게 입히도록 해서 글자 색과 Outline을 구현했습니다.
- 이후 해당 과정을 색상 프리셋 지정이 가능한 형태로 래핑해서, 다른 팀원들이 간편히 이용 가능한 형태로 제공했습니다.
4. 미니게임 구현
- 미니게임 다채화를 구현했습니다. 이는 제한된 횟수의 클릭으로, 모든 칸을 특정 색상으로 바꾸는 퍼즐입니다.
std::queue를 통한BFS알고리즘을 사용하여, 클릭 시 동일 색상의 인접 타일들을 탐색합니다.- 이후 가까운 타일부터,
Dissolve및 색상전환 효과를 재생합니다. - 레벨 데이터는
.csv파일로 관리했습니다.
Etc.
- 몬스터 HP 바도 파동 형태로 제작했는데, 이는 기존 HP바가 너무 단조로워보인다는 피드백을 받아 어떻게하면 좀 특이해보일까 하고 만든 결과물입니다.
- HUD 하단의 에너지 게이지도 열심히 만들었습니다. 인스턴스마다 일렁이는 효과 주는게 재밌었습니다.
- 투척 궤적을 미리 보여주는 가이드 UI도 만들었습니다. 이는 매 프레임마다 위치, 속도, 가속도 정보를 받아 해당 경로에 맞는 리본메쉬를 생성하고, 각 리본메쉬 구간마다 Raycast를 검사하여 충돌이 감지되는 구간에 리본메쉬를 끊기 + 해당 교차점에 구체를 생성하는 방식으로 구현했습니다. 구체에는 카메라와 구체 메쉬의 노말벡터를 계산해서 셰이더로 프레넬 효과도 줬어요.
- 컷씬이나 NPC와의 대화 상황을 상정해서, 대화 창(Dialog) UI도 제작했습니다. 한 글자씩 순차적으로
Fade In효과를 주게 했어요. 그리고 키 입력을 막고 함수 호출로 대화를 넘기거나, 입력으로 대화를 넘길 수 있게 옵션을 대응해뒀습니다. (대화 데이터는.csv로 관리했습니다.) - 이외 데미지 폰트, 미니맵, 도구선택 UI(Tab UI), HP바 등도 만들었습니다.
DirectX 11 학습과 병행한 기간입니다. ↩︎
This post is licensed under CC BY 4.0 by the author.


























댓글
불러오는 중...