Sondeo vs entrada impulsada por evento

19

Estoy desarrollando un juego usando encuestas para el método de entrada. Sin embargo, ahora que estoy profundizando en los menús del juego y otros componentes de la interfaz de usuario, descubro que probablemente me gustaría tener una entrada impulsada por eventos. Quizás incluso tener ambos, usando eventos controlados por la interfaz de usuario y sondeo para la entrada del "mundo". Tengo curiosidad por saber cuál es el mejor camino a seguir.

Estoy definiendo sondeo como: cada ciclo de actualización compruebo qué teclas se presionan, dónde está el mouse, botones presionados, luego los ejecuto y hago acciones en función de la información recopilada.

Estoy definiendo el evento impulsado como: eventos basados ​​en interrupciones, cuando ocurre un evento y se activa la interrupción y se ejecuta un bloque de código basado en el evento.

¿Crees que es mejor ir a todos los eventos, todas las encuestas, o es aceptable una combinación de ambos? Si tiene pros y contras para cualquiera, por favor enumérelos. Gracias.

EDITAR

El juego está basado en Java / OpenGL, por lo que se lanzará a Windows / Mac / Linux. La posibilidad de extender eso a los dispositivos móviles es baja. El juego es estilo RTS, tercera persona en 3D.

EDITAR 2

Todavía no estoy totalmente contento con la forma en que implementé esto, pero hacia lo que me estoy moviendo es detectar eventos en mi interfaz de usuario y, si ninguno de mis componentes de la interfaz de usuario los maneja, paso el evento al "Mundo" para recoger / seleccionar. Algo como:

@Override  
private boolean handleEvent(Event event) {  
    if(hud.handleEvent(event)) {  
        return true;  
    }  
    return WORLD.handleEvent(event);  
}

De esta manera no obtengo clics que se filtren a través de la interfaz de usuario para seleccionar objetos detrás de los botones y lo que no.

Actualmente, los controles de mi cámara todavía se basan en encuestas, y eso parece estar funcionando por ahora, pero puedo actualizar eso más adelante.

Agradezco todas las respuestas, lo siento, ¡solo pude elegir una!

MichaelHouse
fuente
66
No estoy seguro en Java, pero en general siempre tiene que sondear la entrada. Luego, puede publicar eventos cuando las cosas cambian, pero esto todavía se basa en un sistema de encuestas.
James
El punto de enfoque más relevante en mi opinión es diseñar un ciclo de eventos que esté libre de cualquier otra carga que no sea la colección de entrada. Permítanme explicar: el sistema operativo hará la interrupción impulsada por la entrada y la tratará en el "hilo de entrada" global, luego este hilo del SO redirigirá los mensajes a la aplicación actualmente enfocada y escribirá la información en su cola de mensajes. PeekMessage u GetMessage debe sondear la cola de mensajes. La forma más rápida de obtener esto es usar GetMessage y dejar que el programador lo despierte, luego puede marcar el mensaje con mucha precisión.
v.oddou

Respuestas:

17

Depende de los requisitos de su juego y hardware. La mayoría de los juegos generalmente están interesados ​​en los cambios en el estado de entrada, es decir, el usuario presiona la tecla de disparo y su arma comienza a disparar, el usuario suelta la tecla de disparo y su arma deja de disparar, el usuario presiona la tecla de movimiento y comienza a moverse, suelta la tecla de movimiento y deja de moverse , etc., por lo que un sistema de entrada controlado por eventos tiene más sentido en esos casos ya que la información ya está en un formato adecuado. Además, en la plataforma Windows, ya recibe eventos por cambios en el estado del teclado y el mouse, por lo que a menudo es una conversión 1: 1 de eventos de entrada de bajo nivel a eventos de juego de alto nivel. Con el sondeo, a menudo tendrá que generar tales eventos manualmente al comparar el estado entre el cuadro actual y el último. Básicamente, "¿qué botones se presionan ahora?"

Dicho esto, en ciertas plataformas está atascado con la entrada de sondeo en un nivel bajo y no hay forma de evitar la verificación de los bordes usted mismo. Sin embargo, siempre he logrado los mejores resultados utilizando eventos para toda la lógica de alto nivel, ya que así es naturalmente como esos sistemas tienden a funcionar.

Skyler York
fuente
Gracias, he incluido información adicional sobre la plataforma y el propósito del juego.
MichaelHouse
1
Tenga en cuenta que GetAsyncKeyStatees una forma sencilla de utilizar el sondeo en Win32.
Macke
Derp, hice una pregunta en los comentarios de Nate Bross que tratas aquí, así que supongo que lo refinaré. ¿Todas las PC ofrecen esa interrupción de hardware 1: 1 a la relación de eventos del teclado del sistema operativo, y qué tipo de plataformas se limitan al sondeo de bajo nivel?
michael.bartnett
@Macke: a veces los antivirus informan programas que usan esta API porque pueden recibir pulsaciones de teclas de todo el sistema global, lo que permite el registro de teclas maliciosas. El artículo más asombroso al respecto en todo Internet (lo sé) es este: securelist.com/analysis/publications/36358/…
v.oddou
7

No veo ninguna razón por la que no puedas hacer ambas cosas y obtener lo mejor de ambos mundos.

Los eventos de entrada se generan por sondeo (en algún nivel, el controlador sondea el hardware para ver en qué estado se encuentra), y dado que su bucle principal sondea todos los dispositivos de entrada, puede implementar fácilmente el suyo. Algo simple como a continuación es lo que he usado en el pasado.

mouseInput = GetMouse();
kbInput = GetKeyboard();


// refactor this out to its own method if it makes sense
if menuState == Showing
    if mouseInput.LeftButton == State.Pressed
        LeftButton(mouseInput.X, mouseInput.Y)

// rest of game input code processing

void LeftButton(int x, int y)
{
    // left button event handler
}

Sé que definió los eventos como interrupciones y lo que he puesto aquí no está "realmente basado en eventos", pero no veo lo que no le da lo anterior que las interrupciones sí: la mayoría de los usuarios no se darán cuenta se pierde el fotograma único, a menos que el juego se ejecute a una velocidad de fotogramas muy baja.

Nate
fuente
1
Tengo curiosidad sobre la naturaleza de obtener información de los dispositivos. ¿Los eventos de teclado enviados por el sistema operativo son el resultado del sondeo en el nivel del controlador del dispositivo? ¿O un evento de teclado corresponde con una interrupción? ¿O hay interrupciones, pero el sistema operativo las protege y las despacha cuando lo considera conveniente?
michael.bartnett
No estoy seguro de cómo funciona a ese nivel, pero es más básico, algunos programas se ejecutan en un bucle y comprueban el estado del teclado y lo comparan con el estado anterior, si cambia, el cambio se dispara.
Nate
5

Aquí hay dos problemas diferentes:

  1. ¿Cómo se lee la entrada del usuario desde el sistema operativo / hardware?

  2. ¿Cómo procesas la entrada del usuario en tu motor?

Para leer, depende claramente de su plataforma y de qué tipo de entrada desea leer. Tenga en cuenta que es fácil convertir una cosa a otra en su capa de entrada. (Es decir, sondear y emitir eventos al motor, o escuchar eventos y emitir estados al motor).

Para el procesamiento, hay algunas opciones diferentes:

  • Para el control de movimiento del jugador (y esquemas similares), el sondeo puede ser más simple ya que necesita recalcular la velocidad de cada cuadro. Es muy probable que su bucle interno se base en encuestas:

    es decir, algo como speed += 1 if button.down else -1; clamp(speed, 0, 42);

  • Para eventos discretos (misil de fuego, juego de pausa, teletransporte a otro lado del planeta), el procesamiento de eventos es preferible, de lo contrario, su código estará lleno de maybeLaunchMissile(key_state);llamadas, y eso es simplemente ... malo, está bien. ;)

Espero eso ayude.

Macke
fuente