Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

31

27.01.2014, 13:35

Beim Inputhandling gibt es verschiedene Aspekte, die man auch getrennt voneinander behandeln soll. (Callbacks sind nich zwingend erforderlich, um die Tasten konfigurierbar zu halten.)

Der erste Punkt ist die Abstraktion bzw. das Mapping der tatsächlichen Eingaben zu "highlevel" Eingaben. Hier ist lediglich die Frage, ob man dies macht und ob man auch über die Tasten/Buttons an den rohen Input kommen kann. Ich persönlich würde dazu raten, diese Abstraktion einzubauen und den direkten Weg über die tatsächlichen Tasten nicht anzubieten. In seinem Spiel wird man ohnehin nur eine begrenzte Anzahl an Aktionen/"highlevel" Eingaben haben ("springen", "nach rechts laufen", "nach links laufen", "ducken", "schlagen", "oberes UI Element auswählen", "unteres UI Element auswählen", "UI Element aktivieren" etc.). Diesen kann man jeweils eine oder mehrere lowlevel Eingaben zuweisen ("Pfeiltaste hoch" -> "springen", "W" -> "springen", "W" -> "oberes UI Element auswählen", ...). Mit geringem Aufwand ist es bereits an dieser Stelle möglich, die Zuweisungen konfigurierbar zu halten, sodass die Steuerung angepasst werden kann, ohne den Code anfassen zu müssen, und damit alternative Steuerungen (Zweitbelegungen) möglich sind.
Das Mapping ist dabei nicht der einzige Teil dieser Abstraktion. Man kann die Abstraktion auch so handhaben, dass sich dahinter unterschiedliche Eingabemöglichkeiten/-arten (digitale Tasten, die gedrückt oder nicht gedrückt sind, analoge Eingaben, deren Wert von 0 bis 1 oder -1 bis 1 gehen kann, "Zeiger", wie die Maus oder Touchinput) befinden können, die dann einheitlich angesprochen/abgefragt werden können. Je mehr Eingabemöglichkeiten man bei dieser Abstraktion berücksichtigen möchte, um so schwieriger wird es aber auch, eine einheitliche und gleichzeitig sinnvolle Schnittstelle zu definieren, über die man immernoch gut auf die Eingaben eingehen kann (wenn eine enorme Abstraktion für das eigene Spiel nicht von relevanz ist, kann man auf besetimmte Teile verzichten). Gerade im Falle der Maus wird man sich am ehesten denken, dass ein einheitliches Ansprechen mit bspw. einem Analogstick nicht wirklich möglich ist, da die Maus bereits die Koordinaten auf dem Bildschirm liefert, während der Stick nur Werte von -1 bis 1 für beide Achsen liefert. Wenn man allerdings auch von der Maus lediglich die relative Bewegung berücksichtigt (und nicht die vom System gegebene Mausposition für bspw. den Cursor verwendet), dann hat man nicht nur den Vorteil, über einen Analogsstick und die Maus den Cursor bewegen zu können, sondern kann auch sehr einfach Einschränkungen für die Bewegung des Cursors implementieren (während der Auswahl von Einheiten macht es bspw. wenig Sinn, mit dem Cursor den sichtbaren Bereich zu verlassen).
Teil der Abstraktion ist auch die repräsentation der abstrahierten Eingaben nach außen hin und welche Arten dabei angeboten werden. Es könnte dort Eingaben geben, die betätigt oder nicht betätigt sein können, es könnte wie in Unity Achsen geben, denen man entweder tatsächliche Achsen oder 2 Buttons zuweisen kann, die ggf. auch automatisch interpoliert werden könnten, Es könnte aber auch 2 Achsige Eingaben (bspw. für die Spielerbewegung) geben, der dann 2 Achsen oder 4 Buttons/Tasten zugewiesen werden können. Abhhängig vom Spiel ist es ggf. auch Erforderlich, auf Texteingaben einzugehen (Name für Highscore, Chatnachrichten, ...), wofür die Schnittstelle des Inputmanagement ebenfalls etwas parat halten sollte. Dabei können die Eingaben nicht nur von der Tastatur kommen, aber dazu mehr im übernächsten Absatz.

Nachdem man nun ggf. das Mapping hat, müssen die entsprechenden Objekte der Spielszene und des UIs davon mitkriegen. Dabei kann man Events (dem Inputmanager werden Callbacks mitgegeben), Polling (vom Inputmanager kann der Ektuelle Zustand einer Eingabe abgefragt werden) oder beides verwenden. Was sinnvoller ist, dürfte wohl sehr vom Einsatzgebiet abhängen, allerdings würde ich Events nur für Dinge verwenden, die sich "gelegentlich" ändern können (bspw. das Drücken eines Buttons, um im Spiel eine Aktion auszulösen) und für Dinge, die sich im Grunde in jedem Frame ändern können (bspw. die Achsen eines Gamepads für Bewegung/Umschauen) eher ein Polling verwenden.
Wichtig dabei zu bedenken ist nur, dass die bisher genannten Nachteile des Pollings keine Nachteile des Pollings sind. Verwendet man ein Polling muss man entweder an der jeweiligen Stelle prüfen, ob die Eingaben berücksichtigt werden sollen oder man muss eine "höhere Stelle" haben, die von Inputmanager die Eingaben abfragt und dann schaut, wohin diese weitergegeben werden sollen. Verwendet man Events muss man entweder im Eventhandler ebenfalls die Prüfung durchführen, ebenfalls ein "höheres Objekt" verwenden oder man muss die Callbacks permanent anpassen. Das heißt also, dass man entweder genau das Gleiche wie vorher hat (Prüfung im Zielobjekt oder übergeordnetes Objekt) oder dass man fast das gleiche hat (Prüfung an anderer Stelle, damit Callbacks angepasst / Zielobjekte ausgetauscht werden können).
Anbei noch: in anderen Bereichen ist sehr häufig etwas Event-basiertes besser, allerdings hat man dort i. d. R. nur gelegentlich auftretende Änderungen und will grundsätzlich auch nur dann etwas machen, wenn es Eingaben gab. In Spielen macht man ohnehin schon in jedem Frame viele (teils Input-abhängige) Dinge, wodurch die üblichen Nachteile des Pollings nicht mehr relevant sind.

Worüber man sich anschließend noch Gedanken machen kann, ist das manuelle Auslösen von Eingaben bzw. virtuelle Eingaben. Einfachstes Beispiel sind dabei Abbildungen von Eingabegeräten, die dann mit den physisch vorhandenen bedient werden. Das können die vermutlich allseits bekannten Softkeys/Bildschirmtasten sein, die häufig von Spielen für Mobilgeräte verwendet werden, es können aber auch "Tastaturen" sein. Während man seinen Namen in einem Spiel eingibt will man nicht unbedingt auf eine Tastatur beschränkt sein, vor allem wenn man an einer Konsole spielt oder das Spiel aus einem anderen Grund Support für Gamepads bieten will.
Es wäre zwar möglich, den Großteil der Spielinternen Events ebenfalls über den Inputmanager zu handhaben, das macht allerdings nur dann Sinn, wenn es mehr als 1 Möglichkeit gibt, dieses Event auszulösen und/oder wenn ein solches über Eingabegeräte ausgelöst werden kann. Sinnvoller dürfte es in diesem Fall aber sein, das Versenden der Nachrichten in einen EventManager auszulagern und eine Kommunikation zwischen diesem und dem Inputmanager für aus Inputs resultierende Events aufzubauen.


Ich habe mir die beiden verlinkten Seiten noch nicht weiter angesehen, werde ich dann aber noch nachholen.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

ERROR

Alter Hase

  • »ERROR« ist der Autor dieses Themas

Beiträge: 417

Wohnort: Paderborn

Beruf: Informatik Student

  • Private Nachricht senden

32

22.02.2014, 17:56

Eine letzte Frage habe ich zu dem Thema noch, erstmal erkläre ich den derzeitigen Stand.

Ich mache das Ganze jetzt so:

Es gibt eine Klasse für den "RawInput", diese liest jeglichen benötigten Input erstmal direkt von den benötigten devices ein. Also Bewegung und Tasten der Maus und Tasten der Tastatur.

Die Klasse für den High Level Input mapt sich dann daraus den High Level Input.

Jetzt habe ich dabei nur ein Problem, die Klasse für den RawInput muss nun in JEDEM Frame ALLE Tasten abfragen, weil die Klasse zum einen ja nicht wissen darf, welche Tasten welchem High Level Input entsprechen und zum anderen muss es möglich sein, dass manchmal geschrieben wird o.Ä..


Ich denke, dass es ziemlich viel ist für jeden einzelnen Knopf in jedem Frame abzufragen ob er gedrückt ist oder eben nicht und dann jeweils die Keymap so zu verändern. Andererseits denke ich, wie soll man es sonst machen? Es Müssen ja alle Knöpfe zur Verfügung stehen.



Würde dann ja so aussehen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
Ist 'a' gedrückt?
{
    lastframegedrückt = gedrückt;
    gedrückt = true;
}
else
{
    lastframegedrückt = gedrückt;
    gedrückt = false;
}

Wenn man jetzt bedenkt, dass die Tastatur, die Maus, ein Controller und ein Joystick unterstützt werden, ist man locker bei 100+ Knöpfen. Hinzu kommen noch die Bewegungen auf den Achsen.


Die Frage nochmal Knapp formuliert: Wie sonst?

EDIT:
Ein Ansatz wäre natürlich, dass nur wichtiger Input abgefragt, also eben jene Knöpfe, die auch für den High Level input relevant sind und sobald Text erwartet wird, der Input anders eingelesen wird. Nur dann ergibt die Sache mit Raw und High Level ja wenig Sinn.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »ERROR« (22.02.2014, 18:14)


Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

33

22.02.2014, 20:01

Du benötigst eine solche Speicherung der Tastenzustände dann, wenn du diese abfragen musst (Polling), aber selbst lieber Events haben würdest.
Allerdings ist es nicht nur möglich, die Roheingaben zu speichern, da du genausogut auch den Stand des Highlevelinputs speichern kannst. Durch das Mapping ist bekannt, welche Tasten von welchem Gerät abgefragt werden müssen, um den aktuellen Zustand und somit den Unterschied zum letzten Zustand zu ermitteln, damit dann Events ausgelöst werden können.

Oder anders: Dieses Speichern des letzten Zustands muss nicht unbedingt mit dem Rohinput gemacht werden, sondern kann auch mit dem "Highlevel"-Input gemacht werden.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Werbeanzeige