WinAPI에서
// 함수: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 용도: 주 창의 메시지를 처리합니다.
//
// WM_COMMAND - 애플리케이션 메뉴를 처리합니다.
// WM_PAINT - 주 창을 그립니다.
// WM_DESTROY - 종료 메시지를 게시하고 반환합니다.
WndProc을 통해 메시지를 처리한다.
여기서 SetTimer함수를 통해 특정함수를 일정 주기마다 호출하는 방법을 사용할 수 있다.
이 함수를 통해 유니티의 FixedUpdate()와 비슷하게 일정 시간 마다 호출하는 부분을 구현해보려고한다.
SetTimer(hwnd, // handle to main window
IDT_TIMER1, // timer identifier
10000, // 10-second interval
(TIMERPROC) NULL); // no timer callback
첫번째 인자는 window의 handle이다.
두번째 인자는 해당 타이머의 이름
세번째 인자는 1ms단위로 10000ms는 10초다.
네번째 인자는 콜백함수이다.
null값을 설정하면 WndProc함수의 case WM_TIMER:에 전달 되고,
특정함수를 설정하면 해당 함수에서 WM_TIMER을 처리한다.
식별자가 있어 여러개의 타이머를 동시에 세팅할 수 있다.
SetTimer(hwnd, 1, 10, NULL);
SetTimer(hwnd, 2, 100 ,NULL);
이렇게 1번 2번 타이머를 세팅해줬다면
case WM_TIMER:
switch (wParam)
{
case 1: //1번 타이머의 메시지
MessageBox(hwnd, L"1실행", L"1번타이머", NULL);
break;
case 2: //2번 타이머의 메시지
MessageBox(hwnd, L"2실행", L"2번타이머", NULL);
break;
}
break;
이런식으로 wParam의 값을 통해 몇번 타이머인지 알아낼수 있다.
case WM_CREATE: // 프로그램이 실행 될 때 한 번 호출된다.
SetTimer(hWnd, 1, 10, NULL);
break;
위와 같이 WM_CREATE에서 식별자가 1이고, 주기가 10ms인 타이머를 호출해준다.
case WM_TIMER:
if(pMainGame)
pMainGame->Update();
break;
콜백함수가 NULL이므로 case WM_TIMER: 에서 처리해야한다.
여기서 메인게임의 Update를 호출함으로 10ms마다 주기적으로 호출해줬다.
기본적으로 wWinMain함수에는 MSG msg 이런식으로 메시지 변수를 선언한 후,
GetMessage함수를 통해 메시지를 읽어온다.
단점은 메시지큐가 비어있다면 무한 대기에 빠진다.
따라서 PeekMessage함수를 통해 block되지않고 큐 확인만 한 후,
나머지 처리 (예: update함수나 render함수) 를 해준다.
MSG msg;
// 기본 메시지 루프입니다:
while (true)
{
if(PeekMessage(&msg,nullptr,0,0,PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
if (pMainGame) {
pMainGame->Update();
pMainGame->Render();
}
}
}
이런식으로 if문을 통해 message큐 처리만 해준 후, else로 빠져나와 함수처리를 해준다.
이런 방식으로 짜면 위 SetTimer방식보다 훨씬 더 많이 CPU를 사용할 수 있다.
함수호출도 훨씬 많아진다.
단점은 컴퓨터마다 성능이 달라 프레임이 달라지므로 이전에 작성한
QPC(QueryPerformanceCounter)를 통한 deltatime 을 이용해야한다!