[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/de/docs/Web/API/Gamepad_API/Using_the_Gamepad_API [Back]  [Original]

Verwendung der Gamepad API - Web-APIs | MDN

Dieser Inhalt wurde automatisch aus dem Englischen bersetzt, und kann Fehler enthalten. Erfahre mehr ber dieses Experiment.

View in English Always switch to English

Verwendung der Gamepad API

Baseline Weitgehend verfgbar *

Diese Funktion ist gut etabliert und funktioniert auf vielen Gerten und in vielen Browserversionen. Sie ist seit Mrz 2017 browserbergreifend verfgbar.

* Einige Teile dieser Funktion werden mglicherweise unterschiedlich gut untersttzt.

HTML stellt die notwendigen Komponenten fr eine reichhaltige, interaktive Spielentwicklung bereit. Technologien wie <canvas>, WebGL, <audio> und <video>, zusammen mit JavaScript-Implementierungen, untersttzen Aufgaben, die hnliche, wenn nicht sogar die gleichen Funktionen wie nativer Code bieten. Die Gamepad API ermglicht es Entwicklern und Designern, Gamepads und andere Spielsteuerungen zu verwenden und darauf zuzugreifen.

Die Gamepad API fhrt neue Ereignisse auf dem Window Objekt ein, um den Status von Gamepads und Controllern (im Folgenden als Gamepad bezeichnet) auszulesen. Zustzlich zu diesen Ereignissen fgt die API ein Gamepad Objekt hinzu, welches zum Abfragen des Status eines verbundenen Gamepads verwendet werden kann, und eine Methode navigator.getGamepads(), mit der Sie eine Liste der der Seite bekannten Gamepads abrufen knnen.

In diesem Artikel

Verbindung mit einem Gamepad

Wenn ein neues Gamepad mit dem Computer verbunden wird, erhlt die fokussierte Seite zuerst ein gamepadconnected Ereignis. Wenn ein Gamepad bereits verbunden ist, wenn die Seite geladen wird, wird das gamepadconnected Ereignis an die fokussierte Seite gesendet, wenn der Benutzer eine Taste drckt oder eine Achse bewegt.

Hinweis: In Firefox werden Gamepads einer Seite nur dann angezeigt, wenn der Benutzer mit der sichtbaren Seite mit einem interagiert. Dies hilft zu verhindern, dass Gamepads fr das Fingerprinting des Benutzers verwendet werden. Sobald mit einem Gamepad interagiert wurde, werden andere verbundene Gamepads automatisch sichtbar sein.

Sie knnen gamepadconnected folgendermaen verwenden:

js
window.addEventListener("gamepadconnected", (e) => {
  console.log(
    "Gamepad connected at index %d: %s. %d buttons, %d axes.",
    e.gamepad.index,
    e.gamepad.id,
    e.gamepad.buttons.length,
    e.gamepad.axes.length,
  );
});

Jedes Gamepad hat eine eindeutige ID, die im gamepad Eigenschaft des Ereignisses verfgbar ist.

Trennen eines Gamepads

Wenn ein Gamepad getrennt wird, und falls eine Seite zuvor Daten fr dieses Gamepad erhalten hat (z.B. gamepadconnected), wird ein zweites Ereignis an das fokussierte Fenster gesendet, das gamepaddisconnected:

js
window.addEventListener("gamepaddisconnected", (e) => {
  console.log(
    "Gamepad disconnected from index %d: %s",
    e.gamepad.index,
    e.gamepad.id,
  );
});

Die index Eigenschaft des Gamepads ist eindeutig pro Gert, das mit dem System verbunden ist, selbst wenn mehrere Controller desselben Typs verwendet werden. Die index Eigenschaft dient auch als Index in das von Navigator.getGamepads() zurckgegebene Array.

js
const gamepads = {};

function gamepadHandler(event, connected) {
  const gamepad = event.gamepad;
  // Note: Use gamepad.index as the stable key, then read the latest
  // state from navigator.getGamepads() inside your update loop.

  if (connected) {
    gamepads[gamepad.index] = gamepad;
  } else {
    delete gamepads[gamepad.index];
  }
}

window.addEventListener("gamepadconnected", (e) => {
  gamepadHandler(e, true);
});
window.addEventListener("gamepaddisconnected", (e) => {
  gamepadHandler(e, false);
});

Dieses vorherige Beispiel zeigt, wie man den berblick darber behlt, welche Gerte anhand ihrer index Eigenschaften verbunden sind. Fr den aktuellen Tasten- und Achsenzustand rufen Sie in jedem Frame Navigator.getGamepads() auf und lesen Sie das neueste Objekt fr diesen index.

Abfrage des Gamepad-Objekts

Wie Sie sehen knnen, enthalten die oben besprochenen gamepad Ereignisse eine gamepad Eigenschaft im Ereignisobjekt, die ein Gamepad Objekt zurckgibt. Wir knnen dies verwenden, um zu bestimmen, welches Gamepad (d.h. seine ID) das Ereignis ausgelst hat, da mehrere Gamepads gleichzeitig angeschlossen sein knnten. Um den aktuellen Tasten- und Achsenzustand zu lesen, nutzen Sie den index des Gamepads und holen Sie das neueste Objekt von Navigator.getGamepads() in Ihrer Animationsschleife.

Solche berprfungen tendieren dazu, das Gamepad Objekt zusammen mit einer Animationsschleife (z.B. requestAnimationFrame) zu verwenden, bei der Entwickler Entscheidungen fr den aktuellen Frame basierend auf dem Zustand des Gamepads oder der Gamepads treffen mchten.

Die Methode Navigator.getGamepads() liefert ein Array aller derzeit fr die Webseite sichtbaren Gerte als Gamepad Objekte (der erste Wert ist immer null, sodass null zurckgegeben wird, wenn keine Gamepads verbunden sind). Dies kann dann verwendet werden, um die gleiche Information zu erhalten. Zum Beispiel knnte das erste Codebeispiel oben wie folgt umgeschrieben werden:

js
window.addEventListener("gamepadconnected", (e) => {
  const gp = navigator.getGamepads()[e.gamepad.index];
  console.log(
    "Gamepad connected at index %d: %s. %d buttons, %d axes.",
    gp.index,
    gp.id,
    gp.buttons.length,
    gp.axes.length,
  );
});

Die Eigenschaften des Gamepad Objekts sind wie folgt:

  • id: Ein String, der einige Informationen ber den Controller enthlt. Dies ist nicht streng spezifiziert, aber in Firefox wird er drei Informationen enthalten, die durch Bindestriche (-) getrennt sind: zwei 4-stellige Hexadezimalzeichenfolgen, die die USB-Hersteller- und Produkt ID des Controllers enthalten, und den vom Treiber bereitgestellten Namen des Controllers. Diese Informationen sollen helfen, eine Zuordnung fr die Bedienelemente auf dem Gert zu finden und ntzliches Feedback an den Benutzer zu geben.

  • index: Eine Ganzzahl, die fr jedes derzeit mit dem System verbundene Gamepad eindeutig ist. Dies kann verwendet werden, um mehrere Controller zu unterscheiden. Beachten Sie, dass das Trennen eines Gerts und anschlieendes Verbinden eines neuen Gerts den vorherigen Index erneut verwenden kann.

  • mapping: Ein String, der angibt, ob der Browser die Bedienelemente auf dem Gert auf ein bekanntes Layout umgemappt hat. Derzeit gibt es nur ein untersttztes bekanntes Layout - das standardmige Gamepad. Wenn der Browser in der Lage ist, die Bedienelemente auf dem Gert auf dieses Layout zu mappen, wird die mapping Eigenschaft auf den String standard gesetzt.

  • connected: Ein Boolescher Wert, der angibt, ob das Gamepad noch mit dem System verbunden ist. Wenn dies der Fall ist, lautet der Wert True; andernfalls False.

  • buttons: Ein Array von GamepadButton Objekten, die die auf dem Gert vorhandenen Tasten reprsentieren. Jeder GamepadButton besitzt eine pressed und eine value Eigenschaft:

    • Die pressed Eigenschaft ist ein Boolean, der angibt, ob die Taste derzeit gedrckt (true) oder ungedrckt (false) ist.
    • Die value Eigenschaft ist ein Fliekommawert, der verwendet wird, um analoge Tasten darzustellen, wie z.B. die Trigger bei vielen modernen Gamepads. Die Werte sind auf den Bereich 0.0..1.0 normalisiert, wobei 0.0 eine ungedrckte Taste darstellt und 1.0 eine vollstndig gedrckte Taste.
  • axes: Ein Array, das die Steuerungen mit Achsen auf dem Gert reprsentiert (z.B. analoge Thumbsticks). Jeder Eintrag im Array ist ein Fliekommawert im Bereich von -1.0 bis 1.0, der die Achsenposition vom niedrigsten Wert (-1.0) bis zum hchsten Wert (1.0) darstellt.

  • timestamp: Dies gibt ein DOMHighResTimeStamp zurck, welches den Zeitpunkt der letzten Aktualisierung der Daten fr dieses Gamepad darstellt. Dadurch knnen Entwickler feststellen, ob die axes und button Daten von der Hardware aktualisiert wurden. Der Wert muss relativ zum Attribut navigationStart der PerformanceTiming Schnittstelle sein. Die Werte sind monoton steigend, was bedeutet, dass sie verglichen werden knnen, um die Reihenfolge der Aktualisierungen zu bestimmen, da neuere Werte stets grer oder gleich lteren Werten sind. Beachten Sie, dass diese Eigenschaft derzeit in Firefox nicht untersttzt wird.

Hinweis: Das Gamepad-Objekt ist aus Sicherheitsgrnden im gamepadconnected Ereignis verfgbar und nicht im Window Objekt selbst. Sie knnen auch ber Navigator.getGamepads() auf Gamepads zugreifen. In der Praxis sollten Sie Navigator.getGamepads() abfragen und jede Bildaktualisierung das aktuelle Objekt fr einen bekannten index lesen, anstatt sich auf eine langfristige Referenz eines frheren Ereignisses zu verlassen.

Verwendung von Tasteninformationen

Schauen wir uns ein Beispiel an, das Verbindungsinformationen fr ein Gamepad anzeigt (nachfolgende Gamepad-Verbindungen werden ignoriert) und es ermglicht, einen Ball ber den Bildschirm zu bewegen, indem die vier Gamepad-Tasten auf der rechten Seite des Gamepads verwendet werden. Sie knnen die Demo live ansehen und den Quellcode auf GitHub finden.

Zuerst deklarieren wir einige Variablen: Der gamepadInfo Absatz, in den die Verbindungsinformationen geschrieben werden, der ball, den wir bewegen wollen, die start-Variable, die als ID fr requestAnimationFrame dient, die a und b Variablen, die als Positionsmodifikatoren fr die Ballbewegung fungieren, und die Kurzvariablen, die fr die plattformbergreifenden Variationen von requestAnimationFrame() und cancelAnimationFrame() verwendet werden.

js
const gamepadInfo = document.getElementById("gamepad-info");
const ball = document.getElementById("ball");
let start;
let a = 0;
let b = 0;

Als nchstes verwenden wir das gamepadconnected Ereignis, um zu prfen, ob ein Gamepad angeschlossen ist. Wenn eines angeschlossen ist, holen wir das Gamepad mit navigator.getGamepads()[0], drucken Informationen ber das Gamepad in unser div fr Gamepad-Informationen und starten die gameLoop() Funktion, die den gesamten Ballbewegungsprozess ins Rollen bringt.

js
window.addEventListener("gamepadconnected", (e) => {
  const gp = navigator.getGamepads()[e.gamepad.index];
  gamepadInfo.textContent = `Gamepad connected at index ${gp.index}: ${gp.id}. It has ${gp.buttons.length} buttons and ${gp.axes.length} axes.`;

  gameLoop();
});

Jetzt verwenden wir das gamepaddisconnected Ereignis, um zu berprfen, ob das Gamepad wieder getrennt wird. Falls ja, beenden wir die requestAnimationFrame() Schleife (siehe unten) und setzen die Gamepaddaten auf ihren ursprnglichen Zustand zurck.

js
window.addEventListener("gamepaddisconnected", (e) => {
  gamepadInfo.textContent = "Waiting for gamepad.";

  cancelAnimationFrame(start);
});

Jetzt zur Hauptspielschleife. Bei jeder Ausfhrung der Schleife prfen wir, ob eine der vier Tasten gedrckt wird; falls ja, aktualisieren wir die Werte der Bewegungsvariablen a und b entsprechend und aktualisieren die left und top Eigenschaften, indem wir ihre Werte auf die aktuellen Werte von a und b setzen. Dies hat den Effekt, den Ball ber den Bildschirm zu bewegen.

Nachdem dies alles erledigt ist, verwenden wir unser requestAnimationFrame(), um das nchste Animationsbild anzufordern und gameLoop() erneut auszufhren.

js
function gameLoop() {
  const gamepads = navigator.getGamepads();
  if (!gamepads) {
    return;
  }

  const gp = gamepads[0];
  if (gp.buttons[0].pressed) {
    b--;
  }
  if (gp.buttons[2].pressed) {
    b++;
  }
  if (gp.buttons[1].pressed) {
    a++;
  }
  if (gp.buttons[3].pressed) {
    a--;
  }

  ball.style.left = `${a * 2}px`;
  ball.style.top = `${b * 2}px`;

  start = requestAnimationFrame(gameLoop);
}

Komplettes Beispiel: Anzeige des Gamepad-Zustands

Dieses Beispiel zeigt, wie das Gamepad Objekt sowie die Ereignisse gamepadconnected und gamepaddisconnected verwendet werden, um den Zustand aller mit dem System verbundenen Gamepads anzuzeigen. Das Beispiel basiert auf einer Gamepad-Demo, deren Quellcode auf GitHub verfgbar ist.

js
let loopStarted = false;

window.addEventListener("gamepadconnected", (evt) => {
  addGamepad(evt.gamepad);
});
window.addEventListener("gamepaddisconnected", (evt) => {
  removeGamepad(evt.gamepad);
});

function addGamepad(gamepad) {
  const d = document.createElement("div");
  d.setAttribute("id", `controller${gamepad.index}`);

  const t = document.createElement("h1");
  t.textContent = `gamepad: ${gamepad.id}`;
  d.append(t);

  const b = document.createElement("ul");
  b.className = "buttons";
  gamepad.buttons.forEach((button, i) => {
    const e = document.createElement("li");
    e.className = "button";
    e.textContent = `Button ${i}`;
    b.append(e);
  });

  d.append(b);

  const a = document.createElement("div");
  a.className = "axes";

  gamepad.axes.forEach((axis, i) => {
    const p = document.createElement("progress");
    p.className = "axis";
    p.setAttribute("max", "2");
    p.setAttribute("value", "1");
    p.textContent = i;
    a.append(p);
  });

  d.appendChild(a);

  // See https://github.com/luser/gamepadtest/blob/master/index.html
  const start = document.querySelector("#start");
  if (start) {
    start.style.display = "none";
  }

  document.body.append(d);
  if (!loopStarted) {
    requestAnimationFrame(updateStatus);
    loopStarted = true;
  }
}

function removeGamepad(gamepad) {
  document.querySelector(`#controller${gamepad.index}`).remove();
}

function updateStatus() {
  for (const gamepad of navigator.getGamepads()) {
    if (!gamepad) continue;

    const d = document.getElementById(`controller${gamepad.index}`);
    const buttonElements = d.getElementsByClassName("button");

    for (const [i, button] of gamepad.buttons.entries()) {
      const el = buttonElements[i];

      const pct = `${Math.round(button.value * 100)}%`;
      el.style.backgroundSize = `${pct} ${pct}`;
      if (button.pressed) {
        el.textContent = `Button ${i} [PRESSED]`;
        el.style.color = "#42f593";
        el.className = "button pressed";
      } else {
        el.textContent = `Button ${i}`;
        el.style.color = "#2e2d33";
        el.className = "button";
      }
    }

    const axisElements = d.getElementsByClassName("axis");
    for (const [i, axis] of gamepad.axes.entries()) {
      const el = axisElements[i];
      el.textContent = `${i}: ${axis.toFixed(4)}`;
      el.setAttribute("value", axis + 1);
    }
  }

  requestAnimationFrame(updateStatus);
}

Spezifikationen

Spezifikation
Gamepad
# gamepad-interface
Gamepad Extensions
# partial-gamepad-interface

Browser-Kompatibilitt


Web Proxy Viewer  |  New URL  |  Original Page