이 Application.Run
호출은 Windows 메시지 펌프를 구동합니다. 이는 궁극적으로 Form
수업에 참여할 수있는 모든 이벤트를 강화합니다 . 이 생태계에서 게임 루프를 만들려면 응용 프로그램의 메시지 펌프가 비어있을 때를 듣고, 비어있는 동안 일반적인 "프로세스 입력 상태, 게임 논리 업데이트, 장면 렌더링"단계를 수행하여 프로토 타입 게임 루프를 수행하십시오. .
Application.Idle
이벤트가 발생 때마다 한 번 응용 프로그램의 메시지 큐가 비워 및 응용 프로그램이 유휴 상태로 전환된다. 기본 폼의 생성자에서 이벤트를 연결할 수 있습니다.
class MainForm : Form {
public MainForm () {
Application.Idle += HandleApplicationIdle;
}
void HandleApplicationIdle (object sender, EventArgs e) {
//TODO: Implement me.
}
}
다음으로 응용 프로그램이 여전히 유휴 상태 인지 확인할 수 있어야합니다 . Idle
응용 프로그램이 때 이벤트는 한 번 발사 됩니다 유휴. 메시지가 대기열에 들어간 후 대기열이 다시 비워 질 때까지 다시 시작되지 않습니다. Windows Forms는 메시지 큐의 상태를 쿼리하는 메서드를 제공하지 않지만 플랫폼 호출 서비스 를 사용 하여 해당 질문에 응답 할 수있는 네이티브 Win32 함수에 쿼리를 위임 할 수 있습니다 . 에 대한 가져 오기 선언 PeekMessage
및 지원 유형은 다음과 같습니다.
[StructLayout(LayoutKind.Sequential)]
public struct NativeMessage
{
public IntPtr Handle;
public uint Message;
public IntPtr WParameter;
public IntPtr LParameter;
public uint Time;
public Point Location;
}
[DllImport("user32.dll")]
public static extern int PeekMessage(out NativeMessage message, IntPtr window, uint filterMin, uint filterMax, uint remove);
PeekMessage
기본적으로 대기열에서 다음 메시지를 볼 수 있습니다. 존재하면 true를, 그렇지 않으면 false를 반환합니다. 이 문제의 목적을 위해 특별히 관련된 매개 변수는 없습니다. 중요한 반환 값일뿐입니다. 이를 통해 애플리케이션이 여전히 유휴 상태인지 (즉, 큐에 메시지가 없는지) 알려주는 함수를 작성할 수 있습니다.
bool IsApplicationIdle () {
NativeMessage result;
return PeekMessage(out result, IntPtr.Zero, (uint)0, (uint)0, (uint)0) == 0;
}
이제 완전한 게임 루프를 작성하는 데 필요한 모든 것이 있습니다.
class MainForm : Form {
public MainForm () {
Application.Idle += HandleApplicationIdle;
}
void HandleApplicationIdle (object sender, EventArgs e) {
while(IsApplicationIdle()) {
Update();
Render();
}
}
void Update () {
// ...
}
void Render () {
// ...
}
[StructLayout(LayoutKind.Sequential)]
public struct NativeMessage
{
public IntPtr Handle;
public uint Message;
public IntPtr WParameter;
public IntPtr LParameter;
public uint Time;
public Point Location;
}
[DllImport("user32.dll")]
public static extern int PeekMessage(out NativeMessage message, IntPtr window, uint filterMin, uint filterMax, uint remove);
}
또한이 접근 방식은 표준 네이티브 Windows 게임 루프 와 최대한 비슷하게 (P / Invoke에 의존 함) 다음과 같습니다.
while (!done) {
if (PeekMessage(&message, window, 0, 0, PM_REMOVE)){
TranslateMessage(&message);
DispatchMessage(&message);
}
else {
Update();
Render();
}
}