2010-01-29 10 views
13

Sto lavorando a un gioco C++ DirectX 2D e ho bisogno di input da tastiera e mouse.
Wikipedia dice:Devo usare DirectInput o il loop dei messaggi di Windows?

Microsoft consiglia le applicazioni di uso del ciclo di messaggi di Windows per la tastiera e il mouse di ingresso, invece di DirectInput

Allora, come devo usarlo?
Ho una classe GameScreen che si occupa del disegno e dell'aggiornamento (logica del gioco), chiamo i metodi Draw e Update all'interno di un loop di messaggi di Windows.

Grazie

risposta

14

Poiché è necessario eseguire un messaggio pump per avere una finestra, si potrebbe anche usare quella pompa per gestire anche l'input della tastiera e del mouse. Dipende interamente dalla tua pompa, se porti gli eventi della tastiera su una finestra secondaria, puoi gestirli nella pompa, se preferisci.

tuo pompa tipico messaggio simile a questo:

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 
} 

Per un gioco, la pompa potrebbe apparire più simile a questo

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. 
     // 
    } 
} 

Naturalmente, la pompa effettiva sarà probabilmente ancora più complessa di quello, possibilmente con un MsgWaitForMultipleObjects così che tu possa svegliarti periodicamente anche se non ci sono messaggi da elaborare, ma immediatamente quando ci sono messaggi.

+4

Mi piacerebbe sapere perché non dovrei usare DirectInput. Grazie – Adir

+1

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

1

Se il gioco ha una sola finestra, che per quanto posso dire la distinzione è puramente una questione di gusto. Se, tuttavia, si ha (o si prevede di avere o non si può escludere in modo positivo l'opzione di avere in futuro) più finestre, la messaggistica di Windows può diventare faticosa.

Il problema è che per impostazione predefinita i messaggi di tastiera/mouse sono indirizzati solo alla finestra correntemente a fuoco, e in genere nei giochi si vuole essere in grado di passare messa a fuoco (per una visione hi-score, i nemici in mostra radar o qualsiasi altra cosa) e mantenere ancora l'interattività. La soluzione facile sarebbe per ogni modulo che richiede l'input da tastiera/mouse per interrogarlo direttamente, e non fare affidamento sull'inoltro dei messaggi - quindi, DirectInput.

Non posso dire molto sul tuo scenario specifico, ovviamente - solo il mio 2c.

+1

Non è vero che gli eventi di tastiera e mouse si spostano nella finestra di messa a fuoco. Gli eventi della tastiera vengono inviati alla finestra di messa a fuoco _del tuo messaggio pump_ (è ciò che fa DispatchMessage). Gli eventi del mouse si spostano nella finestra sotto il cursore. –

+0

Giusto. Grazie! Inizialmente avevo commentato solo con la tastiera e solo dopo averlo "corretto" su tastiera/mouse .. –

-1

XInput è definitivamente la strada da percorrere. L'input a bassa latenza è fondamentale per il gioco e XInput (la sostituzione di DirectInput nei nuovi DirectXSDK) è progettata proprio per questi casi d'uso.

Inoltre, è disponibile il supporto per gamecontroller, joystick, ecc.

+1

DirectInput non è una latenza inferiore per eventi di tastiera e mouse. Ma ti dà un modello di input più coerente se in seguito vuoi supportare i joystick, ecc. –

+0

Hai assolutamente ragione, ma quello che intendevo era che DirectInput (e XInput, che è il successore DInput) ha una latenza inferiore rispetto ai messaggi di Windows. – DarthCoder

+1

Ma non per l'input da tastiera e mouse.DirectInput è solo un wrapper attorno all'API Win32 per tastiera e mouse. –

1

Sì, il post MSDN è corretto. Usando i messaggi di Windows puoi usare il supporto multilingua (per qualsiasi tipo di tastiera che l'utente può usare)/le impostazioni personali dell'utente (tasto destro del mouse invece di sinistra), ecc. Che devi scartare per usare DirectInput/XInput . Utilizzare solo quelli 2 per il supporto gamepad/joystick. Per il resto basta usare i messaggi di Windows.

Per i dettagli sono d'accordo con la risposta di John Knoeller.

4

DirectInput è stato dichiarato obsoleto per validi motivi.Per quanto ne so, crea un thread aggiuntivo e interroga solo l'interfaccia di Windows Raw Input. Per le migliori prestazioni, utilizzerei Raw Input direttamente.

Se le prestazioni non rappresentano un problema per te (e suppongo che sia il caso di un gioco 2D sull'hardware corrente), segui i consigli di Microsoft e utilizza i messaggi della finestra, come descritto da John Knoeller.

+0

Puoi per favore sostenere "solo query" Raw Input di Windows interfaccia "un po 'oltre (magari con un riferimento)? – bobobobo

3

FYI: Re risposta di John Knoeller ... una pompa messaggio semplicistico assomiglia a questo:

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

Il test WM_QUIT che ha incluso non può mai essere vero, perché GetMessage restituisce zero quando si riceve un WM_QUIT. Tuttavia, il test per WM_QUIT in un ciclo PeekMessage è richiesto perché PeekMessage restituisce true/false se un messaggio è stato restituito o meno. Poiché GetMessage blocca fino a quando non viene restituito un messaggio, può avere un valore di ritorno diverso.

0

Utilizzare la sola utilizzare DirectInput in circostanze particolari

La cosa bella il ciclo di messaggi di Windows utilizzato con GetMessage è che utilizza 0% l'utilizzo della CPU. Se si stanno facendo cose non intensive come l'attesa di una chiave da parte dell'utente, la raccolta di dati da parte dell'utente come in un database o un programma fiscale, o anche un word processor, ha senso solo usare il messaggio di Windows con getmessage. La data di tutti i programmi precedenti è la procedura in cui l'utente preme un tasto.

Tutto ciò per cui il loop di messaggi di Windows deve elaborare le chiavi è per il programma da passare. Il mouse non ha nemmeno bisogno di essere nella finestra.

speciale circostanze usare DirectInput

Se è necessario: 1) Sapere quando si preme un tasto e rilasciato. Potresti anche non voler ripetere i tasti rilevati come pressioni dei tasti.
2) Elabora i tasti in background quando si passa a un altro programma.

Se una delle condizioni precedenti è vera, utilizzare directinput.

Se si raccolgono dati dall'utente, è necessario utilizzare il comando di sospensione per sospendere l'esecuzione del programma. Si desidera che il programma abbia un utilizzo della cpu pari a 0% nel task manager se il programma è appena seduto in attesa di chiavi dall'utente.

Utilizzare la funzione di sospensione per mettere il programma in pausa fino a quando non si desidera eseguire il polling dell'input diretto per i tasti.

Pertanto, l'input diretto spreca tempo di programmazione se si sta eseguendo un semplice compito ordinario di raccolta chiavi dall'utente, come si può vedere.