Siden nettbasert spill blir mer populært, er en av de største stikkpunktene for spillere inngangskontroll. Mens mine første FPS-spill var rent mus- og tastaturbaserte, har jeg nå blitt så mye mer vant til en riktig konsollkontroller som jeg helst vil bruke den til alt, inkludert nettbaserte spill.
Heldigvis eksisterer HTML5 Gamepad API for å tillate webutviklere programmatisk tilgang til spillkontrollere. Uheldigvis, selv om denne API-en har eksistert lenge, er det bare nå sakte å flytte inn i de nyeste versjonene av desktop-nettlesere. Det ble tynn i lang tid i en bygning av Firefox (ikke en bygge høyere, ingen nattlig bygge) og var problematisk i Chrome. Nå er det-ikke-perfekt, men litt mindre problematisk og faktisk ganske enkelt å bruke.
I denne artikkelen diskuterer jeg de forskjellige funksjonene i APIen, hvordan du får den til å fungere både i Firefox og Chrome, og viser et ekte (hvis enkelt) spill, og hvor enkelt det er å legge til gamepad-støtte til det.
Gamepad API består av følgende funksjoner:
koble
og koble fra
arrangementer.La oss begynne med å diskutere hvordan du kan oppdage støtte til en gamepad på høyt nivå.
Både Firefox og Chrome støtter en metode på navigator
, getGamepads ()
, som returnerer en rekke av alle tilkoblede gamepad-enheter. Vi kan bruke dette som en enkel metode for å oppdage om Gamepad API er tilstede. Her er en enkel funksjon for den sjekken:
funksjon canGame () return "getGamepads" i navigator;
Så langt så bra. Nå for den funky delen. Gamepad API har støtte for hendelser som oppdager når en gamepad er koblet til og frakoblet. Men hva skjer hvis brukeren allerede har en gamepad koblet til sin bærbare når de treffer siden din? Normalt vil nettsiden vente på at brukeren skal gjøre noe, noe med den faktiske gamepad. Dette betyr at vi må gi en slags melding til brukeren som lar dem få vite at de trenger å "våkne" støtte for gamepad hvis den er tilkoblet. Du kan fortelle dem å treffe hvilken som helst knapp eller flytte en pinne.
For å gjøre ting enda mer interessant, synes denne sjekken ikke å være nødvendig når du oppdaterer siden. Du vil oppdage at når du har brukt Gamepad API på en side og deretter lastet den på nytt, gjenkjenner siden dette faktum, og automatisk vurderer det tilkoblet.
Men vent - det blir bedre. Chrome støtter ikke de tilkoblede (eller frakoblede) hendelsene for øyeblikket. Det typiske arbeidet for dette (og det som ble vist i de gode MDN-dokumentene for API) er å sette opp en meningsmåling og se om en gamepad "vises" i listen over tilkoblede enheter.
Forvirrende? La oss starte med et eksempel som bare støtter Firefox:
I eksemplet ovenfor begynner vi å sjekke for å se om nettleseren støtter Gamepad API. Hvis det gjøres, oppdaterer vi først en div med instruksjoner for brukeren, og begynner deretter å lytte umiddelbart til begge koble
og koble fra
arrangementer.
Hvis du kjører dette med Firefox og kobler til spillkontrollen din, må du også trykke på en knapp, på hvilket tidspunkt hendelsen er avfyrt, og du er klar til å gå.
Igjen, i min test, når jeg laster opp siden, forbindelse
hendelsen er umiddelbar. Dette skaper en liten "flimmer" -effekt som kan være uønskelig. Du kan faktisk bruke et intervall for å angi retninger for noe som 250ms etter at DOM har lastet og bare spørre om det ikke oppsto en forbindelse i mellomtiden. Jeg bestemte meg for å holde ting enkelt for denne opplæringen.
Koden vår fungerer for Firefox, men la oss nå legge til Chrome-støtte:
Koden er litt mer kompleks nå, men ikke så veldig. Last demoen i Chrome og se hva som skjer.
Legg merke til at vi har en ny global variabel, hasGP
, at vi vil bruke som et generelt flagg for å ha en gamepad tilkoblet. Som før har vi to hendelseslyttere, men nå har vi et nytt intervall satt opp for å sjekke om en gamepad eksisterer. Dette er første gang du har sett getGamepads
i bruk, og vi beskriver det litt mer i neste avsnitt, men vet nå at det bare returnerer en matrise, og hvis det første elementet eksisterer, kan vi bruke det som en måte å vite at en gamepad er koblet til.
Vi bruker jQuery til å avbrå den samme hendelsen Firefox ville ha mottatt, og deretter fjerne intervallet. Legg merke til at dette samme intervallet vil brenne en gang i Firefox også, noe som er litt sløsing, men ærlig talt trodde jeg det var bortkastet tid å legge til ekstra støtte for å snuse Chrome versus Firefox. En liten samtale som dette bortkastet i Firefox burde ikke ha noe i det hele tatt.
Nå som vi har en tilkoblet gamepad, la oss jobbe med den!
For å gi deg en ide om hvor gammel jeg er - her er toppmoderne joysticken jeg brukte til mitt første spillsystem.
Fint - enkelt - og det gjorde vondt etter helvete etter en time med å spille. Moderne konsoller har mye mer komplekse gamepads. Vurder PS4-kontrolleren:
Bilde fra Wikimedia Commons.Denne kontrolleren har to pinner, en retningsplate, fire hovedknapper, fire på baksiden, a Dele og alternativer knapp, a PS knapp, noe funky touch control ting, en høyttaler og et lys. Det har også sannsynligvis en flux kapasitør og en kjøkkenvask.
Heldigvis har vi tilgang til dette dyret via Gamepad-objektet. Egenskapene inkluderer:
id
: Dette er navnet på kontrolleren. Forvent ikke noe vennlig fra dette. Min DualShock 4 ble rapportert som 54c-5c4-trådløs kontroller
i Firefox, mens Chrome kalte den samme kontrolleren Trådløs kontroller (STANDARD GAMEPAD-leverandør: 054c Produkt: 05c4)
.index
: Siden Gamepad API støtter flere kontroller, lar denne deg bestemme hvilken nummerert kontroller den er. Det kan brukes til å identifisere spiller ett, to og så videre.kartlegging
: Kartlegging er ikke noe vi skal dekke her, men i hovedsak er dette noe nettleseren kan gjøre for å hjelpe deg med å kartlegge din spesielle kontroller til et "standard" kontrolleroppsett. Hvis du har spilt flere konsoller, vet du at de har noen likheter når det gjelder kontroll, og API-en forsøker å "knuse" kontrolleren til en standard. Du trenger ikke å bekymre deg for dette for nå, men hvis du vil ha mer informasjon, sjekk kartleggingsdelen av API-dokumentene.tilkoblet
: En boolsk indikerer om styreenheten fortsatt er tilkoblet.knapper
: En rekke knappverdier. Hver knapp er en forekomst av GamepadButton. Legg merke til at GamepadButton
objektet støtter både en enkel boolsk eiendom (presset
) samt a verdi
Egenskap for analoge knapper.akser
: En rekke verdier som representerer de forskjellige pinner på gamepad. Gitt en gamepad med tre pinner, vil du ha en rekke seks elementer, hvor hver pinne representeres av to arrayverdier. Den første i paret representerer X, eller venstre / høyre bevegelse, mens den andre representerer Y, opp / ned bevegelse. I alle tilfeller vil verdien variere fra -1
til 1
: for venstre / høyre verdier, -1
er igjen og 1
er riktig; for opp / ned-verdier, -1
er oppe og 1
er nede. I henhold til API er sorteringen sortert etter "betydning", så i teorien kan du fokusere på akser [0]
og akser [1]
for de fleste spillbehov. For å gjøre ting mer interessant, bruker jeg DualShock 4, rapporterte Firefox tre akser (som gir mening - se bildet ovenfor), men Chrome rapporterte to. Det virker som om d-pad-staven er rapportert i Firefox som en akse, men ingen data ser ut til å komme ut av det. I Chrome viste d-puten opp som flere knapper, og ble korrekt lest.tidsstempel
: Endelig er denne verdien en tidsstempel som representerer siste gang maskinvaren ble sjekket. I teorien er dette sannsynligvis ikke noe du vil bruke.Ok, så det er mye å fordøye. I eksemplet nedenfor har vi ganske enkelt lagt til et intervall for å få, og inspisere, den første gamepad, og skrive ut ID og deretter knappene og aksene:
Du kan prøve demoen i Chrome eller Firefox.
Jeg antar at dette er alt ganske selvforklarende; Den eneste virkelige vanskelige delen var å håndtere aksene. Jeg slår over arrayet og teller ved to til å representere både venstre / høyre, opp / ned-verdiene på en gang. Hvis du åpner dette i Firefox og kobler til en DualShock, kan du se noe slikt.
Som du kan se, ble knapp 2 trykket da jeg tok skjermbildet mitt. (Hvis du er nysgjerrig, det var det X knappen.) Merk pinnene; min gamepad satt på min laptop og de verdiene var stadig svingende. Ikke på en måte som ville bety at verdiene var dårlig, i seg selv - hvis jeg plukket opp spillplaten og presset helt i en retning så jeg den riktige verdien. Men jeg tror det jeg så på, var hvor følsomt regulatoren er for miljøet. Eller kanskje gremlins.
Her er et eksempel på hvordan Chrome viser det:
Jeg holdt igjen X knapp - men legg merke til hvordan knappindeksen er annerledes her. Som du kan fortelle, må du gjøre litt ... massasje hvis du vil bruke denne APIen for et spill. Jeg kan tenke deg at du kunne sjekke begge knappene 1 og 2 for "brann" og følge opp med en god del testing.
Så, hva med en ekte demo? Som de fleste kodere som startet sitt liv med å spille videospill, drømte jeg om å være en hotshot videospillskaper når jeg vokste opp. Det viser seg at matematikk blir ekte hardt etter kalkulator, og tilsynelatende har disse "web" -temaene en fremtid, så mens den fremtiden ikke skjedde for meg, vil jeg likevel forestille meg at jeg en dag kunne slå disse nettstandardene ferdigheter til et spillbart spill. Inntil den dagen, det jeg har i dag er en ganske lammet lerretsbasert versjon av pong. Single-player pong. Som sagt, lame.
Spillet gjør bare en padle og en ball, og gir deg tastaturkontroll over ballen. Hver gang du savner ballen, går poengsummen opp. Som gir mening for golf i stedet for pong, antar jeg, men la oss ikke bekymre deg for mye om det. Koden finnes i game1.html, og du kan spille demoen i nettleseren din.
Jeg vil ikke gå gjennom all koden her, men la oss se på noen få utdrag. Først er her hovedløyfunksjonen som håndterer alle animasjonsdetaljer:
funksjonsløkke () draw.clear (); ball.move (); ball.draw (); paddle.draw (); paddle.move (); draw.text ("Score:" + score, 10, 20, 20);
Padlen kjøres av tastaturet ved hjelp av to enkle hendelsesbehandlere:
$ (vindu) .keydown (funksjon (e) switch (e.keyCode) tilfelle 37: input.left = true; break; tilfelle 39: input.right = true; break;); $ (vindu) .keyup (funksjon (e) switch (e.keyCode) tilfelle 37: input.left = false; break; case 39: input.right = false; break;);
De inngang
variabel er en global variabel som hentes av et padleobjekt bevege seg
metode:
this.move = function () if (input.left) this.x - = this.speed; if (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;
Igjen, ingenting for komplisert her. Her er et skjermbilde av spillet i aksjon. (Jeg vet-jeg burde ikke avslutte dagjobben min.)
Så, hvordan legger vi til gamepad-støtte? Heldigvis har vi allerede koden for oss. I den forrige demonstrasjonen gjorde vi alt som var nødvendig for å se etter og legge merke til oppdateringer av koden. Vi kan ta den koden og bare legge den til spillets eksisterende kode.
Siden det er (nesten) det samme, vil jeg ikke gjenta det (selv om hele oppføringen er tilgjengelig hvis du vil ha det), men jeg vil dele den endrede koden som kjøres hver 100ms når en gamepad er oppdaget:
funksjonskontrollGamepad () var gp = navigator.getGamepads () [0]; var axeLF = gp.axes [0]; if (axeLF < -0.5) input.left = true; input.right = false; else if(axeLF > 0,5) input.left = false; input.right = true; else input.left = false; input.right = false;
Igjen kan du prøve demoen i begge nettlesere.
Som med forrige eksempel har vi antatt at vi bare bryr oss om en gamepad. Siden spillet vårt bare har en padle og det bare beveger seg horisontalt, kan vi komme forbi ved å bare sjekke den aller første aksen. Husk, i henhold til API-en, bør dette være den "viktigste" en, og i testen var det den venstre pinnen, som er ganske standard for spill.
Siden vårt spill bruker en global variabel, inngang
, For å representere venstre og høyre bevegelse, er alt jeg trenger å gjøre, å endre den verdien basert på aksenverdien. Legg merke til at jeg ikke bare sjekket om "mindre enn null" og "større enn null". Hvorfor? Hvis du husker fra den tidligere demonstrasjonen, var gamepaden svært følsom, og vil ofte rapportere verdier selv når jeg ikke trodde jeg hadde faktisk flyttet pinnen. Bruke en grenseverdi på .5
gir kontrollen litt mer stabilitet. (Og selvfølgelig er dette den typen ting du må tilpasse for å se hva "føles" riktig.)
Alt i alt lagde jeg omtrent 25 linjer med kode til spillet mitt for å legge til gamepad-støtte. Det stener.
Forhåpentligvis har du sett det, mens det er definitivt noen idiosyncrasies, har Gamepad API nå støtte i to store nettlesere, og det er noe jeg tror utviklere burde begynne å vurdere for deres spill.
Her er noen ekstra ressurser for å hjelpe deg med å lære mer om Gamepad API.