Home 4강 프로젝트 세팅
Post
Cancel

4강 프로젝트 세팅

4강 프로젝트 설정

프로젝트 만들기 & 설정하기

[1]

Untitled 프로젝트 생성 - C++ 언어 설정 - Window 데스크탑 애플리케이션 프로젝트 만들기 - 정적 라이브러리 타입의 프로젝트 추가 (이름은 Engine)

  • 필터 추가 (Engine, Resource, Utils) - 한글 폴더 제거 - Utils필터에 소스코드들 추가 - Engine.cpp 제거 (필요 없다)

DLL(동적 라이브러리)와 정적 라이브러리의 차이점

DLL : 런타임에 연결되는 라이브러리

정적 라이브러리 : 소스 코드를 빌드할때 포함되어 연결되는 라이브러리

라이브러리(엔진)을 분리하는 이유

클라이언트 (컨텐츠 부분) 과 엔진 부분을 나누기 위함이다

빌드 시 엮여있는 상황이 될 것. 예시로 엔진 수정 시 클라이언트까지 빌드를 해야 함 ⇒ 최악🤮

[2] Engine 프로젝트의 특징

  • 메인 함수가 없다

    기능 모음집 (=라이브러리) 이기 때문이다

다음을 pch.h (프리 컴파일된 헤더) 에 코딩하고 framework.h 제거

1
2
3
// framework.h의 유일한 한줄 코드입니다

#define WIN32_LEAN_AND_MEAN             // 거의 사용되지 않는 내용을 Windows 헤더에서 제외합니다.

(결과) - pch.h

1
2
3
4
5
6
#ifndef PCH_H
#define PCH_H

#define WIN32_LEAN_AND_MEAN             // 거의 사용되지 않는 내용을 Windows 헤더에서 제외합니다.

#endif //PCH_H
  • Utils 에 클래스 추가 (EnginePch)

Untitled

  • EnginePch.h 에 다음 코딩 (앞으로 사용하게 될 라이브러리들)
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
46
#pragma once

// 각종 include
#include <windows.h>
#include <tchar.h>
#include <memory>
#include <string>
#include <vector>
#include <array>
#include <list>
#include <map>
using namespace std;

#include "d3dx12.h"
#include <d3d12.h>
#include <wrl.h>
#include <d3dcompiler.h>
#include <dxgi.h>
#include <DirectXMath.h>
#include <DirectXPackedVector.h>
#include <DirectXColors.h>
using namespace DirectX;
using namespace DirectX::PackedVector;
using namespace Microsoft::WRL;

// 각종 lib (라이브러리)
#pragma comment(lib, "d3d12")
#pragma comment(lib, "dxgi")
#pragma comment(lib, "dxguid")
#pragma comment(lib, "d3dcompiler")

// 각종 typedef 오른쪽의 형을 왼쪽으로 사용할 수 있게 함
using int8		= __int8;
using int16		= __int16;
using int32		= __int32;
using int64		= __int64;
using uint8		= unsigned __int8;
using uint16	= unsigned __int16;
using uint32	= unsigned __int32;
using uint64	= unsigned __int64;
using Vec2		= XMFLOAT2;
using Vec3		= XMFLOAT3;
using Vec4		= XMFLOAT4;
using Matrix	= XMMATRIX;

void HelloEngine();

내용 중 #include "d3dx12.h"

이 파일은 없음! 마이크로소프트 d3dx12.h파일 깃허브

이 곳에서 직접 다운 받아서 프로젝트에 넣어야 함 !

  • 마이크로 소프트에서 지원해주는 비 공식적 유틸리티 라이브러리
  • 편리하게 이용할 수 있는 기능들이 모여있음

이제 Engine.cpp 안의 다음 HelloEngine()을 클라이언트에서 부를 수 있게 할 것

1
2
3
4
5
6
7
#include "pch.h"
#include "EnginePch.h"

void HelloEngine()
{

}
  • pch.h 에 다음 추가
1
#include "EnginePch.h"
  • EnginePch.h은 공용 헤더로써, 나중에 클라이언트에서 EnginePch.h 을 사용하기 위해서 따로 분리를 하였다

빌드해보기

빌드를 하면 프로젝트 폴더의 x64 - Debug 폴더 안에 내용물이 만들어진다.

Untitled

  • Engine.lib 파일
    • 후에 이 파일을 클라이언트에서 사용하게 된다
  • Client.exe 파일은 실행할 수 있지만, Engine파일은 그렇지 않음. 차이가 있다

[2]

Client 설정

Client 프로젝트 (우클릭) 속성에서 다음과 같이 설정

  • 미리 컴파일된 헤더 - 사용 설정, pch.h 를 미리 컴파일된 헤더 파일로 설정

  • 플랫폼을 x64로 설정

Untitled

Client (우클릭) 클래스 추가 - pch 클래스 추가

  • Client 필터 추가 Game, Utils - Utils 에 모든 소스코드 넣기 - 헤더파일 폴더 삭제

생성한 pch.cpp 에서 속성 페이지 - c/c++ 설정 - 미리컴파일된 헤더 : 만들기 설정

앞으로 생성할 cpp 파일들에서 다음 헤더를 가장 상위에 추가 해야 함

  • 안 하면 에러가 난다
1
#include "pch.h"

[3] pch.h 설명

1
2
3
4
5
#pragma once

#pragma comment(lib, "Engine.lib")

#include "EnginePch.h"

#include "EnginePch.h" 에서 에러가 나는 이유 🔥🔥🔥

  • Engine 폴더와 Client 폴더의 경로가 다르기 때문 ⇒ 경로를 설정해 주어야 한다!

[4] 빌드 결과물이 (x64 폴더 말고) 다른 폴더에 만들어지게 할 때, 사전 세팅

원하는 프로젝트 ( 여기선 Engine 프로젝트) - 속성 - 구성 속성 - 일반 - 출력 디렉터리

다음과 같이 설정

$(SolutionDir)[폴더명]\

이렇게 하면 빌드 후 [폴더명] 에 Engine 프로젝트 빌드 결과가 저장이 된다

[5] 클라이언트에서 Engine 의 코드들을 사용하기

클라이언트에서 Engine 의 코드들을 사용하기

⇒ 엔진의 [1] 헤더 파일들의 경로와 [2] 라이브러리 파일의 경로 [3] 사용할 파일들의 경로를 알려주어야 함

[1] Client 속성 - C/C++ 일반 - 추가 포함 디렉터리

  • $(SolutionDir)Engine\

[2] Client 속성 - 링커 - 일반 - 추가 라이브러리 디렉터리

  • $(SolutionDir)Output\
    • 위 [4]단계에서 빌드 결과물이 있는 폴더 명을 써야 함

[3] 사용할 파일들을 알려주기

pch.h 에 #include "EnginePch.h" 윗줄에 다음 코딩

#pragma comment(lib, “Engine.lib”)

  • 전처리기 단계에서 빌드하기 전에 “Engine.lib” 파일을 사용할 것을 요청함

⇒ 이 단계까지 끝나면 [3] pch.h 설명에서 났던 에러가 사라진다! 🔥🔥🔥

클라이언트에서 Engine 의 함수 사용하기

  • 기능 추가는 X

[1]

Game 폴더 - 추가 클래스 - Game 클래스 추가

여기서 만들었던 Game.cpp 파일에 다음과 같이 코딩 ⇒ 엔진에 있던 함수를 호출하게 만들어보자

🔽 Game.cpp

1
2
3
4
5
6
7
8
9
10
11
12
#include "pch.h"
#include "Game.h"

void Game::Init()
{
	HelloEngine();
}

void Game::Update()
{

}
  • HelloEngine(); : Engine.cpp 에 있던 함수이다 ! ✨

[2]

Client.cpp 파일에서 wWinMain메인 함수 안에서 다음과 같이 무한루프를 돌며 기능을 수행 중이다

(라고 까지만 대강 알고 있자)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
                break;

			if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
        }

		// TODO
        game->Update();
    }

🔼 무한 루프문

Game 클래스 내용을 메인함수 wWinMain에서 호출하기

⇒ 다음을 wWinMain 의 while 무한루프 위에 코딩

1
2
unique_ptr<Game> game = make_unique<Game>(); //Game 클래스 만들기
game->Init(); //초기화 시키기

다음을 wWinMain 의 while 무한루프 에 코딩

1
game->Update(); //갱신하기
  • Game 이 while 문이 도는 주기 (프레임) 만큼 갱신이 된다

[3]

1
2
3
4
while (GetMessage(&msg, nullptr, 0, 0)) {
	if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
	...
}

다음은 마우스나 키보드의 입력 등 이벤트가 있을 시 GetMessage로 깨어나서 while문을 돌겠다는 의미이다 …

⇒ 그런 이벤트 없이, 이벤트 메시지가 있건 없건 실행되어야 하기 때문에 다음과 같이 코딩한다

완성된 메인함수의 while 문

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
while (true)
    {
        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
                break;

			if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
        }

		// TODO
        game->Update();
    }
  • 스마트 포인터 사용
1
unique_ptr<Game> game = make_unique<Game>();

파일, 도움말 메뉴 뜨지 않게 하기

여기까지 과정을 실행하면 다음과 같이 파일, 도움말 메뉴가 달린 Client 가 실행된다

이를 없애보자

Untitled

  • Client.cpp 에서 MyRegisterClass 부근의 wcex.lpszMenuName 값을 바꿔준다
1
wcex.lpszMenuName   = nullptr;

결과) 파일, 도움말 메뉴가 사라져 말끔해진 Client.exe 실행 결과

Untitled

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