Přejít k navigační liště

Zdroják » JavaScript » Když na webové hry, tak s gamepadem

Když na webové hry, tak s gamepadem

Články JavaScript

Gamepady a webové prohlížeče? Proč ne. V článku vám představíme specifikaci Gamepad API a ukážeme, jak (snad) bude běžné v budoucnu ovládat webové hry.

Období vánočních svátků je pryč. Možná někdo z vás dostal herní konzoli. A možná se zamyslel, zda jde takovým  prímovým gejmpédem ovládat hry z éry JavaScriptu a HTML5. Dnešní článek vám na tuhle otázku odpoví. A na konci najdete i malé demo, kde si můžete váš gamepad odzkoušet.

Tento článek je zkráceným překladem článku The Gamepad API od Teda Mielczarka a Roberta Nymana a je uveden pod licencí CC BY-SA 3.0.

Videohry mě fascinovaly už od mala a strávil jsem u nich hromady hodin. Sleduji rostoucí popularitu webových her a věřím, že to signalizuje příchod nové éry hraní s hromadou her dostupných velkému počtu uživatelů. Během zkoušení webových her jsem si říkal, že řada z nich by se přece lépe ovládala gamepadem! Pustil jsem se do implementace ve Firefoxu. A tak se zrodilo Gamepad API.

gamepads

Dejte API zelenou

Od Firefoxu 24 je Gamepad API dostupné skrze předvolby. Můžete ho povolit na  about:config nastavením předvolby dom.gamepad.enabled na true. Noční verze Aurora verze Firefoxu mají API již zapnuté. Předpokládáme, že od verze Firefox 28 bude API standardně zapnuté.

Používání API

Gamepad API je už od návrhu jednoduché. Specifikace popisuje pouze rozhraní pro práci s tradičními ovládacími prvky gamepadů — sadou tlačítek a křížovým ovládáním. To by mělo pokrýt většinu herních ovladačů na trhu a zároveň se vyhneme zbytečným složitostem ve snaze specifikovat vše, co existuje. API obsahuje jedno volání funkce, několik DOM událostí a jeden typ objektu.

Šup sem s gamepadem

Gamepad nebude pro webovou stránku viditelný, dokud s ním uživatel nezačne nad otevřenou stánkou pracovat. To pro ochranu soukromí, hlavně jako ochrana před použitím pro fingerprinting uživatelského systému. Jakmile se uživatel chopí ovladače (tj. stiskne tlačítko nebo pohne pákou) a pokud je stránka současně viditelná, bude vyvolána událost gamepadconnected.

Objekt GamepadEvent má vlastnost gamepad, která popisuje připojené zařízení. Ve Firefoxu platí, jakmile začne být jeden gamepad pro stránku viditelný, tak připojení jakéhokoliv dalšího gamepadu (přes USB nebo Bluetooth) okamžitě zpřístupní i tento gamepad stránce a vyvolá událost gamepadconnected.

window.addEventListener("gamepadconnected", function(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);
});

Gamepad API obsahuje jednu funkci a sice navigator.getGamepads(), která vrátí seznam stránce viditelných gamepadů.

var gamepad_count = 0;
function pollGamepads() {
  var gamepads = navigator.getGamepads();
  if (gamepads.length != gamepad_count) {
    gamepad_count = gamepads.length;
    for (var i = 0; i < gamepads.length; i++) {
      console.log("Gamepad %d: %s. %d buttons, %d axes",
        i, gamepads[i].id,
        gamepads[i].buttons.length, gamepads[i].axes.length);
    }
  }
}
setInterval(pollGamepads, 100);

Pozn.: tenhle kód funguje až v nočních verzích Firefoxu 28, ve starších byl bug.

Pokud je gamepad odpojen, vyvolá se událost gamepaddisconnected.  Pokud jste si uložili odkaz na objekt Gamepad, bude mít od téhle chvíle nastavenou vlastnost connected na false.

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

Objekt Gamepad

Objekt Gamepad obsahuje stav herního zařízení. Najdete u něj tyto vlastnosti:

  • id – řetězec obsahující informace o ovladači. Jeho hodnota není přesně specifikována, ve Firefoxu je složen ze tří částí oddělených pomlčkou (-): dva 4ciferné hexadecimální řetězce obsahující USB vendor a product id ovladače a název ovladače; tato informace slouží jako feedback uživateli.
  • index – celé číslo, jedinečné pro každý připojený ovladač, umožňující rozlišit mezi více ovladači.
  • connected – boolean: true, když je ovladač připojen, false když byl odpojen.
  • mapping – řetězec signalizující, zda prohlížeč namapoval ovládací prvky zařízení na jemu známý layout. V této chvíli existuje pouze jeden podporovaný známý layout “standard gamepad“. Pokud prohlížeč ovládací prvky namapoval, bude vlastnost mapping nastavena na řetězec standard.
  • axes – pole hodnot s plovoucí desetinnou čárkou obsahující stav všech křížových ovládacích prvků zařízení. Obvykle se jedná o analogové páky, jejichž poloha je udávána pozicí dle os X a Y. Obě osy jsou normalizovány na rozmezí -1.0..1.0, kde -1.0 zastupuje maximální horní nebo levou polohu a 1.0 zastupuje maximální dolní nebo pravou polohu.
  • buttons – pole objektů GamepadButton obsahující stav všech tlačítek zařízení. Každý GamepadButton má vlastnosti pressedvalue. Vlastnost pressed je logická hodnota signalizující, zda je tlačítko aktuálně stisknuto (true) nebo ne (false). Vlastnost value je číslo s plovoucí desetinnou čárkou zastupující analogová tlačítka typu spoušť na řadě moderních gamepadů. Jejich hodnoty jsou normalizovány na rozmezí 0.0..1.0, kde 0.0 zastupuje nestisknuté tlačítko a 1.0 zastupuje plně stisknuté tlačítko.

Kompatibilita mezi prohlížeči

Specifikace Gamepad API byla implementovaná ve Firefoxu a Chromu a tyto implementace jsou kompatibilní jen do jisté míry. Firefox momentálně implementoval kompletní editorský draft specifikace kromě vlastnosti timestamp objektu Gamepad.

V době psaní toho článku (prosinec 2013) prohlížeč Chrome neimplementoval události ongamepadconnected a ongamepaddisconnected. Pro přístup k herním ovladačům musíte zavolat funkci navigator.webkitGetGamepads() (nezapomeňte na prefix).

Dalším rozdílem je, že objekty Gamepad v Chromu vyjadřují snapshoty, zatímco ve Firefoxu obsahují vždy nejnovější stav ovládacích prvků. To znamená, že ve Chromu musíte stav tlačítek získávat opakovaným voláním navigator.webkitGetGamepads(), zatímco ve Firefoxu stačí, když si podržíte referenci na objekt Gamepad.

A do třetice, nedávná změna specifikace způsobila, že Chrome a zveřejněné verze Firefoxu se od Firefoxu 28 trochu liší — vlastnost buttons objektu Gamepad byla původně specifikována jako objekt hodnot double a nikoliv jako pole objektů GamepadButton. To můžete ošetřit touto kontrolou:

function listButtons(gamepad) {
  for (var i = 0; i < gamepad.buttons.length; i++) {
      var b = gamepad.buttons[i];
      var pressed, val;
      if (typeof(b) == "object") {
        pressed = b.pressed;
        val = b.value;
      } else {
        val = b;
        pressed = b == 1.0;
      }
      console.log("Button %d: %s (%f)", i, pressed ? "pressed" : "not pressed", val);
  }
}

Jednoduché demo

Následuje jednoduché demo, které dává všechny střípky dohromady a ukazuje, jak dnes můžete použít Gamepad API napříč prohlížeči. Jednoduše zobrazuje stav ovládacích prvků připojených gamepadů. Demo by mělo fungovat ve všech verzích Firefox od verze 24 výše a v Chromu od verze 21. Zdrojový kód najdete na Githubu.

Doufám, že vás tento článek inspiroval. A vytvořte nějaké hry!

gamepadtest-250x143

Komentáře

Subscribe
Upozornit na
guest
4 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Šimoník Dušan

Ve Firefoxu funguje, ale v Google Chrome Verze 33.0.1750.117 m mi nefunguje ani nevím kde to povolit. V chrome://flags/ jsem nic nenašel :(

Šimoník Dušan

Ve verzi Verze 34.0.1847.3 dev-m již fungje.dš

Viktor

Ahoj může někdo doporučit nějaké ty hry které se dají hrát nebo stránky kde jsou ty nej hry ?

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.

Pocta C64

Za prvopočátek své programátorské kariéry vděčím počítači Commodore 64. Tehdy jsem genialitu návrhu nemohl docenit. Dnes dokážu lehce nahlédnout pod pokličku. Chtěl bych se o to s vámi podělit a vzdát mu hold.