Bu Application.Run
çağrı, Windows mesaj pompanızı yönlendirir; bu, sonuçta Form
sınıfa (ve diğerlerine) bağlayabileceğiniz tüm olaylara güç sağlayan şeydir . Bu ekosistemde bir oyun döngüsü oluşturmak için, uygulamanın mesaj pompasının ne zaman boş olduğunu ve boş kalırken, prototipik oyun döngüsünün tipik "işlem giriş durumunu, oyun mantığını güncelle, sahneyi oluştur" adımlarını dinlemek istersiniz. .
Application.Idle
Olay yangınları her zaman bir kez uygulamanın ileti sırası boşaltılır ve uygulama boş durumuna geçiyor. Olayı ana formunuzun yapıcısına bağlayabilirsiniz:
class MainForm : Form {
public MainForm () {
Application.Idle += HandleApplicationIdle;
}
void HandleApplicationIdle (object sender, EventArgs e) {
//TODO: Implement me.
}
}
Daha sonra, uygulamanın hala boşta olup olmadığını belirleyebilmeniz gerekir . Idle
Uygulama sırasında olay sadece bir kez patlar hale boşta. Bir mesaj sıraya girinceye kadar tekrar kovulmaz ve sıra tekrar boşaltılır. Windows Forms, mesaj kuyruğunun durumunu sorgulamak için bir yöntem göstermez, ancak sorguyu bu soruyu yanıtlayabilecek yerel bir Win32 işlevine devretmek için platform başlatma hizmetlerini kullanabilirsiniz . İçin ithalat beyanı ve destekleyici türleri şöyle görünür: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
temel olarak sıradaki bir sonraki mesaja bakmanıza izin verir; eğer varsa, doğru, aksi takdirde yanlış olur. Bu problemin amaçları için, parametrelerden hiçbiri özellikle ilgili değildir: sadece önemli olan geri dönüş değeridir. Bu, uygulamanın hala boşta olup olmadığını söyleyen bir işlev yazmanıza olanak tanır (yani, sırada hala mesaj yok):
bool IsApplicationIdle () {
NativeMessage result;
return PeekMessage(out result, IntPtr.Zero, (uint)0, (uint)0, (uint)0) == 0;
}
Artık oyun döngüsünün tamamını yazmak için gereken her şeye sahipsin:
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);
}
Dahası, bu yaklaşım , aşağıdaki gibi görünen kanonik yerel Windows oyun döngüsüne mümkün olduğunca yakındır (P / Invoke'a en az güvenerek) :
while (!done) {
if (PeekMessage(&message, window, 0, 0, PM_REMOVE)){
TranslateMessage(&message);
DispatchMessage(&message);
}
else {
Update();
Render();
}
}