Web-Gamepad-API: DirectInput, XInput und die Mapping-Verwirrung

Was die Gamepad-API dir gibt

Die Gamepad-API des Browsers legt verbundene Controller über navigator.getGamepads() offen, was ein Array von Gamepad-Objekten zurückgibt. Jedes Objekt hat ein buttons-Array — jeder Eintrag ist ein Objekt mit pressed, touched und einem analogen value von 0 bis 1 — und ein axes-Array mit den analogen Stickpositionen, jede von -1 bis 1. Es gibt gamepadconnected- und gamepaddisconnected-Events, aber der Zustand von Tasten und Achsen wird dir nie zugeschoben: Du musst ihn pollen.

In der Praxis heißt das, das Gamepad in einer requestAnimationFrame-Schleife einmal pro Frame zu lesen und dieses Frame mit dem letzten zu vergleichen, um eine gerade gedrückte oder losgelassene Taste zu erkennen. Das Objekt, das du erhältst, ist eine eingefrorene Momentaufnahme, also rufst du getGamepads() jedes Frame erneut für frische Werte auf. Dieses Polling-Modell ist das Erste, was Entwickler überrascht, die von Tastatur- oder Pointer-Events kommen.

Das 'Standard Mapping'

Die Spezifikation definiert ein kanonisches Layout namens Standard Mapping. Wenn ein Controller dazu passt, ist gamepad.mapping der String standard, und die Indizes sind fest und vorhersehbar: buttons[0] ist die untere Face-Taste (A / Kreuz), buttons[1] die rechte (B / Kreis), und Bumper, Trigger, Steuerkreuz und Stick-Klicks sitzen an definierten Positionen, wobei axes[0] bis axes[3] den linken und rechten Stick tragen. Siebzehn Tasten und vier Achsen in bekannter Reihenfolge.

Wenn gamepad.mapping ein leerer String ist, passte der Controller nicht zum Standard-Layout und keiner dieser Indizes ist garantiert. Dieselbe physische Taste kann an einem anderen Index landen, ein Trigger kann als Achse erscheinen, und das Steuerkreuz kann eine einzelne Hat-Achse statt vier Tasten sein. Die mapping-Eigenschaft ist das wichtigste Feld, das du prüfen musst, bevor du irgendeinem Index traust.

DirectInput vs. XInput: die Wurzel der Verwirrung

Unter Windows gibt es zwei Wege, wie ein Spiel mit einem Controller spricht. XInput ist Microsofts moderne API, gebaut um den Xbox-Controller und das Layout, dem jedes Xbox-kompatible Pad folgt. Weil dieses Layout fest ist, können Browser ein XInput-Gerät sauber auf das Standard Mapping abbilden — deshalb 'funktioniert' ein Xbox-Controller in einem Web-Spiel einfach.

DirectInput ist die ältere, generische API für jeden HID-Controller (Human Interface Device): viele Dritthersteller-Pads, Arcade-Sticks, Flight-Sticks, Lenkräder sowie ältere oder No-Name-Controller. DirectInput erzwingt keine feste Tastenreihenfolge, also hat der Browser kein kanonisches Layout zum Abbilden und meldet ein leeres mapping. Dieser eine Unterschied ist die Quelle fast jeder Meldung 'meine Tasten sind im Browser durcheinander'.

Warum dieselbe Taste verschiedene Indizes meldet

Bei einem DirectInput-Pad entscheidet der Hersteller, welches physische Bedienelement 'Taste 1' ist, also kann deine A-Taste als buttons[2] ankommen, die Trigger können im axes-Array statt als Tasten auftauchen, und das Steuerkreuz kann als Point-of-View-Hat (POV) gemeldet werden — eine Achse mit acht Richtungen — statt als vier getrennte Tasten.

Um diese Geräte nutzbar zu machen, wendet jeder Browser seine eigene Remapping-Heuristik an, und sie sind sich nicht immer einig: Derselbe DirectInput-Controller kann in Chrome und Firefox verschiedene Indizes erzeugen. XInput umgeht das ganze Problem, weil Microsoft das Layout festgelegt hat, weshalb 'nimm einen Controller im Xbox-Stil' der zuverlässigste Rat für Web-Spiele ist.

Wie man es im Code behandelt

Das robuste Muster ist, zuerst gamepad.mapping zu prüfen. Ist es gleich standard, kannst du benannte Indizes gefahrlos nutzen. Ist es leer, codiere nichts fest — biete einen Remapping-Bildschirm, der den Spieler bittet, jede Aktion zu drücken, damit du das Layout des Geräts lernst, und speichere das Ergebnis mit dem Schlüssel gamepad.id, damit es pro Controller erhalten bleibt.

Zwei weitere Details zählen unabhängig vom Mapping. Analogsticks ruhen selten exakt auf null, also wende eine kleine Deadzone an (üblicherweise um 0.1) und behandle alles darin als keine Eingabe, sonst bewegt Drift die Figur von selbst. Und weil die API poll-basiert ist, lies das Gamepad jedes Frame frisch und vergleiche mit dem vorigen Frame, um kontinuierlichen Zustand in diskrete 'gerade gedrückt'-Events zu verwandeln. Der Gamepad-Tester auf dieser Seite zeigt die rohen Tastenindizes und Achsenwerte, die dein Gerät meldet — der schnellste Weg zu sehen, ob es Standard-gemappt ist.

Erkenntnisse

Prüfe immer mapping, bevor du Indizes traust. Standard heißt das Spec-Layout; leer heißt gerätespezifisch.

Bevorzuge XInput- / Xbox-artige Controller für Web-Spiele — sie mappen auf das Standard-Layout, DirectInput-Pads nicht.

Codiere niemals Indizes fest für Nicht-Standard-Pads. Biete eine Remapping-UI und speichere das Ergebnis pro gamepad.id.

Wende eine Deadzone auf Achsen an, damit ruhende Sticks nicht als Bewegung zählen.

Polle jedes Frame und vergleiche — für Tasten und Achsen gibt dir die Gamepad-API Zustand, keine Events.