기타

[C++] 게임엔진 가이드 2 App Layer.

by 쿼티만세12345 posted Jan 01, 2017
?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

크게 작게 위로 아래로 댓글로 가기 인쇄

먼저 관련 내용으로 추천 하는 책으로는 

Game Coding Complete 4th (원서)

게임 엔진 아키텍처 2th (번역서)

게임 프로그래밍 gems (번역서 절판)

등등이 있습니다.

앞으로 이야기 할 내용들은 적어도 C++ 초보딱지는 땐 사람들을 위한 내용입니다. 


App Layer 코딩 가이드.


먼저 App Layer는 OS와 게임이 서로 소통하는 부분입니다. 이부분을 나눈 이유는 앞으로 만들 게임이 게임이 플랫폼 독립적으로 돌리기 위해서 입니다.

이렇게 나누었을때의 장점은 타 OS 이식을 할때 편하게 이식할수 있습니다.

OS 마다 이벤트가 다른 방식으로 들어오고, 써야하는 코드가 다르기 때문입니다.


Win api 코드를 짜고 싶으시다면 아래 사이트에서 배워보시는것도 좋습니다. 하지만 전반적인 내용은 windows app을 만드는게 목적이니,

필요한것 몇가지만 배우시면 됩니다. (윈도우를 띄우는 법이라던지 등등)

http://www.winprog.org/tutorial/ 


다른 라이브러리를 쓰고 싶으시다면 SDL이나 SFML, GLFW, FreeGLUT 등등의 다양한 라이브러리가 있습니다.

(제 경우는 지금은 SDL 2를 쓰고 있습니다. 자세한 버젼은 모르겠지만 16년도 6월 쯔음에 최신 릴리즈된 버젼으로 했습니다. )


그럼 전반적인 설명을 시작하겠습니다.


먼저 main 함수는 다들 아실 것입니다. 바로 OS에서 보고 프로그램을 시작하는 함수입니다.

(다른 말로 엔트리 포인트라고 부릅니다.)


C/C++에서 코드를 짤때 기본적으로 

int main(void)

{

return 0;

}


의 형식으로 메인 함수를 만들었습니다. 맥에서 저걸 컴파일 하고 실행 하면 터미널에서 돌아가고,

윈도우에서는 CMD 창에서 볼수 있었죠. 


하지만 CMD 창이 아닌 다른 프로그램들 처럼 창을 띄우고 거기서 그래픽을 돌리려면 어떻게 해야할까요?

윈도우의 경우는 Win32Api를 통해 프로그램을 만듭니다. (물론 유니버셜 앱으로도 만들수 있습니다.) 그러기 위해서 winmain이라는 기본과는 다른 main함수를 쓰죠.

이 함수들은 윈도우의 경우에만 쓸수 있는 함수입니다. (위 라이브러리들은 이걸 여러 OS에 맞게 만들어주는 역할을 합니다.)

그럼 이제 새로 윈도우 프로그램을 위해 main함수를 만들어 봅시다. 


main.cpp에 아래 함수를 추가해 주세요.


#include <windows.h> //Winmain 

int WINAPI WinMain(HINSTANCE instance, HINSTANCE /*prev*/, LPSTR /*commandLine*/, int /*show*/) 

{

return 0; 

}


후방 호환성 때문에 코멘트 처리한 3개 파라미터들이 있지만 상콤하게 무시해 주시면 됩니다.

우리가 필요한건 instance하나 거든요.

대충 설명하자면,


HINSTANCE instance - 실행중인 응용 프로그램의 인스턴스에 대한 핸들입니다. Windows는 리소스에 대한 포인터를 제공하지 않고 대신 handle이라는 고유 ID를 제공합니다. 앞으로 우리가 더 많은 윈도우 리소스를 생성함에 따라 더 많은 핸들을 볼 수 있습니다.


HINSTANCE prev -이 매개 변수는 Windows에서 더 이상 사용되지 않지만 이전에 실행중인 인스턴스 (있는 경우)의 ID였습니다. 이건 필요가 없습니다.


LPSTR commandLine - 이것은 문자열에 대한 긴 포인터의 약자입니다. C 스타일 문자열을 말하는 것은 Windows / Hungarian Notation입니다. 이것은 명령 줄 인수를 프로그램에 전달하는 WinMain 방법 일뿐입니다. 우리가 만들 게임에서는 필요하지 않지만 사용하고자한다면 할 수 있습니다. 문자열 배열 대신 단일 문자열이므로 직접 구문 분석해야합니다.


int show - 날씨를 선언하는 C 스타일의 bool 값으로, 윈도우가 보이는지 아닌지로 시작해야합니다. 이번경우에선 보이게 시작할거기 때문에 이것도 무시할 것입니다.


사실 이것들의 대부분은 별로 신경 쓰지 않으셔도 됩니다. 우리한테 필요한건 instance 하나 뿐이기 때문입니다.  다음은 우리가 만들고있는 App Layer 클래스에 instance를 전달해야합니다. 


뭐 커맨드 라인 인수와 show 쓸 수도 있습니다만;; 솔직히 커맨드 라인에서 게임을 실행하는 대신에 게임 아이콘을 더블 클릭해서 실행하는경우가 많기 때문에 무시하는 겁니다.


WinMain 함수 앞에 붙어있는 WINAPI 라는 매크로가 이상해 보일수 있지만 이건 컴파일러에 함수에대한 어셈블리 정보를 주는(저도 자세히는 모르지만;;) 역할을 합니다. 너무 신경쓰시지 마시고 그냥 놔두면 됩니다.


main 함수를 만들었으면 다음 단계로 갑시다.

이제 window 메세지를 처리하는 함수를 만들 차례입니다. 보통 이걸 Window Procedure Function 또는 WinProc 등등으로 부릅니다. 이 함수는 switch 를 통해 우리가 컨트롤 해야하는 모든 메세지를 처리합니다. (if else 로 할수도 있지만, 가독성에서 switch를 쓰는경우라 보시면 됩니다.)

나중에 app class를 만들고 나면 private에 두시면 되고, 지금은 간단히 global 함수로 둡시다.


LRESULT CALLBACK WinProc(HWND win, UINT msg, WPARAM wp, LPARAM lp) 

switch (msg) 

default: 

return DefWindowProc(win, msg, wp, lp); 

return 0; 

}


SDL 이나 SFML같은 다른 라이브러리 역시도 이런 콜백 프로시저 함수를 만드시면 됩니다. 

작동 방식이나 생긴 모습은 비슷하니, 튜토리얼이나 위키 사이트에서 보시면 아실수 있습니다.


함수의 리턴 값이 LRESULT 인데 이건 우리가 현재 핸들링 하는 메세지에 달려있습니다. 

보시다 싶이, 기본값(우리가 원하지 않는 다른 윈도우 메세지들)으로 리턴값으로 DefWindowProc 함수를 씁니다.


다른 경우에는 0을 리턴하는데 이건 메세지를 핸들하는데 성공 했다는 뜻입니다. (프로그램이 메인함수에서 return 0; 을 하는이유가

0이 끝마치는데 성공했다는 의미를 가지고 있습니다. 파워쉘, 배치, 배쉬 같은걸로 에러메세지를 잡을때도 리턴값을 확인하는 겁니다.)


CALLBACK 역시 WINAPI랑 비슷한겁니다. 컴파일러가 알아서 해주는거니 넘어갑시다 ㅎㅎ;;


HWND win - 메시지를받은 현재 창에 대한 핸들입니다.

UINT msg - 현재 메시지의 ID입니다.

WPARAM wp - 메시지 정보. 특정한 메세지에 쓰입니다..

LPARAM lp - 메시지 정보. wp랑 비슷합니다.


HWND는 다음 글에서 설명 하겠습니다. 이건 윈도우에 대한 변수로 사용되며, 우리가 윈도우를 가지고 무엇인가를 하고 싶을 때마다 HWND가 필요합니다. 대부분의 윈도우 함수는 첫 번째 파라미터로 HWND를 사용하므로 윈도우즈에서 조절? 조종?할 창을 알 수 있습니다.


WPARAM 및 LPARAM은 메시지 정보입니다. 특정 메시지는 WPARAM 만 사용하며, 특정 메시지는 LPARAM 만 사용합니다. 요것들은 비트로 묶인 데이터가있는 "Anything"  같은 역할을합니다. 


예를 들자면 마우스 클릭 메시지에서 x와 y 좌표는 모두 LPARAM에 저장됩니다. 그러나 키보드 처리를위한 메시지에서 WPARAM에는 실제로 어떤 키가 눌렸는지에 대한 정보가 포함되어 있습니다. 이거도 담에 자세히 설명하겠습니다. 어려워 보일 수도 있지만 헬퍼 함수들이 제공되서 쓰는게 어렵지는 않습니다.

물론 궁금하시면 MSDN에서 보시면됩니다.


다음은 메세지 펌프입니다.


MSG message; 

while (PeekMessage(&message, m_data.window, 0, 0, PM_REMOVE)) 

TranslateMessage(&message); 

DispatchMessage(&message); 

}


대충 이런식으로 생겼습니다. 이건 픽 메세지 함수 인데, 보통의 윈도우 앱과는 다른 형태의 메세지 펌프입니다.

그 이유는 보통의 앱들은 유저의 입력을 바탕으로 돌아가면 되지만, 게임은 유저의 입력과는 상관 없이 돌아야 하기 때문입니다.

보통프로그램의 경우는 겟 메세지 함수를 주로 씁니다.


이번거는 여기서 마치겠습니다;; 

다음엔 APP class랑 윈도우 구현의 나머지를 쓸 예정인데 언제 돌아올지는 장담 못하겠습니다;;