Chrome-Dino-Spiel mit dem Gamepad spielen

Hier erfährst du, wie du mit der Gamepad API deine Webspiele auf Erfolgskurs bringst.

Das Easter Egg auf der Offlineseite von Chrome ist eines der am schlechtesten gehüteten Geheimnisse der Geschichte ([citation needed], aber der dramatische Effekt ist die Behauptung. Wenn Sie die Leertaste drücken oder auf einem Mobilgerät auf den Dinosaurier tippen, wird die Offlineseite zu einem spielbaren Arcade-Spiel. Vielleicht ist Ihnen bewusst, dass Man muss beim Spielen nicht offline sein: In Chrome navigieren Sie einfach zu about://dino oder, für den Geek in dir, zu about://network-error/-106. Aber wussten Sie, dass es Werden jeden Monat 270 Millionen Chrome-Dinospiele gespielt?

<ph type="x-smartling-placeholder">
</ph> Offlineseite von Chrome mit dem Chrome-Dino-Spiel. <ph type="x-smartling-placeholder">
</ph> Drücke zum Spielen die Leertaste!

Außerdem ist es sicherlich nützlicher zu wissen, dass man sich im Arcade-Modus, können Sie das Spiel mit einem Gamepad spielen. Die Gamepad-Unterstützung wurde vor etwa einem Jahr als dieses Schreibens in einer commit durch Reilly Grant: Wie ihr seht, ist das Spiel genau wie der Rest wurde vollständig Open Source. In zeige ich Ihnen, wie Sie die Gamepad API verwenden können.

Gamepad API verwenden

Funktionserkennung und Browserunterstützung

Die Gamepad API bietet eine allgemeine Browserunterstützung auf und Mobilgeräte. Anhand des folgenden Snippets können Sie feststellen, ob die Gamepad API unterstützt wird:

if ('getGamepads' in navigator) {
  // The API is supported!
}

Darstellung eines Gamepads im Browser

Der Browser stellt Gamepads als Gamepad dar. Objekte. Ein Gamepad hat die folgenden Attribute:

  • id: Ein Identifizierungsstring für das Gamepad. Diese Zeichenfolge identifiziert die Marke oder den Stil von verbundenem Gamepad-Gerät.
  • displayId: Die VRDisplay.displayId von verknüpfte VRDisplay (falls relevant).
  • index: Index des Gamepads im Navigator.
  • connected: Gibt an, ob das Gamepad noch mit dem System verbunden ist.
  • hand: Eine Aufzählung, in der definiert wird, in welcher Hand der Controller gehalten wird oder in welcher wahrscheinlich er gehalten wird .
  • timestamp: Der Zeitpunkt, zu dem die Daten für dieses Gamepad zuletzt aktualisiert wurden.
  • mapping: Die für dieses Gerät verwendete Zuordnung von Schaltflächen und Achsen, entweder "standard" oder "xr-standard"
  • pose: Ein GamepadPose-Objekt. Sie stellen die Positionsinformationen dar, die mit einem WebVR-Controller verknüpft sind.
  • axes: ein Array von Werten für alle Achsen des Gamepads, linear auf den Bereich von -1.01.0.
  • buttons: Eine Reihe von Schaltflächenstatus für alle Tasten des Gamepads.

Hinweis: Tasten können digital (gedrückt oder nicht gedrückt) oder analog (z. B. zu 78% gedrückt) sein. Dieses werden Schaltflächen als GamepadButton-Objekte mit den folgenden Attributen gemeldet:

  • pressed: Der gedrückte Zustand der Schaltfläche (true, wenn die Taste gedrückt wird, und false wenn sie nicht gedrückt wird.
  • touched: Der berührte Status der Schaltfläche. Wenn die Taste Berührungen erkennen kann, ist true, wenn die Schaltfläche berührt wird, andernfalls false.
  • value: Bei Schaltflächen mit analogem Sensor gibt diese Eigenschaft den Wert an, um den gedrückt, linear auf den Bereich von 0.01.0 normalisiert.
  • hapticActuators: ein Array mit GamepadHapticActuator -Objekte, die jeweils Hardware für haptisches Feedback darstellen, die auf dem Controller verfügbar ist.

Je nach Browser und Gamepad können Sie auch auf Folgendes stoßen: ist eine vibrationActuator-Property. Es gibt zwei Arten von Rumble-Effekten:

  • Dual-Rumble: Der haptische Feedback-Effekt, der von zwei exzentrischen rotierenden Masseantrieben erzeugt wird, einer in jedem Griff des Gamepads.
  • Trigger-Rumble: Der haptische Feedback-Effekt, der von zwei unabhängigen Motoren erzeugt wird, wobei sich je ein Motor in jedem Trigger des Gamepads befindet.

Die folgende schematische Übersicht direkt aus den Spezifikationen, zeigt die Kartenzuordnung und die Anordnung der Tasten und Achsen auf einem generischen Gamepad.

<ph type="x-smartling-placeholder">
</ph> Schematische Übersicht der Schaltflächen- und Achsenzuordnungen eines gängigen Gamepads. <ph type="x-smartling-placeholder">
</ph> Visuelle Darstellung eines Standard-Gamepad-Layouts (Quelle)

Benachrichtigung, wenn ein Gamepad verbunden wird

Wenn Sie wissen möchten, wann ein Gamepad verbunden ist, warten Sie auf das gamepadconnected-Ereignis, das beim window-Objekt. Wenn der Nutzer ein Gamepad anschließt, was entweder über USB oder Bluetooth passiert, wird ein GamepadEvent ausgelöst, das die Details des Gamepads in einem passenden gamepad-Attribut enthält. Nachfolgend sehen Sie ein Beispiel eines Xbox 360-Controllers, den ich herumgespielt habe. Retro-Gaming).

window.addEventListener('gamepadconnected', (event) => {
  console.log(' 🎮 A gamepad was connected:', event.gamepad);
  /*
    gamepad: Gamepad
    axes: (4) [0, 0, 0, 0]
    buttons: (17) [GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton]
    connected: true
    id: "Xbox 360 Controller (STANDARD GAMEPAD Vendor: 045e Product: 028e)"
    index: 0
    mapping: "standard"
    timestamp: 6563054.284999998
    vibrationActuator: GamepadHapticActuator {type: "dual-rumble"}
  */
});

Benachrichtigung, wenn die Verbindung zu einem Gamepad getrennt wird

Die Benachrichtigung über Unterbrechungen des Gamepads erfolgt analog zur Erkennung von Verbindungen. Dieses Mal wartet die App auf das Ereignis gamepaddisconnected. Beachten Sie, wie im folgenden Beispiel connected ist jetzt false, wenn ich den Xbox 360-Controller trenne.

window.addEventListener('gamepaddisconnected', (event) => {
  console.log('❌ 🎮 A gamepad was disconnected:', event.gamepad);
  /*
    gamepad: Gamepad
    axes: (4) [0, 0, 0, 0]
    buttons: (17) [GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton]
    connected: false
    id: "Xbox 360 Controller (STANDARD GAMEPAD Vendor: 045e Product: 028e)"
    index: 0
    mapping: "standard"
    timestamp: 6563054.284999998
    vibrationActuator: null
  */
});

Das Gamepad in deiner Spielschleife

Das Abrufen eines Gamepads beginnt mit einem Aufruf von navigator.getGamepads(), der ein Array zurückgibt mit Gamepad Elementen. Das Array in Chrome hat immer eine feste Länge von vier Elementen. Wenn null oder kleiner ist als vier Gamepads verbunden sind, kann ein Artikel nur „null“ sein. Achten Sie immer darauf, alle Punkte der dass sich Gamepads daran erinnern, und sind möglicherweise nicht immer ersten verfügbaren Slot.

// When no gamepads are connected:
navigator.getGamepads();
// (4) [null, null, null, null]

Wenn ein oder mehrere Gamepads verbunden sind, navigator.getGamepads() aber immer noch null Elemente meldet, musst du eventuell „aufwecken“ indem Sie eine beliebige Taste drücken. Anschließend können Sie das Gamepad abfragen wie im folgenden Code dargestellt:

const pollGamepads = () => {
  // Always call `navigator.getGamepads()` inside of
  // the game loop, not outside.
  const gamepads = navigator.getGamepads();
  for (const gamepad of gamepads) {
    // Disregard empty slots.
    if (!gamepad) {
      continue;
    }
    // Process the gamepad state.
    console.log(gamepad);
  }
  // Call yourself upon the next animation frame.
  // (Typically this happens every 60 times per second.)
  window.requestAnimationFrame(pollGamepads);
};
// Kick off the initial game loop iteration.
pollGamepads();

Vibrationsbetätiger

Das Attribut vibrationActuator gibt ein GamepadHapticActuator-Objekt zurück, das einem Konfiguration von Motoren oder anderen Bedienelementen, die eine Kraft zum Zweck der Haptik anwenden können Feedback geben. Haptische Effekte können durch Aufrufen von Gamepad.vibrationActuator.playEffect() abgespielt werden. Die einzige Gültige Effekttypen sind 'dual-rumble' und 'trigger-rumble'.

Unterstützte Rumble-Effekte

if (gamepad.vibrationActuator.effects.includes('trigger-rumble')) {
  // Trigger rumble supported.
} else if (gamepad.vibrationActuator.effects.includes('dual-rumble')) {
  // Dual rumble supported.
} else {
  // Rumble effects aren't supported.
}

Doppeltes Ruckeln

„Dual-rumble“ beschreibt eine haptische Konfiguration mit einem Exzentrische rotierende Massenvibration an jedem Griff eines Standard-Gamepads Bei dieser Konfiguration können beide Motoren das gesamte Gamepad vibrieren. Die beiden Massen sind ungleich, können miteinander kombiniert werden, um komplexere haptische Effekte zu erzeugen. Dual-Rumble-Effekte durch vier Parameter definiert:

  • duration: legt die Dauer des Vibrationseffekts in Millisekunden fest.
  • startDelay: Legt die Dauer der Verzögerung bis zum Einsetzen der Vibration fest.
  • strongMagnitude und weakMagnitude: Stellen Sie die Vibrationsintensität auf das leichtere exzentrische rotierende Massenmotoren, normalisiert auf den Bereich von 0.01.0.
// This assumes a `Gamepad` as the value of the `gamepad` variable.
const dualRumble = (gamepad, delay = 0, duration = 100, weak = 1.0, strong = 1.0) => {
  if (!('vibrationActuator' in gamepad)) {
    return;
  }
  gamepad.vibrationActuator.playEffect('dual-rumble', {
    // Start delay in ms.
    startDelay: delay,
    // Duration in ms.
    duration: duration,
    // The magnitude of the weak actuator (between 0 and 1).
    weakMagnitude: weak,
    // The magnitude of the strong actuator (between 0 and 1).
    strongMagnitude: strong,
  });
};

Trigger-Rumble

Das Trigger-Rumble ist der haptische Feedback-Effekt, der von zwei unabhängigen Motoren erzeugt wird, wobei sich je ein Motor in jedem Trigger des Gamepads befindet.

// This assumes a `Gamepad` as the value of the `gamepad` variable.
const triggerRumble = (gamepad, delay = 0, duration = 100, weak = 1.0, strong = 1.0) => {
  if (!('vibrationActuator' in gamepad)) {
    return;
  }
  // Feature detection.
  if (!('effects' in gamepad.vibrationActuator) || !gamepad.vibrationActuator.effects.includes('trigger-rumble')) {
    return;
  }
  gamepad.vibrationActuator.playEffect('trigger-rumble', {
    // Duration in ms.
    duration: duration,
    // The left trigger (between 0 and 1).
    leftTrigger: leftTrigger,
    // The right trigger (between 0 and 1).
    rightTrigger: rightTrigger,
  });
};

Integration in Berechtigungsrichtlinie

Die Gamepad API-Spezifikation definiert eine richtliniengesteuerte Funktion des String "gamepad". Der Standardwert für allowlist ist "self". Die Berechtigungsrichtlinie eines Dokuments legt fest, ob Inhalte in diesem Dokument auf navigator.getGamepads() zugreifen dürfen. Wenn deaktiviert in in keinem Dokument verwendet werden darf, darf navigator.getGamepads() weder verwendet noch werden die Ereignisse gamepadconnected und gamepaddisconnected ausgelöst.

<iframe src="index.html" allow="gamepad"></iframe>

Demo

Im folgenden Beispiel ist eine Gamepad-Tester-Demo eingebettet. Quellcode ist bei Glitch verfügbar. Testen Sie die Demo, indem Sie eine Verbindung zu einem über USB oder Bluetooth und das Drücken einer beliebigen Taste oder das Verschieben einer Achse.

Bonus: Chrome-Dino auf web.dev spielen

Sie können auf diesem Gamepad mit Chrome Dino spielen auf meiner Website. Der Quellcode ist auf GitHub verfügbar. Testen Sie die Gamepad-Polling-Implementierung in trex-runner.js und achten Sie darauf, wie Tastendruck emuliert wird.

Damit die Demo des Chrome-Dino-Gamepads funktioniert, habe ich das Chrome-Dino-Spiel aus dem Chromium-Kernprojekt herausrissen (durch Aktualisierung eines früheren Aufwand durch Arnelle Ballane platzierte sie auf einer eigenständigen Website, vorhandene Gamepad-API-Implementierung durch Hinzufügen von Ducking- und Vibrationseffekten, erstellten eine Vollbild- und Mehul Satardekar einen dunklen Modus Implementierung. Viel Spaß beim Spielen!

Danksagungen

Dieses Dokument wurde von François Beaufort geprüft und Joe Medley. Die Gamepad API-Spezifikation wird von Steve Agoston James Hollyer und Matt Reynolds Die ehemaligen Spezifikationseditoren Brandon Jones, Scott Graham und Ted Mielczarek Die Spezifikation für Gamepad-Erweiterungen wird bearbeitet von Brandon Jones. Hero-Image von Laura Torrent Puig.