*** 공부하는 방법 ***
1. 코딩을 해야 하는 부분은 첫 부분에 변수나 함수, 메소드에 대한 선언이 코드블럭으로 표시되어 있다.
//ex)
MakeFunction();
2. 코드블럭 하단에는 해당 선언에 대한 구현 로직이 작성되어 있다.
(ex)
- 이 함수는 int형 변수 x와 y를 인자로 받는다.
- x와 y의 합을 구해 int형으로 return한다.
3. 해당 구현 로직을 보고 Visual Studio에서 직접 코드를 작성해 본다.
4. 각 글에는 참고용 코드 솔루션 첨부파일이 업로드되어 있다.
이 코드와 내 코드를 비교하여 분석하고, 개선점이 있으면 수정한다.
물론 참고 코드가 최고의 방법이라는 것은 아니다. 내가 짠 코드가 더 효율적이라 생각되면 내 코드를 그대로 사용하자.
int MakeFunction(int x, int y)
{
return x + y;
}
- 프레임워크부터는 파일들이 많아 복잡하므로, 프로젝트 파일들을 여러 폴더에 정리하여 저장해 주어야 한다.
- 그러므로 몇 가지 사전 설정을 해 주어야 한다.
[사전 설정]
1. 일단 생성된 프로젝트를 우클릭하여 솔루션에서 제거한다.(삭제 X)
2. 프로젝트가 있는 폴더 안에 정리를 위한 폴더를 생성한다.
* 프로젝트 폴더/Include: 프로젝트 및 소스코드
* 프로젝트 폴더/Bin: 게임 만드는 실행파일, 이미지 등 리소스 파일
* 프로젝트 폴더/BinObj: 소스코드를 컴파일하기 위한 중간 Obj파일이 들어올 폴더
3. 프로젝트 폴더 안 폴더를 제외한 기존 파일들을 모두 Include 폴더 안으로 이동시킨다.
4. 솔루션 우클릭 -> 추가 -> 기존 프로젝트 들어가서
Include 폴더로 옮긴 프로젝트를 다시 추가해준다.
5. 상단 드롭다운 메뉴 - 프로젝트 - 프로젝트 속성 - 상대 경로(프로젝트가 있는 Include 폴더 기준)로 설정
* 구성: 모든 구성
* 플랫폼: 모든 플랫폼
* 출력 디렉터리: 컴파일된 파일이 들어갈 곳
- ../Bin/
- 이전 폴더로 가서 -> Bin 폴더로 들어가라
* 중간 디렉터리: 컴파일 및 빌드를 할 때 중간에 생기는 파일들이 들어갈 곳
- ../BinObj/
- 이전 폴더로 가서 -> BinObj 폴더로 들어가라
cf)이전 폴더: ../
이전 폴더에 있는 Bin 파일: ../Bin
*** 여기서 적용 한번 눌러줌 ***
* 대상 이름 - 디버그했을때 나오는 프로그램과 일반 출력을 했을때 나오는 프로그램 명이 다르게 해 주자
- 구성 - 모든 구성 항목 - 기본값으로 두기: $(ProjectName)
- 구성 - Debug 항목: $(ProjectName)_Debug
GameInfo.h
- 각종 클래스들에서 공통적으로 참조할만할 내용들을 담을 GameInfo.h 헤더를 하나 생성한다.
- 일단 가장 기본적인 윈도우 헤더, 리스트 헤더, 배열(vector) 헤더, 연관 컨테이너 헤더를 추가하자.
SingletonMacro.h
#define DECLARE_SINGLETON(Type)
#define DEFINITION_SINGLETON(Type)
- SingletonMacro 헤더를 생성한다.
- DECLARE_SINGLETON: 헤더 파일에 사용하여 사용시 클래스를 Singleton pattern으로 바꾸어 주는 기능을 구현한다.
- m_Inst: 만들어진 싱글턴 패턴 클래스의 주소를 들고있을 포인터 변수
- GetInst(): 싱글턴 패턴의 초기화 및 주소를 받아오는 메소드
- DestroyInst(): 싱글턴 패턴 클래스를 메모리에서 제거하는 메소드
- DEFINITION_SINGLETON: cpp 파일에 사용하여 사용시 m_Inst를 초기화해주는 매크로
- cf)정적변수는 클래스 내부에서 초기화가 불가능하다.
- DECLARE_SINGLETON: 헤더 파일에 사용하여 사용시 클래스를 Singleton pattern으로 바꾸어 주는 기능을 구현한다.
class CGameManager
- CGameManager 클래스를 '싱글턴 패턴'으로 생성한다.
- 클래스 멤버 변수들은 무조건 이름 앞에 소문자 m_을 붙여 클래스 멤버 변수임을 알수 있게 해 줄것이다.
- 앞으로 클래스명은 무조건 이름 앞에 대문자 'C'를 넣어 구분할 수 있게 해 줄것이다.
- 클래스의 '파일 이름'에는 C를 붙이지 않는다.
- CGameManager 클래스는 wWinMain 함수에서 가장 먼저 호출되어 win32api 창을 생성하기 위한 절차를 진행하고, wWinMain 함수와 직접 연결되어 전체적인 게임 진행을 컨트롤하는 클래스이다.
<변수 목록>
- m_hInstance: wWinMain 함수에서 받아온 HINSTANCE 정보 저장
- m_hWnd: CreateWindowW() 함수를 통해 만들어진 창의 정보 저장
- m_Loop
- Run 함수에서 루프 반복 여부를 확인하기 위한 bool타입 변수
- 정적 메소드인 WinProc()에서 사용해야할 변수이므로 똑같이 정적 변수로 선언한다.
- 정적 변수의 초기화는 클래스 바깥에서 해야 한다.(cpp파일의 앞부분)
<메소드 목록>
- Init()
- 인자로 HINSTANCE를 받는다.
- 초기화에 성공했으면 true, 실패했으면 false를 반환해야 한다.
- 클래스가 생성되고 나면 생성자를 통해 모든 초기화 과정을 완료하지 않고, 별도의 초기화 메소드인 Init() 메소드를 이용해 초기화 과정을 완료한다.
- 이 메소드 안에서 Register()과 Create() 메소드를 호출해 윈도우 구조체를 등록하고 창을 생성해 준다.
- Run()
- 게임이 종료되면 wWinMain 함수에 int값을 반환해야 한다.
- 초기화가 완료되면 본격적으로 무한루프를 통해 게임이 작동될 메소드이다.
- Register()
- 윈도우 클래스 구조체를 만들어주고 등록한다.
- 지난번 기본 코드에서
ATOM MyRegisterClass(HINSTANCE hInstance) 함수가 하던 작업을 담당한다.
- 기본 코드에서 긁어와서 적당히 변형하면 된다.
- 언급이 없는 변수들은 기본값으로 냅둔다.
- 메뉴는 사용하지 않는다.
- 창의 이름은 "GameFramework" 로 해 준다.
- 아이콘은 당장 만들수 없다면 Visual Studio에서 기본으로 제공하는 아이콘을 사용해 주자.
- 구조체 값 변경이 완료되면 마지막으로 이 값을 등록해주는 함수를 호출하자.
이러면 아이콘 파일과 resource.h 헤더가 생성이 된다.
이 헤더를 보면 방금 생성한 icon 값이 define되어 있는 것을 확인할 수 있다.
resource 헤더를 포함시킨 후 이 값을 이용하여 아이콘을 등록해 주면 된다.
- Create()
- 윈도우 창을 생성하고 보여준다.
- 지난번 기본 코드에서
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 함수가 하던 작업을 담당한다.
- 이 함수의 2번째 인자는 필요 없다.(게임에서는 창을 항상 띄워줄 것이므로)
마찬가지로 기본 코드에서 긁어와서 적당히 변형해준다. - 클래스 이름, 창 제목 모두 "GameFramework"로 설정해 준다.
- 창은 overrappedwindow 형식을 사용한다.
- 창은 모니터 왼쪽 위로부터 100, 50 위치에 생성한다.
- 창 크기는 1280, 720으로 해준다.
- 이 함수의 2번째 인자는 필요 없다.(게임에서는 창을 항상 띄워줄 것이므로)
- WinProc()
- 클래스 외부에서는 사용할 일이 없다.
- 메시지를 처리해줄 메소드.
- Register() 메소드에서 구조체를 초기화할 때,
함수 포인터형으로 전달받고 있는데, 함수 포인터 형식으로 사용하기 위해서는 정적 메소드로 선언해주어야 한다. - 내부 로직은 1번 글에서 긁어오면 된다. 나중에 추가적으로 살펴볼 예정.
//main.cpp
APIENTRY wWinMain()
- APIENTRY wWinMain() 함수가 동작할 위치이다.
- main.cpp에서는 단순히 win32api를 초기화하고 창을 띄우는 코드만 작성한다.
- 이후의 모든 과정은 CGameManager에서 처리한다.
- CGameManager 클래스를 생성하고, Init() 함수에 hInstance를 인자로 전달하여 창 초기화 과정을 시작한다.
- 초기화에 실패하면 CGameManager의 메모리 할당을 해제하고, wWinMain함수에 0을 반환한다(프로그램을 종료한다)
- 초기화에 성공했다면, int타입 ReturnValue 변수에서 CGameManager::Run() 함수를 호출하여 게임을 실행시킨다.
- 게임이 종료되면 CGameManager의 메모리 할당을 해제한다.
- 마지막으로 모든 과정이 종료되면 wWinMain 함수에 ReturnValue를 리턴한다.
[참고용 코드]
'WIN32API FrameWork > 한단계씩 직접 구현' 카테고리의 다른 글
05. PeekMessage 함수와 Run() 루프 (0) | 2022.05.15 |
---|---|
04. crtdbg 헤더를 통한 메모리 누수 잡기 (0) | 2022.05.15 |
03. 창이 생성될때의 사이즈 설정하기 (0) | 2022.05.15 |
*** 공부 방법 *** (0) | 2022.05.15 |
01. 프레임워크에 사용될 WINAPI32 기본 생성 코드 알아보기 (0) | 2022.05.15 |