Graj w grę z dinozaurem w Chrome na padzie do gier

Dowiedz się, jak używać interfejsu Gamepad API, aby tworzyć jeszcze lepsze gry internetowe.

Ukryta strona offline w Chrome to jeden z najgorzej strzeżonych sekretów historii ([citation needed], ale roszczenie dotyczące efektu dramatycznego). Jeśli naciśniesz klawisz spacji lub naciśniesz przycisk na urządzeniu mobilnym na urządzeniach mobilnych, kliknij dinozaura, a strona offline stanie się grą zręcznościową. Być może wiesz, że nie musisz przechodzić do trybu offline, gdy chcesz grać. W Chrome możesz do about://dino, a dla entuzjastów tej dziedziny wejdź na about://network-error/-106. Czy wiesz, że... że istnieje 270 milionów gier z dinozaurami w Chrome każdego miesiąca?

Strona offline w Chrome z grą z dinozaurem w Chrome.
Aby zagrać, naciśnij spację.

Kolejnym faktem, który prawdopodobnie przydaje się bardziej, a których możemy nie być świadomi, jest fakt, w trybie zręcznościowym możesz grać za pomocą pada do gier. Obsługę padów do gier dodano mniej więcej rok temu jako w czasie tego pisania – commit przez Reilly Grant Jak widać, gra, podobnie jak reszta Projekt Chromium jest pełny open source. W W tym poście pokażę, jak korzystać z interfejsu Gamepad API.

Używanie interfejsu Gamepad API

Wykrywanie funkcji i obsługa przeglądarki

Interfejs Gamepad API zapewnia uniwersalnie doskonałą obsługę przeglądarek w obu tych usługach. komputerach i urządzeniach mobilnych. Aby sprawdzić, czy interfejs Gamepad API jest obsługiwany, użyj tego fragmentu kodu:

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

Sposób, w jaki przeglądarka reprezentuje pada do gier

Przeglądarka wyświetla pady do gier jako Gamepad obiektów. Element Gamepad ma te właściwości:

  • id: ciąg identyfikujący pad do gier. Ten ciąg określa markę lub styl połączonego pada do gier.
  • displayId: VRDisplay.displayId z powiązany element VRDisplay (w odpowiednich przypadkach).
  • index: indeks pada do gier w nawigatorze.
  • connected: wskazuje, czy pad do gier jest nadal połączony z systemem.
  • hand: wyliczenie określające, którą rękę trzyma lub najprawdopodobniej trzyma kontroler cal
  • timestamp: ostatnia aktualizacja danych tego pada do gier.
  • mapping: mapowanie przycisku i osie na tym urządzeniu ("standard" lub "xr-standard"
  • pose: obiekt GamepadPose reprezentujących informacje o pozycji powiązane z kontrolerem WebVR.
  • axes: tablica wartości wszystkich osi pada do gier, znormalizowana liniowo do zakresu -1.01.0.
  • buttons: tablica stanów wszystkich przycisków na padzie do gier.

Pamiętaj, że przyciski mogą być cyfrowe (naciśnięte lub nienaciśnięte) lub analogowe (na przykład wciśnięte 78%). Ten dlatego przyciski są raportowane jako obiekty GamepadButton z tymi atrybutami:

  • pressed: stan kliknięcia przycisku (true, jeśli jest naciśnięty, oraz false). , jeśli nie jest naciśnięty.
  • touched: stan kliknięcia przycisku. Jeśli przycisk wykrywa dotyk, właściwość to true, jeśli użytkownik dotyka przycisku, lub false w innym przypadku.
  • value: w przypadku przycisków z czujnikiem analogowym ta właściwość reprezentuje ilość, o jaką wartość naciśnięto przycisk z liniową normalizacją do zakresu 0.01.0.
  • hapticActuators: tablica zawiera GamepadHapticActuator. z których każdy reprezentuje sprzęt do reakcji haptycznej dostępny na kontrolerze.

W zależności od przeglądarki i posiadanego pada do gier możesz napotkać jeszcze jedną rzecz, to właściwość vibrationActuator. Pozwala uzyskać 2 rodzaje efektów uderzenia:

  • Dual-Rumble: efekt reakcji haptycznej generowany przez dwa ekscentryczne obrotowe silniki masowe, po jednym na każdym uchwytie pada do gier.
  • Wiatrówka: efekt reakcji haptycznych generowany przez 2 niezależne silniki, z którym jeden jest umieszczony w każdym z spustów pada do gier.

Oto omówienie schematu, wzięte prosto ze specyfikacji, pokazuje mapowanie oraz rozmieszczenie przycisków i osi na standardowym padzie do gier.

Schemat mapowania przycisków i osi popularnych padów do gier.
Wizualny układ standardowego pada do gier (Źródło).

Powiadomienie o połączeniu pada do gier

Żeby dowiedzieć się, kiedy pad do gier jest podłączony, nasłuchuj zdarzenia gamepadconnected, które uruchamia się na urządzeniu window obiekt. Gdy użytkownik podłącza pad do gier, co może odbywać się przez USB lub Bluetooth, uruchamiany jest skrypt GamepadEvent, który zawiera szczegóły pada do gier we właściwości gamepad o odpowiedniej nazwie. Poniżej widać przykład kontrolera Xbox 360, który leży mi pod ręką (tak, bardzo mi się to podoba). gry retro).

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

Powiadomienie o odłączeniu pada do gier

Powiadomienia o odłączeniu pada do gier mogą być wysyłane analogicznie jak do sposobu wykrywania połączeń. Tym razem aplikacja nasłuchuje zdarzenia gamepaddisconnected. Zwróć uwagę, jak w przykładzie poniżej Gdy odłączę kontroler Xbox 360, connected ma teraz wartość false.

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

Pad do gier w pętli gry

Przytrzymanie pada do gier rozpoczyna się od wywołania navigator.getGamepads(), które zwraca tablicę z Gamepad elementami. Tablica w Chrome zawsze ma stałą długość 4 elementów. Jeśli wynosi 0 lub mniej Jeśli masz więcej niż 4 pady do gier, jeden przedmiot może mieć tylko null. Zawsze sprawdzaj wszystkie elementy i pamiętaj, że pady do gier „zapamiętują” i nie zawsze może być obecny w pierwszego dostępnego miejsca.

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

Jeśli jest połączonych co najmniej 1 pad do gier, ale navigator.getGamepads() nadal zgłasza null elementów, być może trzeba się „wybudzić” przez naciśnięcie dowolnego z przycisków. Następnie możesz przeprowadzić ankietę na padzie do gier w pętli gry, jak widać w tym kodzie.

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

Element wibracyjny

Właściwość vibrationActuator zwraca obiekt GamepadHapticActuator, który odpowiada konfiguracja silników lub innych urządzeń wykonawczych mogących generować siłę oddziaływania na potrzeby reakcji haptycznych. opinie. Efekty haptyczne można odtwarzać, wywołując funkcję Gamepad.vibrationActuator.playEffect(). Jedyna prawidłowe typy efektów to 'dual-rumble' i 'trigger-rumble'.

Obsługiwane efekty uderzenia

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

Dwa uderzenia

Dzwonek podwójny opisuje konfigurację haptyczną z ekscentryczny, obrotowy silnik wibracyjny w każdym uchuku standardowego pada do gier. W tej konfiguracji Każdy z silników może wibrować cały pad do gier. Te dwie masy są nierówne, więc które można łączyć, aby uzyskać bardziej złożone efekty haptyczne. Efekty podwójnych dźwięków są definiowane przez 4 parametry:

  • duration: ustawia czas trwania efektu wibracji w milisekundach.
  • startDelay: ustawia czas opóźnienia do uruchomienia wibracji.
  • strongMagnitude i weakMagnitude: ustaw poziomy intensywności wibracji dla lżejsze ekscentryczne silniki obrotowe znormalizowane do zakresu 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,
  });
};

Uderzenie spustu

Wibracja to efekt reakcji haptycznej generowany przez 2 niezależne silniki, z których jeden znajduje się w każdym ze spustów pada do gier.

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

Integracja z zasadami dotyczącymi uprawnień

Specyfikacja interfejsu Gamepad API definiuje funkcję podlegającą zasadom zidentyfikowaną przez ciąg "gamepad". Jej domyślna wartość allowlist to "self". Zasada uprawnień dokumentu określa, czy jakakolwiek treść tego dokumentu może uzyskać dostęp do navigator.getGamepads(). Jeśli wyłączono w w dowolnym dokumencie, żadna treść nie będzie mogła korzystać z tagu navigator.getGamepads() ani są uruchamiane zdarzenia gamepadconnected i gamepaddisconnected.

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

Prezentacja

Poniżej znajdziesz przykładową wersję demonstracyjną testowania pada do gier. Kod źródłowy jest dostępna w usłudze Glitch. Wypróbuj wersję demonstracyjną, podłączając pad do gier przez USB lub Bluetooth i naciskając dowolny przycisk lub poruszając dowolną osią.

Dodatkowo: zagraj w dinozaura w Chrome na web.dev

Na tym padzie do gier możesz grać w dinozaura w Chrome tę witrynę. Kod źródłowy jest dostępny na GitHubie. Zapoznaj się z implementacją ankiet na padzie do gier w: trex-runner.js i zwróć uwagę, jak emuluje naciśnięcia klawiszy.

Aby działała wersja demonstracyjna pada do gier z dinozaurem w Chrome, wyjął grę z dinozaurem w Chrome z podstawowego projektu Chromium (aktualizacja wcześniejsze wysiłki o Arnelle Ballane), umieściła ją w osobnej witrynie, rozszerzyła wdrożenie interfejsu API do gier, dodając efekt wyciszania tła i wibracji, a Mehul Satardekar udostępnił tryb ciemny. implementacji. Powodzenia!

Podziękowania

Ten dokument został sprawdzony przez François Beaufort i Joe Medley Specyfikacja interfejsu Gamepad API jest edytowana przez Steve Agoston James Hollyer Matt Reynolds Dawni edytujący specyfikację Brandon Jones, Scott Graham i Ted Mielczarek. Specyfikację rozszerzeń do gier edytował(a) kontroler do gier Brandon Jones Zdjęcie bohatera autorstwa Laury Torrent Puig.