Kontrolagailu bat konektatzen duzunean, botoiak birrintzen dituzu, makilak mugitu, abiarazleei tira... eta garatzaile gisa, ez duzu ezer ikusten. Arakatzaileak jasotzen ari da, noski, baina kontsolan zenbakiak erregistratzen ez badituzu, ikusezina da. Hori da Gamepad APIarekin buruhaustea. Urteak daramatza, eta egia esan nahiko indartsua da. Botoiak, makilak, abiarazleak, lanak irakur ditzakezu. Baina jende gehienak ez du ukitzen. Zergatik? Ez dagoelako iritzirik. Ez dago panelik garatzaileentzako tresnetan. Ez dago modu argirik kontrolatzaileak uste duzuna egiten ari ote den jakiteko. Itsuan hegan egitea bezala sentitzen da. Horrek nahikoa eragin zidan tresna txiki bat eraikitzeko: Gamepad Cascade Debugger. Kontsolaren irteerari begiratu beharrean, kontrolagailuaren zuzeneko ikuspegi interaktiboa lortzen duzu. Sakatu zerbait eta pantailan erreakzionatzen du. Eta CSS Cascade Layers-ekin, estiloak antolatuta geratzen dira, beraz, garbiagoa da arazketa. Argitalpen honetan, kontrolagailuak araztea zergatik den hain mina, CSS-k nola laguntzen duen garbitzen eta nola eraiki dezakezun ikusizko arazketa berrerabilgarria zure proiektuetarako erakutsiko dizut.
Guztiak erregistratzeko gai bazara ere, azkar irakurri ezinezko kontsolaren spamarekin amaituko duzu. Adibidez: [0,0,1,0,0,0.5,0,...] [0,0,0,0,1,0,0,...] [0,0,1,0,0,0,0,...]
Esan al dezakezu zein botoi sakatu den? Agian, baina begiak estutu eta sarrera batzuk galdu ondoren. Beraz, ez, arazketa ez da erraz etortzen sarrerak irakurtzeko orduan. 3. arazoa: Egitura Eza Nahiz eta bistaratzaile azkar bat bildu, estiloak azkar nahas daitezke. Lehenetsiak, aktiboak eta arazketa egoerak gainjar daitezke, eta egitura argirik gabe, zure CSS hauskorra eta hedatzen zaila izango da. CSS Cascade Layers lagun dezake. Estiloak lehentasunaren arabera ordenatuta dauden "geruza"tan biltzen dituzte, beraz, espezifikotasunari aurre egiteari utzi eta "Zergatik ez da nire arazketa estiloa erakusten?" Horren ordez, kezka bereiziak mantentzen dituzu:
Oinarria: kontrolagailuaren estandarra, hasierako itxura. Aktiboa: sakatutako botoietarako eta mugitutako makiletarako nabarmentzen dira. Araztu: Garatzaileentzako gainjartzeak (adibidez, zenbakizko irakurketak, gidak eta abar).
Honen arabera CSS-n geruzak definituko bagenitu, hau izango genuke: /* lehentasun txikienetik handienera */ @geruza oinarria, aktiboa, arazketa;
@geruza oinarria { /* ... */ }
@geruza aktibo { /* ... */ }
@geruza arazketa { /* ... */ }
Geruza bakoitza aurreikusteko modukoa denez, beti dakizu zein arauk irabazten duten. Aurreikusgarritasun horrek arazketa errazten du ez ezik, benetan kudeatzen du. Arazoa (sarrera ikusezina eta nahasia) eta planteamendua (Cascade Layers-ekin eraikitako arazte bisuala) landu ditugu. Orain urratsez urratseko prozesuan ibiliko gara arazketa eraikitzeko. Araztearen kontzeptua Ezkutuko sarrera ikusgai jartzeko modurik errazena pantailan marraztea da. Hori da arazketa honek egiten duena. Botoiek, abiarazleek eta joystickek ikusmen bat lortzen dute.
Sakatu A: zirkulu bat pizten da. Mugitu makila: zirkulua inguruan irristatzen da. Pull a trigger a halfway: Barra bat erdibidean betetzen da.
Orain ez zaude 0 eta 1-ei begira, baizik eta kontroladoreak zuzenean erreakzionatzen ari zarela ikusten. Jakina, lehenetsia, sakatua, arazketa-informazioa, agian grabaketa modua bezalako egoerak pilatzen hasten zarenean, CSS handiagoa eta konplexuagoa bihurtzen hasten da. Hortxe etortzen dira kaskadako geruzak. Hona hemen txikitutako adibide bat: @geruza oinarria { .botoia { atzeko planoa: #222; muga-erradioa: %50; zabalera: 40px; altuera: 40px; } }
@geruza aktibo { .botoia.sakatuta { atzeko planoa: #0f0; /* berde distiratsua */ } }
@geruza arazketa { .button::{ ondoren edukia: attr(datu-balioa); letra-tamaina: 12px; kolorea: #fff; } }
Geruzen ordenak garrantzia du: oinarri → aktibo → arazketa.
oinarriak kontrolagailua marrazten du. aktiboak sakatutako egoerak maneiatzen ditu. debug gainjarrietan botatzen du.
Horrela haustea esan nahi du ez zarela espezifikotasun-gerra arraroen aurka borrokatzen. Geruza bakoitzak bere lekua du, eta beti dakizu zerk irabazten duen. Eraikitzen Jar dezagun zerbait pantailan lehenik. Ez du itxura ona izan behar, existitu behar du, lan egiteko zerbait izateko.
Gamepad Cascade debugger
Hori literalki kutxak besterik ez dira. Oraindik ez da zirraragarria, baina heldulekuak ematen dizkigu gero CSS eta JavaScript-ekin harrapatzeko. Ados, kaskadako geruzak erabiltzen ari naiz hemen egoera gehiago gehitzen dituzunean gauzak antolatuta mantentzen dituelako. Hona hemen pasadizo bat:
/* ===================================== CASCADE GERUZEN KONFINIZIOA Ordenak garrantzia du: oinarri → aktibo → arazketa ==================================== */
/* Zehaztu geruzen ordena aldez aurretik */ @geruza oinarria, aktiboa, arazketa;
/* 1. geruza: Oinarrizko estiloak - itxura lehenetsia */ @geruza oinarria { .botoia { atzeko planoa: #333; muga-erradioa: %50; zabalera: 70px; altuera: 70px; pantaila: flex; justifikatu-edukia: zentro; lerrokatu-elementuak: zentroa; }
.pauso { zabalera: 20px; altuera: 70px; atzeko planoa: #333; pantaila: inline-blokea; } }
/* 2. geruza: egoera aktiboak - sakatutako botoiak kudeatzen ditu */ @geruza aktibo { .button.active { atzeko planoa: #0f0; /* Berde bizia sakatzean */ transformatu: eskala(1.1); /* Botoia zertxobait handitzen du */ }
.pause.aktibo { atzeko planoa: #0f0; transformatu: eskalaY(1.1); /* Bertikalki luzatzen da sakatzean */ } }
/* 3. geruza: Araztu gainjartzeak - garatzailearen informazioa */ @geruza arazketa { .button::{ ondoren edukia: attr(datu-balioa); /* Zenbakizko balioa erakusten du */ letra-tamaina: 12px; kolorea: #fff; } }
Planteamendu honen edertasuna geruza bakoitzak helburu argia duela da. Oinarrizko geruzak ezin du inoiz gainidatzi aktiboa, eta aktiboak ezin du inoiz gainidatzi arazketa, berezitasuna edozein dela ere. Honek arazketa-tresnak izan ohi dituzten CSS espezifikotasun gerrak ezabatzen ditu. Orain badirudi multzo batzuk hondo ilun batean eserita daudela. Egia esan, ez da oso txarra.
JavaScript gehitzea JavaScript ordua. Hau da kontrolatzaileak benetan zerbait egiten duena. Hau urratsez urrats eraikiko dugu. 1. urratsa: konfiguratu egoera kudeaketa Lehenik eta behin, aldagaiak behar ditugu arazketa-egoeraren jarraipena egiteko: // ==================================== // ESTATUKO KUDEAKETA // ====================================
utzi korrika = false; // Araztailea aktibo dagoen ala ez kontrolatzen du utzi rafId; // requestAnimationFrame IDa gordetzen du bertan behera uzteko
Aldagai hauek gamepad sarrera etengabe irakurtzen duen animazio begizta kontrolatzen dute. 2. urratsa: Hartu DOM erreferentziak Ondoren, eguneratuko ditugun HTML elementu guztien erreferentziak jasoko ditugu: // ==================================== // DOM ELEMENTUEN ERREFERENTZIAK // ====================================
const btnA = document.getElementById("btn-a"); const btnB = document.getElementById ("btn-b"); const btnX = document.getElementById ("btn-x"); const pause1 = document.getElementById("pause1"); const pause2 = document.getElementById("pause2"); const status = document.getElementById("egoera");
Erreferentzia hauek aurrez aurre gordetzea eraginkorragoa da DOM-a behin eta berriz kontsultatzea baino. 3. urratsa: Gehitu teklatuaren babesa Kontrolagailu fisikorik gabe probatzeko, teklatuko teklak botoiekin mapatuko ditugu: // ==================================== // KEYBOARD FALLBACK (kontrolagailurik gabe probatzeko) // ====================================
const keyMap = { "a": btnA, "b": btnB, "x": btnX, "p": [pause1, pause2] // 'p' teklak bi pausa-barrak kontrolatzen ditu };
Honek interfazea probatzeko aukera ematen digu teklatu bateko teklak sakatuz. 4. urratsa: Sortu eguneratze-begizta nagusia Hemen gertatzen da magia. Funtzio hau etengabe exekutatzen da eta gamepad egoera irakurtzen du: // ==================================== // JOKO EGUNERATZEKO BIZKIZTA NAGUSIA // ====================================
eguneratu funtzioaGamepad() { // Lortu konektatutako gamepad guztiak const gamepads = navigator.getGamepads(); bada (!gamepads) itzuli;
// Erabili konektatutako lehenengo gamepad const gp = gamepads[0];
bada (gp) { // Eguneratu botoiaren egoerak "aktiboa" klasea aldatuz btnA.classList.toggle("aktibo", gp.buttons[0].sakatuta); btnB.classList.toggle("aktiboa", gp.buttons[1].sakatuta); btnX.classList.toggle("aktiboa", gp.buttons[2].sakatuta);
// Kudeatu pausa botoia (botoiaren indizea 9 kontrolagailu gehienetan) const pausePressed = gp.buttons[9].sakatuta; pause1.classList.toggle("aktiboa", pausePressed); pause2.classList.toggle("aktibo", pausePressed);
// Eraiki unean sakatzen diren botoien zerrenda egoera bistaratzeko utzi sakatuta = []; gp.buttons.forEach((btn, i) => { bada (btn.sakatu)pressed.push ("Botoia " + i); });
// Eguneratu egoera-testua botoiren bat sakatzen bada bada (sakatu.luzera > 0) { status.textContent = "Sakatuta: " + pressed.join(", "); } }
// Jarraitu begizta arazlea exekutatzen ari bada bada (korrika) { rafId = requestAnimationFrame(eguneratuGamepad); } }
classList.toggle() metodoak klase aktiboa gehitzen edo kentzen du botoia sakatuta dagoen ala ez, eta horrek gure CSS geruza estiloak abiarazten ditu. 5. urratsa: kudeatu teklatuko gertaerak Gertaera-entzule hauek teklatuaren babesa funtzionatzen dute: // ==================================== // TECLADOKO EKITALDI KUDEATZAILEAK // ====================================
document.addEventListener("keydown", (e) => { bada (gako-mapa[e.tekla]) { // Elementu bakar edo anitz maneiatu bada (Array.isArray(keyMap[e.key])) { keyMap[e.key].forEach(el => el.classList.add("aktiboa")); } bestela { keyMap[e.key].classList.add("aktiboa"); } status.textContent = "Tekla sakatuta: " + e.key.toUpperCase(); } });
document.addEventListener("keyup", (e) => { bada (gako-mapa[e.tekla]) { // Kendu egoera aktiboa tekla askatzen denean bada (Array.isArray(keyMap[e.key])) { keyMap[e.key].forEach(el => el.classList.remove("aktiboa")); } bestela { keyMap[e.key].classList.remove("aktiboa"); } status.textContent = "Gakoa askatuta: " + e.key.toUpperCase(); } });
6. urratsa: Gehitu Hasi/Stop Kontrola Azkenik, arazketa aktibatzeko eta desaktibatzeko modu bat behar dugu: // ==================================== // AKTIBATU/DESAKTIBATU ARAZATZAILEA // ====================================
document.getElementById("toggle").addEventListener ("klik", () => { korrika = !korrika; // Exekutatzen den egoera irauli
bada (korrika) { status.textContent = "Arazgailua martxan..."; eguneratuGamepad(); // Hasi eguneratze-begizta } bestela { status.textContent = "Arazgailua inaktibo"; cancelAnimationFrame(rafId); // Begizta gelditu } });
Beraz, bai, sakatu botoi bat eta distira egiten du. Bultza ezazu makila eta mugitzen da. Hori da. Beste gauza bat: balore gordinak. Batzuetan zenbakiak ikusi nahi dituzu, ez argiak.
Fase honetan, ikusi beharko zenuke:
Pantailako kontrolagailu sinple bat, Haiekin elkarreraginean erreakzionatzen duten botoiak, eta Sakatutako botoien indizeak erakusten dituen hautazko arazketa-irakurketa.
Hau ez hain abstraktua izan dadin, hona hemen pantailako kontrolagailuak denbora errealean erreakzionatzen duen demo azkar bat:
Orain, Hasi grabazioa sakatuta, dena erregistratzen da Gelditu grabazioa sakatu arte. 2. Datuak CSV/JSONra esportatzea Erregistro bat dugunean, gorde nahi dugu.
1. urratsa: Sortu Deskarga Laguntzailea Lehenik eta behin, arakatzailean fitxategien deskargak kudeatzen dituen funtzio laguntzaile bat behar dugu: // ==================================== // FITXATEGIA DESKARGATZEKO LAGUNTZAILEA // ====================================
deskargatuFitxategia (fitxategiaren izena, edukia, mota = "testua/laua") { // Edukitik blob bat sortu const blob = Blob berria ([edukia], { mota }); const url = URL.createObjectURL (blob);
// Sortu aldi baterako deskargarako esteka eta egin klik const a = document.createElement("a"); a.href = url; a.download = fitxategi-izena; a.klik();
// Garbitu objektuaren URLa deskargatu ondoren setTimeout(() => URL.revokeObjectURL(url), 100); }
Funtzio honek zure datuetatik Blob (objektu handi bitar) bat sortuz funtzionatzen du, horren aldi baterako URL bat sortuz eta programazio bidez deskargatzeko esteka batean klik eginez. Garbiketak memoria galduko ez dugula ziurtatzen du. 2. urratsa: kudeatu JSON esportazioa JSON ezin hobea da datuen egitura osoa gordetzeko:
// ==================================== // EXPORTATU JSON gisa // ====================================
document.getElementById ("export-json").addEventListener ("klik", () => { // Egiaztatu esportatzeko ezer dagoen bada (!markoak.luzera) { console.warn("Ez dago grabaziorik esportatzeko erabilgarri."); itzuli; }
// Metadatuekin eta markoekin karga erabilgarria sortu karga konstante = { sortua: data berria().toISOString(), markoak };
// Deskargatu JSON formatuan deskargatuFitxategia( "gamepad-log.json", JSON.stringify(karga, null, 2), "aplikazioa/json" ); });
JSON formatuak dena egituratuta eta erraz analizatzen du, garapenerako tresnetan berriro kargatzeko edo taldekideekin partekatzeko aproposa da. 3. urratsa: kudeatu CSV esportazioa CSV esportazioetarako, datu hierarkikoak errenkada eta zutabeetan berdindu behar ditugu:
//==================================== // EXPORTATU CSV gisa // ====================================
document.getElementById ("export-csv").addEventListener ("klik", () => { // Egiaztatu esportatzeko ezer dagoen bada (!markoak.luzera) { console.warn("Ez dago grabaziorik esportatzeko erabilgarri."); itzuli; }
// Eraiki CSV goiburuko errenkada (denboraren zigilurako zutabeak, botoi guztiak, ardatz guztiak) const headerButtons = frames[0].buttons.map((_, i) => btn${i}); const headerAxes = frames[0].axes.map((_, i) => ardatz${i}); const header = ["t", ...headerButtons, ...headerAxes].join(",") + "\n";
// Eraiki CSV datu errenkadak const rows = frames.map (f => { const btnVals = f.buttons.map (b => b.value); itzuli [f.t, ...btnVals, ...f.axes].join(","); }).join("\n");
// Deskargatu CSV gisa downloadFile("gamepad-log.csv", goiburua + errenkadak, "text/csv"); });
CSV bikaina da datuen analisirako, Excel edo Google Sheets-en zuzenean irekitzen delako, grafikoak sortzeko, datuak iragazteko edo ereduak ikusteko aukera ematen dizulako. Esportatzeko botoiak sartuta daudenez, bi aukera berri ikusiko dituzu panelean: Esportatu JSON eta Esportatu CSV. JSON polita da erregistro gordina zure garapen-tresnetara itzuli nahi baduzu edo egituran sartu nahi baduzu. CSV, berriz, zuzenean Excel edo Google Sheets-en irekitzen da sarrerak grafiko, iragazi edo alderatu ahal izateko. Ondorengo irudiak panela nolakoa den erakusten du kontrol gehigarri horiekin.
3. Snapshot System Batzuetan, ez duzu grabaketa osoa behar, sarrera-egoeren "pantaila-argazki" azkar bat besterik ez. Hor laguntzen du Hartu argazkia botoiak.
Eta JavaScript:
// ==================================== // ARGAZKIA HARTU // ====================================
document.getElementById("snapshot").addEventListener ("klik", () => { // Lortu konektatutako gamepad guztiak const pads = navigator.getGamepads(); const activePads = [];
// Begiztatu eta harrapatu konektatutako gamepad bakoitzaren egoera for (konst gp pads) { bada (!gp) jarraitu; // Saltatu zirrikitu hutsak
activePads.push({ id: gp.id, // Kontrolagailuaren izena/eredua denbora-zigilua: performance.now(), botoiak: gp.buttons.map(b => ({ sakatu: b.sakatu, balio: b.balio })), ardatzak: [...gp.axes] }); }
// Egiaztatu gamepadrik aurkitu ote den bada (!activePads.length) { console.warn("Ez dago gailurik konektatuta argazkia ateratzeko."); alert("Ez da kontroladorerik hauteman!"); itzuli; }
// Saioa hasi eta erabiltzaileari jakinarazi console.log("Snapshot:", activePads); alerta(Ateratako argazkia! ${activePads.length} kontrolagailuak harrapatu dira); });
Snapshot-ek zure kontrolagailuaren egoera zehatza izozten dute une batean. 4. Ghost Sarrera Erreprodukzioa Orain dibertigarria: ghost input replay. Honek erregistro bat hartzen du eta bisualki erreproduzitzen du erreproduzitzaile fantasma batek kontrolagailua erabiliko balu bezala.
JavaScript errepikatzeko: // ==================================== // GOST REPLAY // ====================================
document.getElementById("erreplay").addEventListener ("klik", () => { // Ziurtatu grabaketa bat dugula errepikatzeko bada (!markoak.luzera) { alert("Ez dago erreproduzitzeko grabaketarik!"); itzuli; }
console.log("Mamua errepikatzen hasten...");
// Sinkronizatutako erreprodukziorako pistaren denbora let startTime = performance.now(); utzi frameIndex = 0;
// Animazio-begizta errepikatu funtzioaren urratsa () { const orain = performance.now(); const elapsed = now - startTime;
// Prozesatu orain arte gertatu behar ziren fotograma guztiak bitartean (frameIndex < frames.length && frames[frameIndex].t <= iragana) { const frame = frames[frameIndex];
// Eguneratu UI grabatutako botoien egoerarekin btnA.classList.toggle("aktibo", fotograma.botoiak[0].sakatuta); btnB.classList.toggle("aktiboa", fotograma.botoiak[1].sakatuta); btnX.classList.toggle("aktibo", fotograma.botoiak[2].sakatuta);
// Eguneratu egoera bistaratzea utzi sakatuta = []; frame.buttons.forEach((btn, i) => { if (btn.sakatu) sakatuta.push ("Botoia " + i); }); bada (sakatu.luzera > 0) { status.textContent = "Mamua: " + pressed.join(", "); }
frameIndex++; }
// Jarraitu begizta fotograma gehiago badaude if (frameIndex < frames.length) { eskatuAnimazioMarkoa(urratsa); } bestela { console.log("Erreproduzituamaitu."); status.textContent = "Erreprodukzioa osatuta"; } }
// Hasi errepikapena urratsa(); });
Arazketa apur bat praktikoagoa izan dadin, mamuaren errepikapen bat gehitu dut. Saio bat grabatu ondoren, errepikatu sakatu eta UI-a antzezten ikusi dezakezu, ia erreproduzitzaile fantasma bat pad-a abiarazten ari den bezala. Horretarako, Replay Ghost botoi berri bat agertzen da panelean.
Sakatu Grabatu, nahastu pixka bat kontrolagailuarekin, gelditu, eta gero errepikatu. Interfazeak egin duzun guztiaren oihartzuna besterik ez du egiten, zure sarrerak jarraitzen dituen mamu bat bezala. Zergatik traba gehigarri hauekin?
Grabaketa/esportazioak probalariek zer gertatu den zehatz-mehatz erakustea errazten dute. Argazkiak une batean izozten dira, oso erabilgarriak akats bakanen atzetik zabiltzanean. Ghost replay bikaina da tutorialetarako, irisgarritasun-egiaztapenetarako edo, besterik gabe, kontrol-konfigurazioak elkarren ondoan alderatzeko.
Une honetan, jada ez da demo txukun bat, benetan lanean jar dezakezun zerbait baizik. Mundu errealeko erabilera kasuak Orain asko egin dezakeen arazketa hau dugu. Zuzeneko sarrera erakusten du, erregistroak grabatzen ditu, esportatzen ditu eta baita gauzak errepikatzen ere. Baina benetako galdera hau da: nori axola zaio benetan? Norentzat da erabilgarria? Jokoen garatzaileak Kontrolatzaileak lanaren parte dira, baina arazketa? Normalean mina. Imajinatu borroka-joko konbinazio bat probatzen ari zarela, adibidez ↓ → + zulatu. Otoitz egin beharrean, bi aldiz sakatu duzu modu berean, behin grabatu eta errepikatu. Eginda. Edo JSON erregistroak taldekide batekin trukatzen dituzu zure jokalari anitzeko kodeak bere makinan berdin erreakzionatzen duen egiaztatzeko. Hori izugarria da. Irisgarritasun profesionalak Hau nire bihotzetik hurbil dago. Denek ez dute kontrolagailu "estandarra" batekin jokatzen. Kontrolagailu egokitzaileek seinale bitxiak botatzen dituzte batzuetan. Tresna honekin, zehazki zer gertatzen ari den ikus dezakezu. Irakasleak, ikertzaileak, edonor. Erregistroak har ditzakete, konparatu edo sarrerak elkarren ondoan errepika ditzakete. Bat-batean, gauza ikusezinak agerikoak dira. Kalitatea Bermatzeko Probak Probatzaileek normalean oharrak idazten dituzte: "Hemen botoiak birrindu ditut eta hautsi egin da". Ez da oso lagungarria. Orain? Prentsa zehatzak har ditzakete, erregistroa esportatu eta bidali. Asmatzerik ez. Hezitzaileak Tutorialak edo YouTube bideoak egiten ari bazara, ghost replay urrea da. Literalki esan dezakezu: "Hona hemen kontrolagailuarekin egin nuena", UI-ak gertatzen ari dela erakusten duen bitartean. Azalpenak argiago uzten ditu. Jolasez Harago Eta bai, hau ez da jokoei buruz bakarrik. Jendeak kontrolagailuak erabili ditu robotetarako, arte proiektuetarako eta irisgarritasun interfazeetarako. Gai bera aldi bakoitzean: zer ikusten ari da arakatzaileak? Honekin, ez duzu asmatu behar. Ondorioa Kontrolagailuaren sarrera araztea beti izan da itsu-itsua izatea. DOM edo CSS ez bezala, ez dago inspektore integraturik gamepadetarako; kontsolaren zenbaki gordinak besterik ez dira, zaratan erraz galtzen direnak. HTML, CSS eta JavaScript-eko ehunka lerrorekin, zerbait desberdina eraiki dugu:
Sarrera ikusezinak ikusgai egiten dituen arazte bisuala. Interfazea garbi eta arazketagarri mantentzen duen CSS geruzadun sistema. Hobekuntza multzo bat (grabaketa, esportazioa, argazkiak, ghost replay) demo izatetik garatzaile tresna izatera igotzen dutenak.
Proiektu honek erakusten du noraino irits daitekeen Web Plataformaren boterea CSS Cascade Layers-en sormen apur batekin nahastuz. Osorik azaldu berri dudan tresna kode irekikoa da. GitHub repo klonatu eta zuk zeuk probatu dezakezu. Baina are garrantzitsuagoa dena, zure egin dezakezu. Gehitu zure geruzak. Eraiki zure erreprodukzio logika. Integratu zure jokoaren prototipoarekin. Edo imajinatu ez dudan moduan ere erabili. Irakaskuntzarako, irisgarritasunerako edo datuak aztertzeko. Azken finean, hau ez da soilik gamepadak araztea. Ezkutuko sarrerak argitzea eta garatzaileei sareak oraindik guztiz onartzen ez duen hardwarearekin lan egiteko konfiantza ematea da. Beraz, konektatu kontrolagailua, ireki editorea eta hasi esperimentatzen. Zure nabigatzaileak eta zure CSSak benetan lor dezaketena harrituko zaitu.