Signatur
Beschreibung
Die Eigenschaft buttons eines Gamepad-Objekts enthält ein Array von GamepadButton-Objekten, eines für jede Taste des Geräts. Jedes Objekt hat drei Eigenschaften: pressed (boolean, ob die Taste gedrückt ist), touched (boolean, ob sie berührt wird, sofern die Hardware das erkennt) und value (Zahl zwischen 0.0 und 1.0, bei analogen Tasten wie Schultertasten/Triggern ein Zwischenwert).
Wenn Gamepad.mapping den Wert "standard" hat, folgen die Indizes dem Standard-Gamepad-Layout der W3C-Spezifikation: 0 = unterer Aktionsknopf (A / Kreuz), 1 = rechter (B / Kreis), 2 = linker (X / Quadrat), 3 = oberer (Y / Dreieck), 4/5 = vordere Schultertasten, 6/7 = Trigger (analog), 8 = Select/Back, 9 = Start, 10/11 = Stick-Klicks, 12–15 = Steuerkreuz (oben, unten, links, rechts), 16 = Home/Guide-Taste.
Die Gamepad API ist abfragebasiert (Polling): Es gibt keine Ereignisse für einzelne Tastendrücke. Man liest die Tastenzustände typischerweise in jedem Frame innerhalb einer requestAnimationFrame-Schleife über navigator.getGamepads() aus und vergleicht sie mit dem vorherigen Zustand, um „gerade gedrückt“ bzw. „gerade losgelassen“ zu erkennen.
Rückgabewert
GamepadButton-Objekten mit den Eigenschaften pressed, touched und value. Die Länge hängt vom Gerät und vom Mapping ab (beim Standard-Layout meist 17).Beispiele
Tastenzustände in einer Spielschleife auslesen
const loop = () => {
// Immer frisch abfragen – in Chrome sind Gamepad-Objekte Momentaufnahmen
for (const pad of navigator.getGamepads()) {
if (!pad) continue;
pad.buttons.forEach((btn, i) => {
if (btn.pressed) {
console.log(`Pad ${pad.index}: Taste ${i} gedrückt (Wert ${btn.value.toFixed(2)})`);
}
});
}
requestAnimationFrame(loop);
};
window.addEventListener('gamepadconnected', (e) => {
console.log(`Verbunden: ${e.gamepad.id} mit ${e.gamepad.buttons.length} Tasten`);
requestAnimationFrame(loop);
});
Analogen Trigger als Gaspedal nutzen
const RT = 7; // rechter Trigger im Standard-Layout
const LT = 6; // linker Trigger
const update = () => {
const pad = navigator.getGamepads()[0];
if (pad && pad.mapping === 'standard') {
const gas = pad.buttons[RT].value; // 0.0 – 1.0
const bremse = pad.buttons[LT].value;
const beschleunigung = gas - bremse;
document.querySelector('#speed').textContent = beschleunigung.toFixed(2);
}
requestAnimationFrame(update);
};
requestAnimationFrame(update);
„Gerade gedrückt“ per Flankenerkennung
let previous = [];
const poll = () => {
const pad = navigator.getGamepads()[0];
if (pad) {
const current = pad.buttons.map((b) => b.pressed);
current.forEach((isDown, i) => {
if (isDown && !previous[i]) console.log(`Taste ${i} neu gedrückt`);
if (!isDown && previous[i]) console.log(`Taste ${i} losgelassen`);
});
previous = current;
}
requestAnimationFrame(poll);
};
requestAnimationFrame(poll);
// Wichtig · Fallstricke
- Momentaufnahme: In Chromium-Browsern ist das von
navigator.getGamepads()gelieferte Objekt ein Schnappschuss –buttonsaktualisiert sich nicht von selbst. RufegetGamepads()daher in jedem Frame neu auf, statt das Objekt aus demgamepadconnected-Ereignis zu speichern. - Mapping prüfen: Die Bedeutung der Indizes ist nur bei
mapping === "standard"garantiert. Bei leerem Mapping ("") sind Reihenfolge und Anzahl herstellerabhängig – biete dann eine Tastenbelegung durch den Benutzer an. - Keine Tasten-Events: Es gibt keine standardisierten
buttondown-Ereignisse; Zustandsänderungen müssen per Polling erkannt werden. - Nutzeraktivierung: Aus Datenschutzgründen (Fingerprinting) werden Gamepads erst sichtbar, nachdem der Benutzer eine Taste gedrückt hat, während die Seite fokussiert ist. Vorher liefert
getGamepads()nurnull-Einträge. - Sicherer Kontext: Neuere Browser stellen die API nur über HTTPS bereit; zudem kann sie per Permissions-Policy
gamepadin iframes gesperrt sein. touchedwird nicht von jeder Hardware unterstützt und entspricht dann meistpressed. Analoge Werte können leicht rauschen – setze bei Bedarf einen Schwellwert.