2010-01-29 21 views
13

Estoy trabajando en un juego de C++ DirectX 2D y necesito la entrada de teclado y mouse.
Wikipedia dice:¿Debo utilizar DirectInput o el bucle de mensajes de Windows?

Microsoft recomienda que las nuevas aplicaciones hacen uso del bucle de mensajes de Windows para el teclado y el ratón de entrada en lugar de DirectInput

Entonces, ¿cómo debo usarlo?
Tengo una clase GameScreen que se encarga del dibujo y la actualización (lógica del juego), llamo los métodos Draw y Update dentro de un bucle de mensajes de Windows.

Gracias

Respuesta

14

Ya que tiene que ejecutar una bomba de mensajes para tener una ventana, también puede usar esa bomba para manejar la entrada del teclado y el mouse también. Depende totalmente de su bomba si entrega los eventos del teclado en una ventana secundaria, puede manejarlos en la bomba si lo prefiere.

Su bomba mensaje típico es el siguiente:

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 
} 

Para un juego, la bomba puede tener un aspecto de la misma familia

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

Por supuesto, la bomba real probablemente será aún más complejo que eso, posiblemente con un MsgWaitForMultipleObjects para que pueda despertarse periódicamente incluso si no hay mensajes para procesar, pero de inmediato cuando hay mensajes.

+4

Me gustaría saber por qué no debería usar DirectInput. Gracias – Adir

+1

Respondido por Alex en http://stackoverflow.com/questions/2165230/should-i-use-directinput-or-windows-message-loop/2168067#2168067 – bobobobo

1

Si el juego tiene una sola ventana, que por lo que yo puedo decir la distinción es puramente una cuestión de gusto. Sin embargo, si tiene (o está planeando tener, o no puede descartar positivamente, la opción de tener en el futuro) varias ventanas, entonces los mensajes de Windows pueden volverse tediosos.

El problema es que, por defecto, los mensajes del teclado/mouse se enrutan solo a la ventana actualmente enfocada, y normalmente en los juegos se quiere cambiar el foco (a una vista de puntaje alto, enemigos en la vista de radar o lo que sea) y aún mantener la interactividad. La solución fácil sería que cada módulo que requiera la entrada de teclado/mouse lo busque directamente y no confíe en el reenvío de mensajes, por lo tanto, DirectInput.

No puedo decir mucho sobre su situación específica, por supuesto, solo mi 2c.

+1

No es cierto que los eventos de teclado y mouse vayan a la ventana de enfoque. Los eventos de teclado se envían a la ventana de foco _por su mensaje pump_ (eso es lo que hace DispatchMessage). Los eventos del mouse van a la ventana debajo del cursor. –

+0

Derecha. ¡Gracias! Originalmente comencé solo con el teclado y luego lo "fijé" en el teclado/mouse ... –

-1

XInput es definitivamente el camino a seguir. La entrada de baja latencia es crucial para el juego y XInput (reemplazo de DirectInput en los nuevos DirectXSDK) está diseñado exactamente para estos casos de uso.

Además, tiene soporte para gamecontrollers, joysticks, etc. de fábrica.

+1

DirectInput no tiene una latencia menor para los eventos de teclado y mouse. Pero sí le da un modelo de entrada más consistente si más adelante quiere apoyar joysticks, etc. –

+0

Tiene toda la razón, pero lo que quise decir es que DirectInput (y XInput, que es el sucesor de DInputs) tiene una latencia menor que los mensajes de Windows. – DarthCoder

+1

Pero no para la entrada de teclado y mouse.DirectInput es solo una envoltura alrededor de la API de Win32 para teclado y mouse. –

1

Sí, la publicación de MSDN es correcta. Con los mensajes de Windows puede usar la compatibilidad multilenguaje (para cualquier tipo de teclado que el usuario pueda estar usando)/configuración personal del usuario (botón derecho del mouse en vez de a la izquierda), etc. que debe descartar para usar DirectInput/XInput . Solo usa esos 2 para el soporte de gamepad/joystick. Por lo demás, simplemente use los mensajes de Windows.

Para los detalles estoy de acuerdo con la respuesta de John Knoeller.

4

DirectInput ha quedado obsoleto por buenas razones.Tan pronto como sé, crea un hilo adicional y solo consulta la interfaz de Windows Raw Input. Para un mejor rendimiento, usaría Raw Input directamente.

Si el rendimiento no es un problema para usted (y supongo que ese es el caso de un juego 2D en el hardware actual), siga los consejos de Microsoft y use los mensajes de la ventana, como lo describe John Knoeller.

+0

Puede por favor justificar "solo consultas de Windows 'Entrada sin formato interfaz "poco más (quizás con una referencia)? – bobobobo

3

FYI: Re respuesta de Juan Knoeller ... una bomba mensaje simplista es así:

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

La prueba WM_QUIT que incluyó nunca puede ser cierto porque GetMessage devuelve cero cuando se recibe una WM_QUIT. Sin embargo, la prueba de WM_QUIT en un bucle PeekMessage es necesaria porque PeekMessage devuelve verdadero/falso, ya sea que se devuelva o no un mensaje. Desde GetMessage bloquea hasta que se devuelve un mensaje, por lo que puede tener un valor de retorno diferente.

0

Utilice el uso de sólo DirectInput bajo circunstancias especiales

Lo bueno del bucle de mensajes de Windows se utiliza con GetMessage es que utiliza 0% uso de la CPU. Si está haciendo cosas que no requieren mucho procesamiento, como esperar una clave del usuario, recopilar datos del usuario, como en una base de datos o un programa de impuestos, o incluso un procesador de textos, tiene sentido usar el mensaje de Windows con getmessage. La fecha de todos los programas anteriores es el proceso cuando el usuario presiona una tecla.

Todo lo que necesita el ciclo de mensajes de Windows para procesar claves es que se cambie ese programa. El mouse ni siquiera necesita estar en la ventana.

especiales circunstancias de usar DirectInput

Si necesita: 1) Saber cuando se presiona y suelta una tecla. También es posible que no desee que se repitan las teclas detectadas como pulsaciones de teclas.
2) Claves de proceso en el fondo cuando se cambia otro programa.

Si cualquiera de las anteriores es verdadera, entonces use la entrada directa.

Si solo está recopilando datos del usuario, deberá usar el comando sleep para suspender la ejecución del programa. Desea que el programa tenga un uso de CPU del 0% en el administrador de tareas si el programa está allí esperando las claves del usuario.

Utilice la función de reposo para poner el programa en reposo hasta que desee sondear la entrada directa de las teclas.

Por lo tanto, la entrada directa solo desperdicia tiempo de programación si usted está haciendo una tarea simple y común de recopilar claves del usuario como puede ver.

Cuestiones relacionadas