Polling vs input guidato dall'evento


19

Sto sviluppando un gioco usando il polling per il metodo di input. Tuttavia, ora che sto approfondendo i menu di gioco e altri componenti dell'interfaccia utente, sto scoprendo che probabilmente mi piacerebbe avere input guidato dagli eventi. Forse anche avendo entrambi, usando event driven per l'interfaccia utente e polling per l'input "world". Sono curioso di sapere quale sia il modo migliore per andare.

Sto definendo il polling come: ogni ciclo di aggiornamento controllo quali tasti vengono premuti, dove si trova il mouse, i pulsanti premuti, quindi li eseguo e eseguo le azioni in base alle informazioni raccolte.

Sto definendo un evento guidato come: eventi basati su interrupt, quando si verifica un evento e viene attivato un interrupt e viene eseguito un blocco di codice basato sull'evento.

Pensi che sia meglio andare su tutti gli eventi, tutti i sondaggi o una combinazione di entrambi è accettabile? Se hai vantaggi e svantaggi per entrambi, ti preghiamo di elencarli. Grazie.

MODIFICARE

Il gioco è basato su Java / OpenGL, quindi verrà rilasciato su Windows / Mac / Linux. La possibilità di estenderlo ai dispositivi mobili è bassa. Il gioco è in stile RTS, 3D in terza persona.

MODIFICA 2

Non sono ancora del tutto soddisfatto del modo in cui ho implementato questo, ma ciò a cui mi sto muovendo è catturare eventi nella mia interfaccia utente e se non sono gestiti da nessuno dei miei componenti dell'interfaccia utente, trasmetto l'evento al "Mondo" per la raccolta / selezione. Qualcosa di simile a:

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

In questo modo non ottengo clic che perdono attraverso l'interfaccia utente per selezionare gli oggetti dietro i pulsanti e cosa no.

Attualmente i controlli della mia fotocamera sono ancora basati sul polling, e per ora sembra funzionare, ma potrei aggiornarlo in seguito.

Apprezzo tutte le risposte, scusa se ne ho potuto scegliere solo una!


6
Non sono sicuro in Java, ma in generale devi sempre effettuare il polling dell'input. Potresti quindi pubblicare eventi quando le cose cambiano, ma questo è ancora basato su un sistema di polling.
James,

Il punto più rilevante a mio avviso è progettare un loop di eventi che sia libero da qualsiasi altro layload oltre alla raccolta di input. Mi spiego: il sistema operativo eseguirà l'interruzione guidata dall'input e la tratterà nel "thread di input" globale, quindi questo thread del sistema operativo reindirizzerà i messaggi nell'applicazione attualmente in-focus e scriverà le informazioni nella loro coda di messaggi. La coda dei messaggi deve essere sottoposta a polling da PeekMessage o GetMessage. Il modo più rapido per ottenere ciò è utilizzare GetMessage e consentire al programmatore di svegliarti, quindi puoi timestamp del messaggio in modo molto preciso.
v.oddou,

Risposte:


17

Dipende dai requisiti del tuo gioco e dell'hardware. La maggior parte dei giochi è generalmente interessata alle modifiche allo stato di input, ovvero l'utente preme il tasto di fuoco e la sua arma inizia a sparare, l'utente rilascia il tasto di fuoco e la sua arma smette di sparare, l'utente preme il tasto di spostamento e inizia a muoversi, rilascia il tasto di spostamento e si ferma , ecc., quindi un sistema di input guidato dagli eventi ha più senso in quei casi poiché le informazioni sono già in un formato adatto. Inoltre sulla piattaforma Windows, ricevi già eventi per le modifiche allo stato della tastiera e del mouse, quindi spesso è una conversione 1: 1 da eventi di input di basso livello a eventi di gioco di alto livello. Con il polling, ti troverai spesso a dover generare tali eventi manualmente confrontando lo stato tra l'attuale e l'ultimo frame. Fondamentalmente, "quali pulsanti vengono premuti ora?"

Detto questo, su alcune piattaforme sei bloccato con input di polling a basso livello e non c'è modo di fare il controllo dei bordi. Tuttavia, ho sempre ottenuto i migliori risultati utilizzando gli eventi per tutta la logica di alto livello, poiché è naturale che questi sistemi tendano a funzionare.


Grazie, ho incluso ulteriori informazioni sulla piattaforma e sullo scopo del gioco.
MichaelHouse

1
Si noti che GetAsyncKeyStateè un modo semplice per utilizzare il polling su Win32.
Macke,

Derp, ho fatto una domanda nei commenti di Nate Bross di cui ti occupi qui, quindi immagino che lo perfezionerò. Tutti i PC offrono l'interruzione hardware 1: 1 alla relazione tra eventi della tastiera del sistema operativo e che tipo di piattaforme sono limitate al polling di basso livello?
michael.bartnett,

@Macke: a volte l'antivirus segnala i programmi che utilizzano questa API perché possono ricevere la pressione dei tasti da tutto il sistema globale, consentendo in tal modo keylogging dannoso. L'articolo più interessante al riguardo su Internet (lo so) è questo: securelist.com/analysis/publications/36358/…
v.oddou,

7

Non vedo alcun motivo per cui non puoi fare entrambe le cose e ottenere il meglio da entrambi i mondi.

Gli eventi di input vengono generati dal polling (a un certo livello il driver esegue il polling dell'hardware per vedere in che stato si trova) e, poiché il loop principale esegue il polling di tutti i dispositivi di input, è possibile implementare facilmente i propri. Qualcosa di semplice come di seguito è quello che ho usato in passato.

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
}

So che hai definito gli eventi come interrupt e ciò che ho inserito qui non è "veramente basato sugli eventi", ma non vedo cosa non ti dà ciò che gli interruzioni ti danno - la maggior parte degli utenti non noterà il singolo frame ha perso, a meno che il gioco non funzioni a frame rate molto bassi.


1
Sono curioso della natura di ricevere input dai dispositivi. Gli eventi della tastiera inviati dal sistema operativo sono il risultato del polling a livello di driver del dispositivo? O un evento della tastiera corrisponde a un interrupt? Oppure ci sono interruzioni, ma il sistema operativo le memorizza nel buffer e le invia quando lo ritiene opportuno?
michael.bartnett,

Non sono sicuro di come funzioni a quel livello, ma è molto semplice, alcuni software vengono eseguiti in loop e controllano lo stato della tastiera e lo confrontano con lo stato precedente, se viene modificato il gorgogliamento cambia.
Nate,

5

Ci sono due diversi problemi qui:

  1. Come leggi l'input dell'utente dal sistema operativo / hardware?

  2. Come elaborate l'input dell'utente nel vostro motore?

Per la lettura, dipende chiaramente dalla tua piattaforma e dal tipo di input che desideri leggere. Nota che è facile convertire una cosa in un'altra nel tuo livello di input. (Cioè sondare ed emettere eventi al motore, oppure ascoltare eventi ed emettere stato al motore.)

Per l'elaborazione, ci sono alcune diverse opzioni:

  • Per il controllo del movimento del giocatore (e schemi simili), il polling potrebbe essere più semplice in quanto è necessario ricalcolare la velocità di ciascun fotogramma. È molto probabile che il tuo ciclo interno sia basato sul polling:

    cioè qualcosa di simile speed += 1 if button.down else -1; clamp(speed, 0, 42);

  • Per eventi discreti (missili antincendio, gioco di pausa, teletrasporto dall'altra parte del pianeta), l'elaborazione degli eventi è preferibile, altrimenti il ​​tuo codice sarà disseminato di maybeLaunchMissile(key_state);chiamate, e questo è solo ... male, okay. ;)

Spero che sia d'aiuto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.