Naarmate HTML-games geleidelijk populairder worden, introduceren leveranciers enkele opwindende nieuwe API's om gamen iets zoeter te maken voor zowel onze ontwikkelaars als onze eindspelers. Een daarvan is de GamepadAPI, waarmee je je oude console-gamepad kunt aansluiten op je computer en deze kunt gebruiken voor browsergebaseerde games, plug-and-play-stijl. Laten we erin duiken!
Kort samengevat: met de Gamepad-API kunt u communiceren met uw browser met behulp van een console voor gameconsoles, AKA een gamepad. Dit vereist geen speciaal stuurprogramma of plug-in om te werken, het is zo simpel als plug and play!
Omdat ik zelf een console-gamer ben in plaats van een desktop-gamer, speel ik het liefst met games via een gamepad en met de aankomende opkomst van HTML- en JavaScript-games wordt dit een echt handig hulpmiddel om games gemakkelijker toegankelijk te maken voor uw gebruikers.
De Gamepad-API is niet direct beschikbaar voor openbare publicatie, maar we kunnen deze zelf gaan gebruiken met voorbeeldversies van Firefox. Dus voordat we vastlopen, hebben we een paar dingen nodig.
Zoals ik al zei, is de Gamepad-API nog niet beschikbaar voor openbare release, dus moet je eerst een Nightly-versie van Firefox kopen en ervoor zorgen dat je de Firebug-add-on hebt geïnstalleerd (alleen voor foutopsporing).
Ook kun je een gamepad niet vergeten! Ik ga een PlayStation 3-controller gebruiken voor deze tutorial, maar een Xbox-controller doet het prima.
Nadat je Nightly hebt geïnstalleerd en hebt toegevoegd aan Firebug, ben je klaar om te gaan!
(NB: recente builds van Chromium hebben ook Gamepad API-ondersteuning, maar deze tutorial is niet getest.)
Laten we beginnen met een eenvoudig HTML-bestand (index.html) met "gamepad.js" (een leeg JavaScript-bestand).
index.html
Inleiding tot de Gamepad-API Gamepad-API
De verbinding van een gamepad wordt gedetecteerd met een eenvoudige JavaScript-gebeurtenislistener, de gebeurtenis die wordt afgevuurd wordt "MozGamepadConnected" genoemd. Dus het eerste wat we moeten doen is een gebeurtenislistener aan het venster toevoegen om die gebeurtenis te detecteren.
Ik voeg ook een callback-functie toe die de details van de gebeurtenis in de Firebug-console registreert. Dit is de informatie waar we het meest in geïnteresseerd zijn en wat ons daadwerkelijk zal laten weten dat we een gamepad met succes hebben verbonden.
function gamepadConnected (evt) console.log (evt); window.addEventListener ('MozGamepadConnected', gamepadConnected);
Voer je index.html uit in Nightly en open de Firebug-console, hier kunnen we de logging van de gebeurtenis zien vanuit onze callback-functie.
Zorg ervoor dat je controller is uitgeschakeld en niet draadloos is verbonden met een gameconsole. Sluit deze via USB aan op uw computer en schakel de controller in, terwijl u het gebeurtenislogboek in de console bekijkt.
Geweldig, we hebben een gamepad die verbinding maakt met een browser, geen extra plug-ins of stuurprogramma's vereist!
Het is net zo belangrijk om te weten of een gamepad ook is losgekoppeld, dus laten we naar de gebeurtenis kijken, "MozGamepadDisconnected".
Vergelijk net als bij stap één een gebeurtenislistener voor een disconnect-gebeurtenis en een callback-functie om de gebeurtenisdetails te loggen.
function gamepadDisconnected (evt) console.log (evt); window.addEventListener ('MozGamepadDisconnected', gamepadDisconnected);
Als je gamepad nog steeds verbonden is, vernieuw je je pagina (die je gekoppelde gebeurtenis laat zien). Koppel vervolgens je gamepad los door deze uit de USB-poort te werpen. U zou een gebeurtenislog zoals deze moeten krijgen.
Nu weten we wanneer een gamepad is aangesloten en losgekoppeld, het is waarschijnlijk een goed idee om de status in een variabele vast te leggen en u klaar te maken om knopgebeurtenissen te detecteren!
var gamepadActive = false; function gamepadConnected (evt) console.log (evt); gamepadActive = true; function gamepadDisconnected (evt) console.log (evt); gamepadActive = false; window.addEventListener ('MozGamepadConnected', gamepadConnected); window.addEventListener ('MozGamepadDisconnected', gamepadDisconnected);
Druk op de knop, gebruik opnieuw een gebeurtenislistener en callback-functie met twee gebeurtenissen, "MozGamepadButtonDown" en "MozGamepadButtonUp".
Ik zou willen voorstellen om het hele evenement te loggen door zelf op de knop te drukken om te zien wat er aan de hand is, maar de belangrijkste informatie die we nodig hebben om van dit evenement te komen is evt.button
. Dit is de numerieke id van de knop die werd ingedrukt.
De callback-functie neemt deze keer een tweede parameter, een booleaanse waarde om te testen of de knop werd ingedrukt of losgelaten. We plaatsen dit zelf in de callback-functies van de gebeurtenislisteners.
functieknop Gedrukt (evt, ingedrukt) console.log (evt.button, ingedrukt); window.addEventListener ("MozGamepadButtonDown", functie (evt) buttonPressed (evt, true);); window.addEventListener ("MozGamepadButtonUp", functie (evt) buttonPressed (evt, false););
Dit zou nu de ID's moeten uitvoeren van de knoppen die zijn ingedrukt en of ze zijn ingedrukt of zijn losgelaten (true voor knop omlaag, false voor knop omhoog).
Vervolgens maken we een array met alle PlayStation 3-knoppen erin. De indices van de array worden toegewezen aan de ID's die op deze gamepad worden gebruikt, waarbij de waarden de naam van de knop zijn.
var gamepadActive = false, ps3Buttons = new Array (); ps3Buttons [12] = 'triangle', ps3Buttons [15] = 'square', ps3Buttons [14] = 'cross', ps3Buttons [13] = 'circle', ps3Buttons [4] = 'up', ps3Buttons [7] = 'left', ps3Buttons [6] = 'down', ps3Buttons [5] = 'right', ps3Buttons [10] = 'L1', ps3Buttons [8] = 'L2', ps3Buttons [11] = 'R1', ps3 Knoppen [9] = 'R2', ps3Buttons [1] = 'L3', ps3Buttons [2] = 'R3', ps3Buttons [16] = 'PS', ps3Buttons [0] = 'select', ps3Buttons [3] = ' begin';
Als u een andere controller gebruikt, neem dan de tijd om erachter te komen welke index bij welke knop hoort en sla deze info op in een vergelijkbare array.
Als we nu de buttonPressed ()
functie ooit zo licht, kunnen we gemakkelijk zien op welke knop op de controller is gedrukt.
functieknop Gedrukt (evt, ingedrukt) console.log (ps3Buttons [evt.button] + 'was ingedrukt');
Geef het een kans! Druk op de knoppen op uw controller om nu de naam te registreren van de knoppen die worden ingedrukt. Dit zal een stuk gemakkelijker te begrijpen zijn dan "knop 5" (wat in mijn geval op de D-pad staat).
Het detecteren van asgebeurtenissen houdt feitelijk bij waar de linker en rechter analoge sticks op de gamepad zijn gepositioneerd met behulp van het "MozGamepad Axex Move" -gebeurtenis.
Voeg de nieuwe gebeurtenishandler en callback-functie toe.
functie moveAnalogSticks (evt) console.log (evt.axis, evt.value); window.addEventListener ("MozGamepadAxisMove", moveAnalogSticks);
Dit is wat we krijgen - verwarrend, goed?
Er is maar één evenement dat wordt afgevuurd door beide analoge sticks; elke gebeurtenis geeft ons een van de vier mogelijke assen en een waarde tussen -1,0 en +1,0. As 0 en 1 behoren tot de linker analoge stick en as 2 en 3 behoren tot de rechterkant.
In het bovenstaande diagram ziet u dat as 0 en 2 overeenkomen met de x-as en 1 en 3 met de y-as. Door voor elke afzonderlijke analoge joystick zowel de x- als de y-as te gebruiken, kunt u uitzoeken op welke manier de analoge joystick is geplaatst!
Op verschillende gamepads kunt u andere assen hebben. De schoudertriggers op een Xbox-controller zijn bijvoorbeeld ook analoog.
Dat omvat alle gebeurtenissen die we momenteel vanaf een gamepad kunnen nemen, dus laten we datgene wat we hebben geleerd in praktijk brengen.
Nu wil ik niet te veel ingaan op de ontwikkeling van games, omdat we ons concentreren op wat we gebruiken om games zelf te besturen. Een van de belangrijkste dingen om naar te kijken is echter het wisselen van besturingsschema's. Omdat niet iedereen een gamepad bij de hand heeft, moeten we ervoor zorgen dat we zowel het toetsenbord als de gamepad kunnen bedienen.
Als u een kleine demo wilt uitvoeren, maakt u een canvas
element in uw html-bestand met een id van "game" en stel de breedte in op 600 en hoogte op 540. Zoals u wellicht weet, wordt het canvas-element vaak gebruikt om HTML-games weer te geven op.
U wilt ook de afbeeldingen "ship.png" en "space.jpg" kopiëren van de brondownload naar uw werkmap, want dit zijn de gegevens die we naar het canvas zullen renderen. Je kunt ook een aantal eigen afbeeldingen vinden om mee te spelen!
Inleiding tot de Gamepad-API Gamepad-API
Nu dat het canvas
element zit in onze DOM, we willen een game-loop creëren om onze game te renderen.
Ik gebruik een schijf voor "requestAnimationFrame" van Paul Irish die de basis zal vormen voor onze loop. Vervolgens krijgen we de 2D-context van de canvas
die we zullen gebruiken om op te tekenen en twee nieuwe afbeeldingsobjecten te maken, één voor de achtergrond en één voor ons ruimteschip.
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/ window.requestAnimFrame = (function () return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (/ * function * / callback, / * DOMElement * / element) window.setTimeout (callback, 1000/60);;) (); var canvas = document.getElementById ('game'), ctx = canvas.getContext ('2d'), ship = new Image (), space = new Image (); space.src = "space.jpg"; ship.src = "ship.png";
Vervolgens het spelerobject. Het heeft x- en y-coördinaten die bijhouden waar het op het canvas zou moeten verschijnen; vier richtingstoestanden (omhoog, omlaag, links en rechts) zodat we kunnen weten op welke manier het schip beweegt; een render ()
functie, die voor het eerst oproept updatePosition ()
en tekent vervolgens het beeld van het schip op het canvas op basis van de x- en y-coördinaten, en ten slotte de updatePosition ()
functie zelf, die test om te zien op welke manier het schip zal bewegen en zijn positie dienovereenkomstig bijwerkt.
var player = x: 200, y: 250, up: false, down: false, left: false, right: false, render: function () this.updatePosition (); ctx.drawImage (schip, this.x, this.y); , updatePosition: function () this.up? this.y--: false; this.down? this.y ++: false; this.left? this.x--: false; deze rechts ? this.x ++: false;
Daarna hebben we onze "renderGame" -functie die de achtergrondafbeelding op de ruimte tekent canvas
eerst trekt dan ons ruimteschip daar bovenop.
En tot slot, onze lus. Deze functie roept zichzelf keer op keer op, elke keer dat we onze "renderGame" -functie aanroepen.
function renderGame () ctx.drawImage (spatie, 0,0); player.render (); ; (function animloop () requestAnimFrame (animloop); renderGame ();) ();
Je canvas zou nu een mooie ruimte moeten hebben met een achtergrondschip er in het midden van een ruimteschip - niet te opwindend, ik weet het. Dus laten we wat besturingselementen toevoegen!
In onze spelercode hebben we de vier knoppen genoemd waarmee we ons schip willen besturen. Deze komen overeen met de namen van de knoppen in de ps3Buttons []
matrix. Dus alles wat we moeten doen is onze aanpassen buttonPressed ()
functioneer nog maar een klein beetje en we zullen in beweging komen.
var player = ... up: false, down: false, left: false, right: false, ...
Wanneer een gamepadknop wordt ingedrukt of losgelaten, zal deze zijn status binnen het spelerobject instellen, dus wanneer op de knop "Omhoog" wordt gedrukt, player.up = true / false
zal worden ingesteld.
functieknop Gedrukt (evt, ingedrukt) console.log (evt.button, ingedrukt); player [ps3Buttons [evt.button]] = ingedrukt? waar onwaar;
Ga terug naar je demo en je moet in staat zijn om je schip te verplaatsen!
Omdat niet iedereen die je spel speelt, een gamepad zal hebben, wil je waarschijnlijk nog steeds toestaan dat ze het spel met een toetsenbord spelen.
Laten we eerst een nieuw maken toetsen []
array, en breng de pijltjestoetsen van het toetsenbord in kaart ' sleutelcode
eigenschappen van de equivalente knoppen op de gamepad. Hierdoor kunnen we het opnieuw gebruiken buttonPressed ()
functie die de gamepad gebruikt.
var gamepadActive = false, ps3Buttons = new Array (), keys = new Array (); ps3Buttons [12] = 'triangle', ps3Buttons [15] = 'square', ps3Buttons [14] = 'cross', ps3Buttons [13] = 'circle', ps3Buttons [4] = 'up', ps3Buttons [7] = 'left', ps3Buttons [6] = 'down', ps3Buttons [5] = 'right', ps3Buttons [10] = 'L1', ps3Buttons [8] = 'L2', ps3Buttons [11] = 'R1', ps3 Knoppen [9] = 'R2', ps3Buttons [1] = 'L3', ps3Buttons [2] = 'R3', ps3Buttons [16] = 'PS', ps3Buttons [0] = 'select', ps3Buttons [3] = ' begin'; toetsen [38] = 4; toetsen [37] = 7; toetsen [40] = 6; toetsen [39] = 5;
Nu hebben we een gebeurtenislistener "onkeyup" en "onkeydown" nodig voor de pijltoetsen. Wanneer een toets wordt ingedrukt of losgelaten, zorgen wij ervoor dat een gamepad niet in gebruik is. Vervolgens voorkomen we dat de pijltoets zijn gebruikelijke taak uitvoert (in dit geval het browservenster omhoog of omlaag schuiven) en vervolgens dezelfde oproep doen buttonPressed ()
functie die door de gamepad wordt aangeroepen.
Hiertoe wordt een nep-gebeurtenisobject doorgegeven met de "sleutelcode" van de sleutel die is toegewezen aan een item in de toetsen []
array, die op zijn beurt de bijbehorende ID van de gamepadknop doorgeeft.
window.onkeydown = function (evt) if (gamepadActive == false) evt.preventDefault (); buttonPressed (button: keys [evt.keyCode], true); window.onkeyup = function (evt) if (gamepadActive == false) evt.preventDefault (); buttonPressed (button: keys [evt.keyCode], false);
Dit zou je nu de pijltjestoetsen moeten laten gebruiken om het schip te besturen wanneer een gamepad niet is aangesloten, terwijl je het gamepad nog steeds kunt laten overnemen wanneer het aanwezig is.
Daarom hebben we de basisbeginselen van het aansluiten van een gamepad op uw computer behandeld, geleerd hoe u de gebeurtenissen die het gamepad oproept, kunt gebruiken en deze vervolgens in de praktijk kunt gebruiken. Niet te vergeten, de cruciale ondersteuning voor het terugvallen van het toetsenbord!
Een snelle uitdaging voor degenen onder u met een andere controller dan een PS3 Dual Shock: pas de toewijzing van de knoppen aan op basis van de controller die is aangesloten.
Bedankt dat je de tijd hebt genomen om meer te weten te komen over de Gamepad-API. Als u vragen heeft, laat deze dan achter in de opmerkingen.