본문 바로가기

개발 프로젝트/Win32 - VampireSurvivor 모작

로그라이크 게임 구현 - 1주차 (2)

이번 글에선 PeekMessage 함수를 정리하겠다.

 

해당 함수를 설명하기 이전에 우선 WinAPI가 어떤 방식으로 작동하는지 알아야할 필요가 있다.

Win32의 운영방식은 윈도우 프로토콜을 실행하면서 작동한다.

이 윈도우 프로토콜은 LRESULT형태의 값을 반환하는 함수의 형태로 작성 되어있지만, 해당 함수를 직접 호출하는 코드는 보이지 않는다.

그 이유는 윈도우 프로토콜은 콜백의 형태로 호출되기 때문이다.

 

 윈도우 프로토콜을 콜백하는 함수는 DispatchMessage라는 함수에 포함되어있다.

DispatchMessage함수는 혼자서 기능을 할 순 없다.

이 함수는 메세지를 윈도우 프로토콜에 전달하는 역할을 하기 때문에 메세지를 받고 해석하는 함수가 필요하다.

PeekMessage()함수는 메세지를 받는 함수들 중 하나이다.

이 PeekMessage함수는 메세지를 받는다는 점에선GetMessage()함수와 동일하다.

GetMessage()함수는 MS에서 기본적으로 사용하도록 권장하는 메세지를 받는 함수이다.

그럼에도 PeekMessage를 사용하는 이유는 PeekMessage가 갖는 차별성 때문이다.

 

GetMessage 예제
    while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)       //GetMessage 예제
    { 
        if (bRet == -1)
        {
            // handle the error and possibly exit
        }
        else
        {
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
        }
    } 
 
    // Return the exit code to the system. 
 
    return msg.wParam; 
}

 

PeekMessage 예제

bool peekbool = false;

while (!peekbool) // PeekMessage 예제
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
            {
                peekbool = true;
            }
            else
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }

        if (dwTime + 32 < GetTickCount64() && bGameProgress)
        {
            dwTime = GetTickCount64();
             GameProcess();
        }

    }

 

 두 함수의 차이점을 먼저 설명하면,

GetMessage 함수는 메세지를 받을 동안 아무 행동을 하지 못한다.

그러나 PeekMessage함수는 메세지를 받으며 다른 명령을 처리할 수 있다.

즉 PeekMessage는 스레드와 비슷한 역할을 한다.

 

만약 게임을 구현하는데 GetMessage함수를 사용한다고 가정해보자.

그렇다면 캐릭터가 움직이지 않으면, 그외 다른 모든것들은 멈출 것이다.

왜냐하면 GetMessage()함수는 메세지를 받을 때 까지 무한정 대기하기 때문이다.

 

게임은 플레이어가 움직이지 않아도 (메세지를 받지 않아도) 상호작용 하고 있어야한다.

때문에 메세지를 받지 않아도, 다른 작업들을 처리 해줄수 있는 PeekMessage() 함수를 사용해야한다.

 

PeekMessage함수는 WM_QUIT 메세지를 받기 전 까지 무한정 반복한다.

이 함수는 윈도우 메세지를 받고 메세지 큐에 저장한다.

그리고 메세지 큐에 메세지가 존재한다면 큐에서 꺼내어 처리한다.

만약 메세지 큐에 메세지가 존재하지 않는다면, PeekMessage함수는 false를 리턴한다.

즉 메세지를 받지 않아도, 다음 구문을 실행시킨다.