The Application.Run
panggilan drive pompa pesan Windows Anda, yang pada akhirnya kekuatan apa semua peristiwa Anda dapat menghubungkan pada Form
kelas (dan lain-lain). Untuk membuat loop game di ekosistem ini, Anda ingin mendengarkan ketika pompa pesan aplikasi kosong, dan sementara itu tetap kosong, lakukan langkah-langkah "proses input negara, perbarui logika game, render adegan" membuat langkah-langkah loop game prototypical .
The Application.Idle
peristiwa kebakaran sekali setiap kali antrian pesan aplikasi dikosongkan dan aplikasi transisi ke keadaan idle. Anda dapat mengaitkan acara di konstruktor formulir utama Anda:
class MainForm : Form {
public MainForm () {
Application.Idle += HandleApplicationIdle;
}
void HandleApplicationIdle (object sender, EventArgs e) {
//TODO: Implement me.
}
}
Selanjutnya, Anda perlu untuk dapat menentukan apakah aplikasi tersebut masih menganggur. The Idle
event hanya kebakaran sekali, saat aplikasi menjadi siaga. Itu tidak dipecat lagi sampai pesan masuk ke antrian dan kemudian antrian kosong lagi. Formulir Windows tidak memaparkan metode untuk menanyakan keadaan antrian pesan, tetapi Anda dapat menggunakan layanan permintaan platform untuk mendelegasikan kueri ke fungsi Win32 asli yang dapat menjawab pertanyaan itu . Deklarasi impor untuk PeekMessage
dan jenis pendukungnya seperti:
[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
pada dasarnya memungkinkan Anda untuk melihat pesan berikutnya dalam antrian; itu mengembalikan true jika ada, false sebaliknya. Untuk keperluan masalah ini, tidak ada parameter yang relevan: hanya nilai pengembalian yang penting. Ini memungkinkan Anda untuk menulis fungsi yang memberi tahu Anda jika aplikasi tersebut masih menganggur (artinya, masih belum ada pesan dalam antrian):
bool IsApplicationIdle () {
NativeMessage result;
return PeekMessage(out result, IntPtr.Zero, (uint)0, (uint)0, (uint)0) == 0;
}
Sekarang Anda memiliki semua yang Anda butuhkan untuk menulis lingkaran permainan lengkap Anda:
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);
}
Lebih lanjut, pendekatan ini cocok sedekat mungkin (dengan ketergantungan minimal pada P / Invoke) ke loop game Windows asli kanonik , yang terlihat seperti:
while (!done) {
if (PeekMessage(&message, window, 0, 0, PM_REMOVE)){
TranslateMessage(&message);
DispatchMessage(&message);
}
else {
Update();
Render();
}
}