Jouez au jeu du dinosaure avec votre manette de jeu Chrome

Découvrez comment utiliser l'API Gamepad pour faire passer vos jeux Web au niveau supérieur.

L'easter egg de la page hors connexion de Chrome est l'un des secrets les moins gardés de l'histoire ([citation needed], mais la déclaration faite pour l'effet dramatique). Si vous appuyez sur la touche Espace ou, sur un appareil mobile, appareils, appuyez sur le dinosaure, la page hors connexion devient un jeu d'arcade jouable. Vous savez peut-être que Vous n'avez pas besoin de vous déconnecter quand vous voulez jouer. Dans Chrome, il vous suffit de naviguer à about://dino ou, si vous êtes un geek, d'accéder à about://network-error/-106. Mais saviez-vous qu'il existe 270 millions de jeux de dinosaures sur Chrome joués chaque mois ?

<ph type="x-smartling-placeholder">
</ph> Page hors connexion de Chrome avec le jeu du dinosaure de Chrome. <ph type="x-smartling-placeholder">
</ph> Appuyez sur la barre d'espace pour jouer !

Un autre fait sans doute plus utile à savoir et dont vous n'êtes peut-être pas conscient est que dans mode arcade, vous pouvez jouer avec une manette. La prise en charge des manettes de jeu a été ajoutée il y a environ un an de la rédaction de cet article commit par Reilly Grant. Comme vous pouvez le voir, le jeu, comme le reste Chromium, est entièrement Open Source. Dans ce post, je veux vous montrer comment utiliser l'API Gamepad.

Utiliser l'API Gamepad

Détection de fonctionnalités et compatibilité avec les navigateurs

L'API Gamepad est parfaitement compatible avec les navigateurs, à la fois ordinateurs et mobiles. Vous pouvez vérifier si l'API Gamepad est compatible à l'aide de l'extrait de code suivant:

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

Comment le navigateur représente une manette de jeu

Le navigateur représente les manettes de jeu sous la forme Gamepad. d'objets. Un Gamepad a les propriétés suivantes:

  • id: chaîne d'identification de la manette de jeu. Cette chaîne identifie la marque ou le style manette de jeu connectée.
  • displayId: le VRDisplay.displayId d'un VRDisplay associé (le cas échéant).
  • index: index de la manette de jeu dans le navigateur
  • connected: indique si la manette de jeu est toujours connectée au système.
  • hand: énumération définissant la main dans laquelle la manette est tenue ou qu'elle est le plus susceptible de tenir. po.
  • timestamp: date de la dernière mise à jour des données de cette manette.
  • mapping: mappage du bouton et des axes utilisé pour cet appareil ("standard" ou "xr-standard"
  • pose: objet GamepadPose représentant les informations de pose associées à un contrôleur WebVR.
  • axes: tableau de valeurs pour tous les axes de la manette de jeu, normalisé linéairement dans la plage des -1.01.0.
  • buttons: tableau des états de tous les boutons de la manette de jeu.

Notez que les boutons peuvent être numériques (enfoncé ou non) ou analogiques (par exemple, 78% de la pression). Ce C'est pourquoi les boutons sont signalés en tant qu'objets GamepadButton, avec les attributs suivants:

  • pressed: état du bouton (true si l'utilisateur a appuyé dessus et false) si ce n'est pas le cas.
  • touched: état d'appui sur le bouton. Si le bouton est capable de détecter une pression tactile, est true si un utilisateur appuie sur le bouton, et false dans le cas contraire.
  • value: pour les boutons équipés d'un capteur analogique, cette propriété représente la quantité de données a appuyé sur le bouton, normalisé de manière linéaire dans la plage comprise entre 0.0 et 1.0.
  • hapticActuators: tableau contenant GamepadHapticActuator des objets, chacun représentant le matériel de retour haptique disponible sur le contrôleur.

Une autre chose que vous pourriez rencontrer, selon votre navigateur et votre manette de jeu, est une propriété vibrationActuator. Il permet deux types d'effets de rumble:

  • Dual-Rumble: effet de retour haptique généré par deux actionneurs en masse rotatifs excentriques, un dans chaque prise de la manette de jeu.
  • Déclencheur/Rumble: effet de retour haptique généré par deux moteurs indépendants, chacun des déclencheurs de la manette de jeu.

La présentation schématique suivante, prise d'après les spécifications, montre la mise en correspondance et la disposition des boutons et des axes sur une manette de jeu générique.

<ph type="x-smartling-placeholder">
</ph> Schéma des mappages des boutons et des axes d&#39;une manette de jeu courante. <ph type="x-smartling-placeholder">
</ph> Représentation visuelle d'une disposition de manette de jeu standard (Source).

Notification lorsqu'une manette de jeu est connectée

Pour savoir quand une manette de jeu est connectée, écoutez l'événement gamepadconnected qui se déclenche sur la window. Lorsque l'utilisateur connecte une manette de jeu, ce qui peut se produire via USB ou Bluetooth, Déclenchement d'une GamepadEvent contenant les détails de la manette dans une propriété gamepad bien nommée. L'exemple suivant illustre une manette Xbox 360 que je me suis laissée traîner (oui, je suis dans les jeux rétro).

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"}
  */
});

Notification lorsqu'une manette de jeu est déconnectée

La réception d'une notification en cas de déconnexion de la manette de jeu se fait de la même manière que la détection des connexions. Cette fois, l'application écoute l'événement gamepaddisconnected. Notez que dans l'exemple suivant, connected est maintenant false lorsque je débranche la manette Xbox 360.

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
  */
});

La manette de jeu dans votre boucle de jeu

L'obtention d'une manette de jeu commence par un appel à navigator.getGamepads(), qui renvoie un tableau avec Gamepad éléments. Le tableau dans Chrome a toujours une longueur fixe de quatre éléments. Si zéro ou une valeur inférieure que quatre manettes de jeu sont connectées, un élément peut simplement avoir la valeur null. Assurez-vous toujours de vérifier tous les éléments de le tableau et gardez à l'esprit que les manettes de jeu leur emplacement et ne sont pas toujours présents le premier emplacement disponible.

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

Si une ou plusieurs manettes de jeu sont connectées, mais que navigator.getGamepads() signale toujours null éléments, vous devrez peut-être "réactiver" chaque manette en appuyant sur l'un de ses boutons. Vous pouvez ensuite interroger la manette dans votre boucle de jeu, comme illustré dans le code suivant.

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();

L'actionneur des vibrations

La propriété vibrationActuator renvoie un objet GamepadHapticActuator, qui correspond à une configuration de moteurs ou autres actionneurs pouvant appliquer une force pour le retour haptique commentaires. Vous pouvez exécuter des effets haptiques en appelant Gamepad.vibrationActuator.playEffect(). La seule les types d'effets valides sont 'dual-rumble' et 'trigger-rumble'.

Effets de rumble compatibles

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.
}

Double rumble

Le double rumble décrit une configuration haptique avec une moteur vibrant à masse rotative excentrique sur chaque poignée d'une manette de jeu standard. Dans cette configuration, l’un ou l’autre des moteurs est capable de faire vibrer l’ensemble de la manette de jeu. Les deux masses sont inégales, les effets de chacun d'eux peuvent être combinés pour créer des effets haptiques plus complexes. Les effets de double vibration sont défini par quatre paramètres:

  • duration: définit la durée de l'effet de vibration en millisecondes.
  • startDelay: définit le délai avant le déclenchement du vibreur.
  • strongMagnitude et weakMagnitude: définissez l'intensité des vibrations pour les moteurs à masse rotatif excentriques plus légers, normalisés dans la plage 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,
  });
};

Déclenchement du grondement

Le bruit de fond correspond au retour haptique généré par deux moteurs indépendants, chacun des déclencheurs de la manette de jeu.

// 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,
  });
};

Intégration avec les règles d'autorisation

Les spécifications de l'API Gamepad définissent fonctionnalité contrôlée par des règles identifiée par le chaîne "gamepad". Sa valeur par défaut (allowlist) est "self". La stratégie d'autorisations d'un document détermine si certains contenus de ce document sont autorisés à accéder à navigator.getGamepads(). Si désactivé dans n'importe quel document, aucun contenu ne sera autorisé à utiliser navigator.getGamepads(), et les événements gamepadconnected et gamepaddisconnected se déclenchent.

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

Démo

Une démo de testeur de manette de jeu est intégrée dans l'exemple suivant. Le code source est disponible sur Glitch. Essayez la version de démonstration en connectant un manette de jeu via USB ou Bluetooth et en appuyant sur l'un de ses boutons ou en déplaçant n'importe quel axe.

Bonus: Jouez au dinosaure de Chrome sur web.dev

Vous pouvez jouer au dino de Chrome avec votre manette sur ce sur le site. Le code source est disponible sur GitHub. Découvrez l'implémentation de l'interrogation de manette de jeu dans trex-runner.js et notez comment il émule les pressions sur les touches.

Pour que la démo de la manette de jeu avec le dinosaure de Chrome fonctionne, a éliminé le jeu du dinosaure de Chrome du projet Chromium principal (mise à jour d'un d'efforts en amont en Arnelle Ballane), l'a placée sur un site autonome, a étendu l'implémentation existante de l'API pour manette de jeu en ajoutant des effets d'atténuation et de vibration, créé un mode plein écran et Mehul Satardekar a contribué au mode sombre la mise en œuvre. Amusez-vous bien !

Remerciements

Ce document a été révisé par François Beaufort et Joe Medley La spécification de l'API Gamepad est modifiée par Steve Agoston, James Hollyer et Matt Reynolds Les anciens éditeurs de spécifications Brandon Jones, Scott Graham et Ted Mielczarek La spécification des extensions Gamepad est modifiée par Brandon Jones. Image principale par Laura Torrent Puig.