Abfrage gegen ereignisgesteuerte Eingabe

19

Ich entwickle ein Spiel, bei dem die Eingabemethode abgefragt wird. Da ich mich jetzt jedoch eingehender mit den Spielmenüs und anderen UI-Komponenten befasse, möchte ich wahrscheinlich ereignisgesteuerte Eingaben haben. Vielleicht haben Sie sogar beides, verwenden ereignisgesteuert für die Benutzeroberfläche und fragen nach der Eingabe "world". Ich bin gespannt, was der beste Weg ist.

Ich definiere Polling als: Bei jeder Update-Schleife überprüfe ich, welche Tasten gedrückt sind, wo sich die Maus befindet, welche Tasten gedrückt sind, durchlaufe sie und führe Aktionen basierend auf den gesammelten Informationen aus.

Ich definiere ereignisgesteuert als: Interrupt-basierte Ereignisse, wenn ein Ereignis eintritt und ein Interrupt ausgelöst wird und ein Codeblock basierend auf dem Ereignis ausgeführt wird.

Denken Sie, dass es am besten ist, alle Ereignisse abzufragen, alle Abfragen durchzuführen, oder ist eine Kombination aus beidem akzeptabel? Wenn Sie für beides Vor- und Nachteile haben, listen Sie diese bitte auf. Vielen Dank.

BEARBEITEN

Das Spiel basiert auf Java / OpenGL und wird daher für Windows / Mac / Linux veröffentlicht. Die Möglichkeit, dies auf mobile Geräte auszudehnen, ist gering. Das Spiel ist im RTS-Stil, 3rd Person 3D.

BEARBEITEN 2

Ich bin immer noch nicht ganz zufrieden mit der Art und Weise, wie ich dies implementiert habe, aber was ich vorantreibe, ist, Ereignisse in meiner Benutzeroberfläche zu erfassen. Wenn sie nicht von einer meiner Benutzeroberflächenkomponenten verarbeitet werden, leite ich das Ereignis an die weiter "Welt" zur Auswahl. So etwas wie:

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

Auf diese Weise bekomme ich keine Klicks durch die Benutzeroberfläche, um Objekte hinter Schaltflächen auszuwählen und was nicht.

Momentan basieren meine Kamerasteuerungen noch auf Abfragen, und das scheint momentan zu funktionieren, aber ich kann das später aktualisieren.

Ich freue mich über alle Antworten, sorry, ich konnte nur eine auswählen!

MichaelHouse
quelle
6
Ich bin mir in Java nicht sicher, aber im Allgemeinen müssen Sie Eingaben immer abfragen. Sie können dann Ereignisse veröffentlichen, wenn sich die Dinge ändern, dies basiert jedoch immer noch auf einem Abfragesystem.
James
Meiner Meinung nach ist der wichtigste Schwerpunkt das Entwerfen einer Ereignisschleife, die frei von jeglichem anderen Layload als der Eingabeauflistung ist. Lassen Sie mich erklären: Das Betriebssystem führt die eingabebasierte Unterbrechung durch und behandelt sie im globalen "Eingabethread". Anschließend leitet dieser Betriebssystem-Thread Nachrichten an die aktuell fokussierte Anwendung weiter und schreibt die Informationen in die Nachrichtenwarteschlange. Die Nachrichtenwarteschlange muss von PeekMessage oder GetMessage abgefragt werden. Am schnellsten erhalten Sie dies, indem Sie GetMessage verwenden und sich vom Scheduler wecken lassen. Anschließend können Sie die Nachricht sehr genau mit einem Zeitstempel versehen.
v.oddou

Antworten:

17

Dies hängt von den Anforderungen Ihres Spiels und Ihrer Hardware ab. Die meisten Spiele sind normalerweise an Änderungen des Eingabestatus interessiert, dh der Benutzer drückt die Feuertaste und seine Waffe beginnt zu feuern, der Benutzer lässt die Feuertaste los und seine Waffe hört auf zu feuern, der Benutzer drückt die Bewegungstaste und beginnt sich zu bewegen, lässt die Bewegungstaste los und hört auf sich zu bewegen usw., so ist in diesen Fällen ein ereignisgesteuertes Eingabesystem am sinnvollsten, da die Informationen bereits in einem geeigneten Format vorliegen. Außerdem erhalten Sie auf der Windows-Plattform bereits Ereignisse für Änderungen des Tastatur- und Mausstatus, sodass häufig eine 1: 1-Konvertierung von Low-Level-Eingabeereignissen in High-Level-Spieleereignisse erfolgt. Beim Abrufen müssen Sie solche Ereignisse häufig manuell generieren, indem Sie den Status zwischen dem aktuellen und dem letzten Frame vergleichen. Grundsätzlich "Welche Tasten werden jetzt gedrückt?"

Auf bestimmten Plattformen ist die Abfrageeingabe jedoch zu niedrig, und Sie können nicht daran vorbei gehen, sich selbst zu überprüfen. Ich habe jedoch immer die besten Ergebnisse mit Ereignissen für die gesamte Logik auf hoher Ebene erzielt, da diese Systeme normalerweise so funktionieren.

Skyler York
quelle
Danke, ich habe zusätzliche Informationen über die Plattform und den Zweck des Spiels beigefügt.
MichaelHouse
1
Beachten Sie, dass dies GetAsyncKeyStateeine einfache Möglichkeit ist, die Abfrage unter Win32 zu verwenden.
Macke
Derp, ich habe in den Kommentaren von Nate Bross eine Frage gestellt, mit der Sie sich hier befassen. Ich schätze, ich werde sie verfeinern. Bieten alle PCs diese 1: 1-Beziehung zwischen Hardware-Interrupts und Tastaturereignissen an, und welche Plattformen sind auf Low-Level-Polling beschränkt?
michael.bartnett
@Macke: Manchmal meldet Antivirus-Programme, die diese API verwenden, weil sie Tastendruck vom gesamten globalen System empfangen können, wodurch böswilliges Keylogging ermöglicht wird. Der tollste Artikel im gesamten Internet (von dem ich weiß) ist dieser: securelist.com/analysis/publications/36358/…
v.oddou
7

Ich sehe keinen Grund, warum Sie nicht beides können und das Beste aus beiden Welten bekommen.

Eingabeereignisse werden durch Abfragen generiert (auf einer bestimmten Ebene fragt der Treiber die Hardware ab, um festzustellen, in welchem ​​Status sie sich befindet). Da Ihre Hauptschleife alle Eingabegeräte abfragt, können Sie problemlos Ihre eigenen implementieren. So etwas Einfaches wie das Folgende habe ich in der Vergangenheit verwendet.

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
}

Ich weiß, dass Sie Ereignisse als Interrupts definiert haben und dass das, was ich hier angegeben habe, nicht "wirklich ereignisbasiert" ist, aber ich sehe nicht, was Ihnen die oben genannten nicht bieten, was Interrupts Ihnen bieten - die meisten Benutzer werden es nicht bemerken Der einzelne Frame geht verloren, es sei denn, Ihr Spiel läuft mit einer sehr niedrigen Framerate.

Nate
quelle
1
Ich bin neugierig auf die Art und Weise, wie Eingaben von Geräten kommen. Sind Tastaturereignisse, die vom Betriebssystem ausgelöst werden, das Ergebnis einer Abfrage auf Gerätetreiberebene? Oder entspricht ein Tastaturereignis einem Interrupt? Oder gibt es Interrupts, die aber vom Betriebssystem gepuffert und bei Bedarf abgesetzt werden?
michael.bartnett
Ich bin mir nicht sicher, wie es auf dieser Ebene funktioniert, aber es ist am einfachsten, einige Software läuft in einer Schleife und überprüft den Tastaturstatus und vergleicht ihn mit dem vorherigen Status.
Nate
5

Hier gibt es zwei verschiedene Probleme:

  1. Wie liest man Benutzereingaben vom Betriebssystem / der Hardware?

  2. Wie verarbeiten Sie Benutzereingaben in Ihrer Engine?

Zum Lesen hängt es eindeutig von Ihrer Plattform ab und welche Art von Eingabe Sie lesen möchten. Beachten Sie, dass es in Ihrer Eingabeebene einfach ist, eine Sache in eine andere zu konvertieren. (Das heißt, Ereignisse abfragen und an die Engine senden oder Ereignisse abhören und Status an die Engine senden.)

Für die Bearbeitung gibt es einige verschiedene Möglichkeiten:

  • Bei der Steuerung der Spielerbewegung (und ähnlichen Schemata) ist das Abrufen möglicherweise einfacher, da Sie die Geschwindigkeit für jedes Bild neu berechnen müssen. Es ist sehr wahrscheinlich, dass Ihre innere Schleife auf Abfragen basiert:

    also so etwas wie speed += 1 if button.down else -1; clamp(speed, 0, 42);

  • Für diskrete Ereignisse (Feuerwaffe, Pausenspiel, Teleport auf die andere Seite des Planeten) ist die Ereignisverarbeitung vorzuziehen, da sonst Ihr Code mit maybeLaunchMissile(key_state);Anrufen übersät ist und das ist nur ... schlecht, m'kay. ;)

Ich hoffe es hilft.

Macke
quelle