2010-01-29 17 views
13

Ich arbeite an einem C++ DirectX 2D Spiel und ich brauche Tastatur und Mauseingabe.
Wikipedia sagt:Sollte ich DirectInput oder Windows-Nachrichtenschleife verwenden?

Microsoft empfiehlt, dass neue Anwendungen Verwendung der Windows-Nachrichtenschleife für Tastatur- und Mauseingaben statt Direct

Wie soll ich es verwenden zu machen?
Ich habe eine GameScreen-Klasse, die sich um die Zeichnung und die Aktualisierung (Spiellogik) kümmert, ich rufe die Draw- und die Update-Methode innerhalb einer Windows-Meldungsschleife auf.

Dank

Antwort

14

Da Sie ziemlich viel eine Nachrichtenpumpe ausführen müssen, um ein Fenster zu haben, können Sie diese Pumpe auch verwenden, um Tastatur- und Mauseingabe ebenso zu behandeln. Es hängt ganz von Ihrer Pumpe ab, ob Sie Tastaturereignisse an ein Kindfenster weitergeben, Sie können sie in der Pumpe handhaben, wenn Sie es bevorzugen.

Ihre typische Meldungsverteilschleife sieht wie folgt aus:

while (GetMessage(&msg, NULL, 0, 0)) 
{ 
    if (WM_QUIT == msg.message) 
     break; 
    TranslateMessage(&msg); // post a WM_CHAR message if this is a WM_KEYDOWN 
    DispatchMessage(&msg); // this sends messages to the msg.hwnd 
} 

Für ein Spiel, Ihre Pumpe mehr aussehen könnte dieses

while (true) 
{ 
    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD)) 
    { 
     bool fHandled = false; 
     if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) 
     fHandled = MyHandleMouseEvent(&msg); 
     else if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) 
     fHandled = MyHandleKeyEvent(&msg); 
     else if (WM_QUIT == msg.message) 
     break; 

     if (! fHandled) 
     { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
     } 
    } 
    else 
    { 
     // if there are no more messages to handle right now, do some 
     // game slice processing. 
     // 
    } 
} 

Natürlich Ihre tatsächliche Pumpe wird wahrscheinlich noch komplexer sein als das, möglicherweise mit einem MsgWaitForMultipleObjects, so dass Sie regelmäßig aufwachen können, auch wenn es keine Nachrichten zu verarbeiten, aber sofort, wenn es Nachrichten gibt.

+4

Ich würde gerne wissen, warum sollte ich DirectInput nicht verwenden. Danke – Adir

+1

Antwort von Alex in http://stackoverflow.com/questions/2165230/should-i-use-directinput-or-windows-message-loop/2168067#2168067 – bobobobo

1

Wenn das Spiel ein einzelnes Fenster hat, als so weit ich die Unterscheidung rein eine Frage des Geschmacks ist zu berichten. Wenn Sie jedoch (oder planen, die Option, in der Zukunft zu haben, mehrere Fenster zu haben, oder dies nicht definitiv ausschließen können), kann Windows-Messaging ermüdend werden.

Problem ist, dass Tastatur/Maus-Nachrichten standardmäßig nur zu dem gerade fokussierten Fenster geroutet werden, und in der Regel in Spielen, in denen Sie den Fokus wechseln möchten (zu einer High-Score-Ansicht, Gegner auf Radar oder was auch immer) und immer noch Interaktivität erhalten. Die einfache Lösung wäre für jedes Modul, das eine Tastatur-/Mauseingabe benötigt, um direkt danach zu fragen, und nicht auf Nachrichtenweiterleitung angewiesen ist - daher DirectInput.

Ich kann natürlich nicht viel über Ihr spezifisches Szenario sagen - nur meine 2c.

+1

Es stimmt nicht, dass Tastatur- und Mausereignisse zum Fokusfenster gehen. Tastaturereignisse werden an das Fokusfenster gesendet _von Ihrer Nachricht pump_ (das ist was DispatchMessage tut). Mausereignisse gehen in das Fenster unter dem Cursor. –

+0

Rechts. Vielen Dank! Ich habe ursprünglich nur mit der Tastatur kommentiert und erst dann die Tastatur/Maus fixiert. –

-1

XInput ist definitiv der Weg zu gehen. Low-Latency-Input ist entscheidend für das Spiel und XInput (Ersatz von DirectInput in den neuen DirectXSDKs) ist genau für diese Anwendungsfälle ausgelegt.

Außerdem haben Sie Unterstützung für Gamecontroller, Joysticks, usw. aus der Box.

+1

DirectInput hat keine geringere Latenz für Tastatur- und Mausereignisse. Aber es gibt Ihnen ein konsistenteres Eingabemodell, wenn Sie später Joysticks usw. unterstützen wollen. –

+0

Sie haben absolut Recht, aber was ich meinte war, dass DirectInput (und XInput, das ist DInputs Nachfolger) eine niedrigere Latenz als Windows Nachrichten hat. – DarthCoder

+1

Aber nicht für Tastatur- und Mauseingabe.DirectInput ist nur ein Wrapper um die Win32-API für Tastatur und Maus. –

1

Ja, der MSDN-Beitrag ist korrekt. Unter Verwendung von Windows-Nachrichten können Sie die mehrsprachige Unterstützung (für jede Art von Tastatur, die der Benutzer verwendet)/persönliche Einstellungen des Benutzers (rechte Maustaste statt links), etc .. verwenden, die Sie wegwerfen müssen, um DirectInput/XInput zu verwenden . Verwenden Sie nur diese 2 für die Gamepad/Joystick-Unterstützung. Für den Rest benutzen Sie einfach die Windows Nachrichten.

Für die Details stimme ich der Antwort von John Knoeller zu.

4

DirectInput wurde aus guten Gründen nicht weiter unterstützt.Soweit ich weiß, erstellt es einen zusätzlichen Thread und fragt nur Windows 'Raw Input Schnittstelle ab. Um die beste Leistung zu erzielen, verwende ich Raw Input direkt.

Wenn Leistung für Sie kein Problem ist (und ich denke, das ist bei einem 2D-Spiel auf der aktuellen Hardware der Fall), folgen Sie den Anweisungen von Microsoft und verwenden Sie Fenstermeldungen, wie von John Knoeller beschrieben.

+0

Können Sie bitte begründen "fragt nur Windows 'Raw Input Schnittstelle "weiter (vielleicht mit einer Referenz)? – bobobobo

3

FYI: Re John Knoeller Antwort ... eine vereinfachte Meldungsverteilschleife sieht wie folgt aus:

while (GetMessage(&msg, NULL, 0, 0)) 
{ 
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
} 

Der WM_QUIT Test, dass er eingeschlossen nie wahr sein kann, weil GetMessage Null zurückgibt, wenn ein WM_QUIT empfangen wird. Das Testen für WM_QUIT in einer PeekMessage-Schleife ist jedoch erforderlich, da PeekMessage True/False zurückgibt, ob eine Nachricht zurückgegeben wurde oder nicht. Da GetMessage blockiert, bis eine Nachricht zurückgegeben wird, kann es einen anderen Rückgabewert haben.

0

Verwenden Sie die Nur-verwenden Direct unter besonderen Umständen

Die nette Sache über die Windows-Nachrichtenschleife mit GetMessage verwendet wird, ist, dass es verwendet 0% CPU-Auslastung. Wenn Sie unprocessorintensive Dinge tun, wie das Warten auf einen Schlüssel vom Benutzer, Sammeln von Daten vom Benutzer, wie in einer Datenbank oder einem Steuerprogramm oder sogar einem Textverarbeitungsprogramm, ist es sinnvoll, nur die Windows-Nachricht mit getmessage zu verwenden. Ich alle oben genannten Programme Datum ist der Prozess, wenn der Benutzer eine Taste drückt.

Alles, was die Windows-Meldungsschleife benötigt, um Schlüssel zu verarbeiten, ist für das Programm, zu dem gewechselt werden soll. Die Maus muss nicht einmal im Fenster sein.

Besondere Umstände bedienDirect

Wenn Sie zu: 1) wissen, wenn eine Taste gedrückt und losgelassen wird. Sie möchten vielleicht auch nicht Schlüssel wiederholen, die als Tastendruck erkannt werden.
2) Tasten im Hintergrund bearbeiten, wenn auf ein anderes Programm umgeschaltet wird.

Wenn eine der obigen Aussagen zutrifft, dann verwenden Sie directinput.

Wenn Sie nur Daten vom Benutzer sammeln, müssen Sie den Befehl sleep verwenden, um die Ausführung des Programms zu unterbrechen. Sie möchten, dass das Programm im Task-Manager eine CPU-Auslastung von 0% hat, wenn das Programm gerade dort sitzt und auf die Schlüssel des Benutzers wartet.

Verwenden Sie die Schlaffunktion, um das Programm in den Ruhezustand zu versetzen, bis Sie die direkte Eingabe für Schlüssel abfragen möchten.

Daher vergeudet direkte Eingabe nur Programmierzeit, wenn Sie eine einfache gewöhnliche Aufgabe des Sammelns von Schlüsseln vom Benutzer tun, wie Sie sehen können.