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();
}
}