Folosind API-ul gamepad-ului HTML5 pentru a adăuga suportul controlerului la jocurile browser-ului

Pe măsură ce jocurile pe bază de web devin mai populare, unul dintre cele mai mari puncte de acces pentru jucători este controlul de intrare. În timp ce primele mele jocuri FPS aveau bazate exclusiv pe mouse și tastatură, acum m-am mult mai obișnuit cu un controler consola propriu-zis, pe care l-aș folosi mai degrabă pentru tot, inclusiv jocuri pe bază de web. 

Din fericire, API-ul Gamepad HTML5 există pentru a permite dezvoltatorilor web accesul programabil la controlorii de jocuri. Din nefericire, deși acest API a fost pe o perioadă lungă de timp, se mișcă încet doar în cele mai recente versiuni de browsere desktop. Ea a dispărut mult timp într-o singură construcție de Firefox (nu una construiește mai mult, nimeni nu se mai construiește noapte de noapte construi) și a fost problematică în Chrome. Acum este - bine - nu perfectă, dar puțin mai puțin problematică și de fapt destul de ușor de folosit. 

În acest articol, voi discuta despre diferitele caracteristici ale API-ului, despre modul în care funcționează atât în ​​Firefox, cât și în Chrome și va afișa un joc real (dacă este simplu) și cât de ușor este să adăugați suportul gamepad-ului pentru acesta.

Cele elementare

API-ul Gamepad cuprinde următoarele caracteristici:

  • Capacitatea de a asculta conectați și deconecta evenimente.
  • Abilitatea de a recunoaște mai multe gamepad-uri. (Teoretic, ați putea conecta cât mai multe gamepad-uri pe măsură ce aveți porturi USB.)
  • Abilitatea de a inspecta aceste gamepad-uri și de a recunoaște numărul de axe pe care le au (joystick-uri), cât de multe butoane au (ați jucat recent o consolă de jocuri?) Și ce state fiecare dintre aceste elemente individuale sunt.

Să începem prin a discuta cum puteți detecta suportul pentru un gamepad la un nivel înalt. 

Atât Firefox cât și Chrome acceptă o metodă navigator, getGamepads (), care returnează o gamă largă de dispozitive de joc conectate. Putem folosi aceasta ca o simplă metodă de detectare a prezenței API-ului Gamepad. Iată o funcție simplă pentru verificarea respectivă:

funcția canGame () return "getGamepads" în navigator; 

Până acum, bine. Acum pentru partea funky. API-ul Gamepad are suport pentru evenimente care detectează când un gamepad este conectat și deconectat. Dar ce se întâmplă dacă utilizatorul are deja un gamepad conectat la laptopul lor când a lovit pagina dvs.? În mod normal, pagina web va aștepta ca utilizatorul să facă ceva, ceva cu adevărat, cu jocul real. Acest lucru înseamnă că trebuie să furnizăm un anumit tip de mesaj utilizatorului, care îi permite să știe că trebuie să-și "trezească" suportul pentru gamepad dacă acesta este conectat. Le-ai putea spune să lovească orice buton sau să muște un băț. 

Pentru a face lucrurile și mai interesante, acest control special nu pare să fie necesar când reîncărcați pagina. Veți descoperi că, odată ce ați folosit API-ul Gamepad pe o pagină și apoi l-ați reîncărcat, pagina va recunoaște acest fapt și va considera automat conexiunea.

Dar așteptați - se face mai bine. Chrome nu acceptă evenimentele conectate (sau deconectate) în acest moment. Activitatea tipică pentru acest lucru (și cea demonstrată în documentele MDN bune pentru API) este de a stabili un sondaj și de a vedea dacă un gamepad "apare" în lista de dispozitive conectate.

Derutant? Să începem cu un exemplu care suportă numai Firefox:

           

În exemplul de mai sus, începem să verificăm dacă browserul acceptă API-ul Gamepad. Dacă se întâmplă acest lucru, actualizăm mai întâi o div cu instrucțiuni pentru utilizator și apoi începem să ascultăm imediat ambele conectați și deconecta evenimente. 

Dacă rulați acest lucru cu Firefox și conectați gamepad-ul dvs., ar trebui să apăsați apoi un buton, moment în care evenimentul este declanșat și sunteți gata să plecați. 

Din nou, însă, în testarea mea, când reîncarc pagina, conexiune evenimentul este imediat. Acest lucru creează un efect ușor de "flicker", care poate fi nedorit. S-ar putea să folosiți un interval pentru a seta instrucțiunile pentru ceva de genul 250ms după ce DOM-ul a fost încărcat și numai prompt dacă o conexiune nu a avut loc între timp. Am decis să păstrez lucrurile simple pentru acest tutorial.

Codul nostru funcționează pentru Firefox, dar acum să adăugăm suport pentru Chrome:

           

Codul este un pic mai complex acum, dar nu atât de groaznic. Încărcați demo-ul în Chrome și vedeți ce se întâmplă.

Rețineți că avem o nouă variabilă globală, hasGP, pe care o vom folosi ca steag general pentru conectarea unui gamepad. Ca și înainte, avem doi ascultători de evenimente, dar acum avem un nou interval stabilit pentru a verifica dacă un gamepad există. Aceasta este prima dată când ați văzut getGamepads în acțiune și o vom descrie mai mult în secțiunea următoare, dar pentru moment știm că tocmai returnează o matrice și dacă primul element există, îl putem folosi ca pe o modalitate de a ști că un gamepad este conectat. 

Utilizăm jQuery pentru a declanșa același eveniment pe care Firefox l-ar fi primit și apoi șterge intervalul. Observați că același interval se va declanșa o dată în Firefox, ceea ce este puțin risipitor, dar sincer am crezut că a fost o pierdere de timp adăugând un sprijin suplimentar pentru a mirosi Chrome față de Firefox. Un apel mic ca acest lucru pierdut în Firefox nu ar trebui să conteze deloc.

Acum că avem un gamepad conectat, hai să lucrăm cu el!

Obiectul Gamepad

Pentru a vă oferi o idee despre cât de vechi sunt - aici este joystick-ul de ultimă oră pe care l-am folosit pentru primul meu sistem de jocuri.


Imagine de la Wikimedia Commons.

Frumoasă - simplă - și doare ca o iad după o oră de joc. Consolele moderne au gamepad-uri mult mai complexe. Luați în considerare controlerul PS4:

Imagine de la Wikimedia Commons.

Acest controler are două bastoane, un pad direcțional, patru butoane principale, încă patru pe spate, a Acțiune și Opțiuni buton, a PS buton, ceva ce controlează atingerea funky, un difuzor și o lumină. De asemenea, probabil are un capaciter de flux și o chiuvetă de bucătărie. 

Din fericire, avem acces la această fiară prin obiectul Gamepad. Proprietățile includ:

  • id: Acesta este numele controlorului. Nu vă așteptați la ceva prietenos de la asta. DualShock 4 a fost raportat ca 54c-5c4-Wireless Controller în Firefox, în timp ce Chrome a numit același controler Controler wireless (STANDARD GAMEPAD Furnizor: 054c Produs: 05c4).
  • index: Deoarece API-ul Gamepad acceptă mai multe controale, acesta vă permite să determinați ce controler numerotat este. Ar putea fi folosit pentru a identifica un jucător, doi, și așa mai departe.
  • cartografiere: Maparea nu este ceva ce vom acoperi aici, dar, în esență, acest lucru este ceva ce browserul poate face pentru a vă ajuta să reglați controlerul dvs. special la o configurație "standard" a controlerului. Dacă ați jucat mai multe console, știți că acestea au unele asemănări în ceea ce privește controlul, iar API încearcă să "mash" controller-ul dvs. într-un standard. Nu trebuie să vă faceți griji în acest moment, dar dacă doriți mai multe detalii, verificați secțiunea de cartografiere a documentelor API.
  • conectat: Un Boolean care indică dacă controlerul este încă conectat.
  • butoane: O serie de valori ale butoanelor. Fiecare buton este o instanță a GamepadButton. Rețineți că GamepadButton obiect suportă atât o proprietate booleană simplă (presat), precum și a valoare proprietate pentru butoane analogice.
  • axă: O serie de valori reprezentând diferite stick-uri de pe gamepad. Având un jocpad cu trei bastoane, veți avea o serie de șase articole, în care fiecare băț este reprezentată de două valori de matrice. Primul din pereche reprezintă X, sau mișcare stânga / dreapta, în timp ce al doilea reprezintă Y, mișcare sus / jos. În toate cazurile, valoarea va varia de la -1 la 1: pentru valorile stânga / dreapta, -1 este stânga și 1 este corect; pentru valorile sus / jos, -1 este sus și 1 este jos. Potrivit API, matricea este sortată în funcție de "importanță", deci în teorie se poate concentra pe Axele [0] și axe [1] pentru cele mai multe nevoi de jocuri. Pentru a face lucrurile mai interesante, folosind DualShock 4, Firefox a raportat trei axe (ceea ce are sens - vezi imaginea de mai sus), dar Chrome a raportat două. Se pare că d-pad-ul este raportat în Firefox ca o axă, dar nu pare să iasă din ea date. În Chrome, d-pad-ul a apărut ca butoane suplimentare și a fost citit corect.
  • timestamp-ul: În cele din urmă, această valoare reprezintă o marcă de timp care reprezintă ultima dată când hardware-ul a fost verificat. În teorie, probabil că nu este ceva pe care îl vei folosi.

Bine, deci e mult de digerat. În exemplul de mai jos, am adăugat pur și simplu un interval pentru a obține și a inspecta primul gamepad și a tipări ID-ul și apoi butoanele și axele:

           

Puteți încerca demonstrația fie în Chrome, fie în Firefox.

Presupun că acest lucru este destul de explicativ; singura parte dificilă a fost manipularea axelor. Am buclă peste matrice și numărul de două pentru a reprezenta ambele valori stânga / dreapta, sus / jos deodată. Dacă deschideți acest lucru în Firefox și conectați un DualShock, este posibil să vedeți ceva de genul acesta.

După cum puteți vedea, butonul 2 a fost apăsat când mi-am luat captura de ecran. (În cazul în care sunteți curios, asta a fost X butonul.) Notați bastoanele; jocul meu era așezat pe laptopul meu și acele valori fluctuau constant. Nu într-un mod care ar implica valorile rău, per se - daca am luat pad-ul de joc si am impins totul intr-o directie, am vazut valoarea potrivita. Dar cred că ceea ce vedeam era cât de sensibil este controlorul asupra mediului. Sau poate gremlins.

Iată un exemplu pentru modul în care afișează Chrome:

Din nou, am reținut X buton, dar observați cum indicatorul de pe butoane este diferit aici. După cum puteți spune, va trebui să faceți un pic de ... masaj dacă doriți să utilizați acest API pentru un joc. Mi-aș imagina că ați putea verifica ambele Butoane 1 și 2 pentru "foc" și urmați-vă cu un test bun.

Punându-le pe toți împreună

Deci, ce zici de o adevărată demo? Ca majoritatea coderilor care și-au început viața jucând jocuri video, am visat să fiu un creator de jocuri video când am crescut. Se pare că matematica devine foarte greu după calcul și, aparent, această chestiune "web" are un viitor, așa că, în timp ce viitorul nu mi-a ieșit, aș vrea să-mi imaginez că într-o bună zi aș putea transforma aceste standarde web competențe într-un joc jucabil. Până în acea zi, ceea ce am astăzi este o versiune frumoasă a pongului bazată pe panza. Pong cu un singur jucător. Așa cum am spus, lame.

Jocul redă pur și simplu o paletă și o minge și vă oferă control asupra tastaturii asupra mingii. De fiecare dată când pierdeți mingea, scorul se ridică. Ceea ce are sens pentru golf, mai degrabă decât pentru pong, cred, dar să nu ne îngrijorăm prea mult. Codul poate fi găsit în game1.html și puteți reda demonstrația în browser. 

Nu voi trece codul aici, dar să ne uităm la câteva fragmente. În primul rând, aici este funcția principală care se ocupă de toate detaliile de animație:

buclă de funcții () draw.clear (); ball.move (); ball.draw (); paddle.draw (); paddle.move (); draw.text ("Scor:" + scor, 10, 20, 20); 

Paddle-ul este condus de tastatură folosind doi manipulatori de evenimente simple:

$ (fereastra) .keydown (functie (e) comuta (e.keyCode) caz 37: input.left = true; pauza 39; input.right = true; break;); $ (fereastra) .keyup (functie (e) comutare (e.keyCode) caz 37: input.left = false; pauza 39; input.right = false; break;); 

intrare variabila este o variabilă globală care este preluată de un obiect pale mișcare metodă:

this.move = funcția () if (input.left) this.x - = this.speed; în cazul în care (this.x < 0) this.x=0;  if(input.right)  this.x += this.speed; if((this.x+this.w) > canvas.width) this.x = canvas.width-this.w;  

Din nou, nimic prea complex aici. Iată o captură de ecran a jocului în acțiune. (Știu - nu ar trebui să renunț la slujba mea de zi).

Deci, cum adaugam suportul jocului? Din fericire, am primit deja codul pentru noi. În demo-ul precedent, am făcut tot ce este necesar pentru a verifica și a observa actualizări ale codului. Putem lua acel cod și pur și simplu îl adăugăm la codul existent al jocului. 

Din moment ce este (virtual) același, nu o voi repeta (deși lista completă este disponibilă dacă doriți), dar voi împărți codul modificat executat la fiecare 100ms odată ce un gamepad este detectat:

funcția checkGamepad () var gp = navigator.getGamepads () [0]; var axeLF = gp.axes [0]; în cazul în care (axeLF < -0.5)  input.left = true; input.right = false;  else if(axeLF > 0.5) input.left = false; input.right = true;  altfel input.left = false; input.right = false;  

Din nou, puteți încerca demo-ul în oricare browser.

Ca și în cazul precedent, am presupus că ne pasă doar de un jocpad. Deoarece jocul nostru are doar o paletă și se mișcă numai orizontal, putem trece prin verificarea numai a primei axe. Amintiți-vă, în conformitate cu API aceasta ar trebui să fie "cea mai importantă", și în testarea mea a fost stick-ul stâng, care este destul de standard pentru jocuri. 

Deoarece jocul nostru folosește o variabilă globală, intrare, pentru a reprezenta mișcarea stângă și dreaptă, tot ce trebuie să fac este să modific această valoare pe baza valorii axei. Acum, observați că nu am verificat pur și simplu pentru "mai puțin de zero" și "mai mare decât zero". De ce? Dacă vă aduceți aminte de demonstrația anterioară, jocul a fost foarte sensibil și de multe ori ar fi raportat valori chiar și atunci când nu credeam că am mutat stickul. Folosind o valoare limită de .5 oferă controlului un pic mai mult stabilitate. (Și, evident, acesta este tipul de lucru pe care ar trebui să-l optimizați pentru a vedea ce "simte"). 

În general, am adăugat aproximativ 25 de linii de cod la jocul meu pentru a adăuga suport pentru gamepad. Pietrele astea.

Joc început!

Sperăm că ați văzut că, deși există cu siguranță unele idiosincrazii, API-ul Gamepad are acum suport în două browsere importante și este ceva ce cred că dezvoltatorii ar trebui să înceapă să ia în considerare pentru jocurile lor.

Resurse

Iată câteva resurse suplimentare pentru a vă ajuta să aflați mai multe despre API-ul Gamepad.

  • Folosind API-ul Gamepad
  • Gamepad Specification
  • Gamepad.js - O bibliotecă Javascript pentru a permite utilizarea gamepad-urilor și joystick-urilor în browser.
  • Gamepad Controls pentru jocurile HTML5
  • Versiunea Wii U (complet diferită de specificație - o slujbă bună, Nintendo!)

Referințe

  • Previzualizare imagine imagine: Controler de jocuri video proiectat de Uriel Sosa de la Proiectul Noun