Trenne ich und wie die Belange von Eingabe- und Spielobjekten?

20

In wahrscheinlich jedem Spiel muss sich ein Entwickler irgendwie mit Eingaben befassen, es können einfache Tastatur- und Mausereignisse, Berührungsereignisse oder etwas wie eine Beschleunigungsmessereingabe sein. Diese Eingabe wirkt sich direkt oder indirekt auf Objekte im Spiel aus. Manchmal kann dieselbe Eingabe unterschiedliche Objekte beeinflussen. Jetzt habe ich darüber nachgedacht, wie ich das modellieren soll. Meines Erachtens gibt es zwei verschiedene Ansätze.

  • Lassen Sie das Spielobjekt selbst damit umgehen, abonnieren Sie die Ereignisse und rufen Sie seine eigenen Methoden auf. Dies hat den Vorteil, dass die Spielobjekte selbst entscheiden können, welche Eingaben welche Aktion auslösen. Ein Nachteil scheint zu sein, dass der eingegebene Code mit dem "Kern" -Spielobjektcode verfälscht wird. Außerdem kennen die Spielobjekte den Status des restlichen Spiels nicht und sollten manchmal möglicherweise nicht auf Eingabeereignisse reagieren. Das scheint nicht richtig zu sein.

  • Lassen Sie alle Eingaben von einem allgemeinen Eingabecontroller erledigen und entscheiden, wer mit welchem ​​Ereignis fertig wird. Dies scheint die Bedenken besser zu trennen, koppelt aber die Input-Controller-Klasse eng mit den Spielobjekten. Es muss irgendwie wissen, wer welches Ereignis in welchem ​​Zustand empfangen möchte. Dies scheint auch nicht richtig zu sein.

Mit welchen Strategien gehen Sie damit um?

Robert Massa
quelle

Antworten:

7

Ich empfehle, Eingabeereignisse von Spielobjekten zu trennen, damit Sie Eingabemethoden schnell ändern / aktualisieren können, ohne 10 Objektklassen bearbeiten und debuggen zu müssen. Beispiele für die Umstellung von Nur-Tastatur-Steuerelementen auf Maus + Tastatur oder die einfache Neuzuweisung von Tasten.

Anstatt die Eingabe fest an die einzelnen Spielobjekte zu koppeln, rufen Sie nur eine Methode pro eindeutigem Eingangssignal für das Spielobjekt auf und lassen Sie es entscheiden, wie es ausgeführt werden soll.

Verwenden Sie einen Eingabecontroller, um den Eingabestatus zu verfolgen:

Up press event   -> dir = up
Down press event -> dir = down

Wenn sich der Eingabestatus ändert, bewerten Sie, ob die Spielobjekte zum Ändern bereit sind:

set dir  ->  if gamestate != paused && battlemode == false
             ->  character.changeDir(dir);

Implementieren Sie bei Bedarf allgemeine Methoden für Ihre Spielobjekte, die vom Eingabecontroller aufgerufen werden können, oder für andere Spielobjekte:

changeDir (dir)
setSpeed (walk/run)
Edwardian
quelle
7

Ich empfehle den MVC-Ansatz. In MVC müssen sich die Spielobjekte nur um die Modellierung des Spielsystems kümmern und bieten eine übergeordnete Oberfläche wie move_left. Stellen Sie dann ein Controller-Objekt bereit, das sich um die Zuordnung der Eingabe zu Modellaufrufen kümmert. Dies ermöglicht nicht nur einen einfachen Wechsel der Steuerung, sondern bietet auch eine gute Schnittstelle für die KI. Sie sind lediglich eine weitere Steuerung.

In Ihrer zweiten Option würde ich den Eingabecontroller in zwei Teile aufteilen, einen, der die tatsächliche Geräteberührung, Tastatur, Beschleunigung und alles, was Sie sonst noch darauf werfen können, behandelt. Dann haben Sie einen zweiten Teil, der generische Eingaben auf spielspezifische Eingaben abbildet. Nehmen wir an, die Pfeiltasten auf der Tastatur zeigen auf Eingabe1 und berühren dann den oberen Rand eines Touchscreens, um auch Eingabe1 zuzuordnen. Jetzt schreiben Sie ein zweites Stück, das Eingabe 1 zum Springen zuordnet. Sie können diesem generischen Eingabesystem jetzt jedes beliebige IO-Gerät sowie gespeicherte Wiedergabe- oder AI-Eingaben zuordnen und einen kleinen spielspezifischen Teil hinzufügen, der die Bedeutung der Eingabe1 für das Modell festlegt.

Steinmetalle
quelle
5
An anderer Stelle auf dieser Website wird viel darüber diskutiert, warum MVC im Allgemeinen kein geeignetes Muster für Spiele ist. Was Stonemetal beschreibt, ist nicht einmal MVC, sondern nur Abstraktion. und "Use MVC" ist keine Antwort, da MVC eine Beschreibung einer ganzen Klasse von Architekturen ist und keine besondere Möglichkeit, Bedenken zu trennen (und auch nicht die einzige Möglichkeit, dies zu tun).
2
MVC sollte ihm A) einen Wikipedia-Artikel zum Lesen geben. B) eine Reihe von Variationen zur Herangehensweise an die Lösung, von denen gezeigt wurde, dass sie funktionieren Der Controller ordnet den Low-Level-Eingang (real oder synthetisch) der High-Level-Aktion zu und manipuliert das Modell direkt und nicht irgendein Ereignissystem.
Stonemetal 18.11.10
1

Ich würde vorschlagen, dass Ihr Spiel (das Modell ) eine Liste möglicher Eingabeereignisse definiert (implementiert als Aufzählungen oder Objekte mit einer gemeinsamen Basisschnittstelle). Dinge wie MovingRightStarted, MovingRightStopped, FiredWeapon1, Escape, etc ...

Das Spiel definiert eine Datenstruktur (zum Beispiel a queue), die Ihr Eingabecode (der Controller ) mit Eingabeereignissen füllen kann.

Anschließend kann Ihr Spiel die Datenstruktur abfragen, um die Eingabeereignisse abzurufen.

Auf diese Weise können Sie verschiedene Arten von Controllern anschließen, um das Modell zu versorgen:

  • Nur Tastatur
  • Tastatur + Maus
  • Joystick
  • Berührungssensitiver Bildschirm
  • Künstliche Intelligenz

Sie müssen sie nur zum Übertragen von Eingabeereignissen auf das Modell verwenden.

Splo
quelle
Ich glaube, ich verstehe, was Sie meinen, außer dass Sie einen queueDatentyp als Datentyp zum Speichern ausgewählt haben. Kannst du erklären warum?
Robert Massa
Zwischen zwei Abfragen von Eingabeereignissen aus dem Modell hat der Controller möglicherweise mehrere Aktionsereignisse übertragen, und es ist wichtig, die Reihenfolge der Benutzereingaben beizubehalten. Deshalb habe ich mich für eine FIFO-Datenstruktur entschieden. Tatsächlich müssen Sie möglicherweise auch angeben, zu welchem ​​Zeitpunkt die Eingabe genau erfolgte.
Splo