Калі вы падключаеце кантролер, вы націскаеце кнопкі, перамяшчаеце ручкі, націскаеце на куркі... і, як распрацоўшчык, вы нічога гэтага не бачыце. Вядома, браўзэр падхоплівае гэта, але калі вы не запісваеце лічбы ў кансолі, ён нябачны. Гэта галаўны боль з API геймпада. Ён існуе шмат гадоў, і насамрэч ён вельмі магутны. Вы можаце чытаць кнопкі, джойсцікі, куркі, працы. Але большасць людзей да гэтага не дакранаюцца. чаму? Таму што няма зваротнай сувязі. Няма панэлі ў інструментах распрацоўшчыка. Няма дакладнага спосабу даведацца, ці робіць кантролер тое, што вы думаеце. Такое адчуванне, што ляціш усляпую. Гэта мяне настолькі ўразіла, што я пабудаваў невялікі інструмент: Gamepad Cascade Debugger. Замест таго, каб глядзець на выхад кансолі, вы атрымліваеце жывы інтэрактыўны выгляд кантролера. Націсніце што-небудзь, і яно адрэагуе на экран. А з CSS Cascade Layers стылі застаюцца арганізаванымі, таму адладжваць іх лягчэй. У гэтай публікацыі я пакажу вам, чаму адладка кантролераў такая цяжкая, як CSS дапамагае гэта ачысціць і як вы можаце стварыць шматразовы візуальны адладчык для вашых уласных праектаў.
Нават калі вы зможаце зарэгістраваць іх усе, вы хутка атрымаеце нечытэльны кансольны спам. Напрыклад: [0,0,1,0,0,0,5,0,...] [0,0,0,0,1,0,0,...] [0,0,1,0,0,0,0,...]
Ці можаце вы сказаць, якую кнопку націснулі? Магчыма, але толькі пасля напружання вачэй і пропуску некалькіх уводаў. Такім чынам, не, адладка не даецца лёгка, калі гаворка ідзе пра чытанне ўваходных дадзеных. Праблема 3: Адсутнасць структуры Нават калі вы збярэце хуткі візуалізатар, стылі могуць хутка сапсавацца. Станы па змаўчанні, актыўныя і адладкавыя могуць перакрывацца, і без выразнай структуры ваш CSS становіцца нетрывалым і яго цяжка пашыраць. CSS Cascade Layers можа дапамагчы. Яны групуюць стылі ў «слаі», упарадкаваныя па прыярытэтах, таму вы перастаеце змагацца з канкрэтнасцю і здагадвацца: «Чаму мой стыль адладкі не паказваецца?» Замест гэтага вы захоўваеце асобныя праблемы:
База: стандарт кантролера, першапачатковы выгляд. Актыўны: Падсвятленне націснутых кнопак і перамешчаных стыкаў. Адладка: накладкі для распрацоўшчыкаў (напрыклад, лікавыя паказанні, кіраўніцтва і гэтак далей).
Калі б мы вызначалі пласты ў CSS у адпаведнасці з гэтым, мы б мелі: /* ад нізкага да высокага прыярытэту */ @layer base, active, debug;
база @layer { /* ... */ }
@layer актыўны { /* ... */ }
адладка @layer { /* ... */ }
Паколькі кожны пласт складваецца прадказальна, вы заўсёды ведаеце, якія правілы выйграюць. Такая прадказальнасць робіць адладку не проста прасцейшай, але і кіраванай. Мы разгледзелі праблему (нябачны, бязладны ўвод) і падыход (візуальны адладчык, створаны з дапамогай каскадных слаёў). Зараз мы крок за крокам азнаёмімся з працэсам стварэння адладчыка. Канцэпцыя адладчыка Самы просты спосаб зрабіць схаваны ўвод бачным - проста намаляваць яго на экране. Вось што робіць гэты адладчык. Кнопкі, трыгеры і джойсцікі атрымліваюць візуальны выгляд.
Націсніце A: загараецца круг. Падштурхніце палку: круг слізгае. Націсніце курок напалову: слупок запаўняецца напалову.
Цяпер вы не глядзіце на 0 і 1, а рэальна назіраеце за рэакцыяй кантролера ўжывую. Вядома, як толькі вы пачынаеце назапашваць такія стану, як па змаўчанні, націснутая інфармацыя, інфармацыя аб адладцы, магчыма, нават рэжым запісу, CSS пачынае павялічвацца і складаней. Вось дзе каскадныя пласты прыходзяць на карысць. Вось скарочаны прыклад: база @layer { .button { фон: #222; радыус мяжы: 50%; шырыня: 40 пікселяў; вышыня: 40 пікселяў; } }
@layer актыўны { .button.pressed { фон: #0f0; /* ярка-зялёны */ } }
адладка @layer { .button::after { змест: attr(значэнне даных); памер шрыфта: 12 пікселяў; колер: #fff; } }
Парадак слаёў мае значэнне: база → актыўны → адладка.
база малюе кантролер. актыўны апрацоўвае націснутыя стану. адладка кідае накладкі.
Такое раздзяленне азначае, што вы не змагаецеся за дзіўныя спецыфічныя войны. Кожны пласт мае сваё месца, і вы заўсёды ведаеце, што выйграе. Будаўніцтва It Out Давайце спачатку пакажам што-небудзь на экране. Яму не трэба добра выглядаць — трэба толькі існаваць, каб нам было з чым працаваць.
Каскадны адладчык геймпада
Гэта літаральна проста скрынкі. Пакуль не захапляльна, але гэта дае нам магчымасць захапіць пазней з CSS і JavaScript. Добра, я выкарыстоўваю тут каскадныя слаі, таму што яны арганізуюць усё пасля таго, як вы дадасце больш станаў. Вось грубы пас:
/* ==================================== НАСТРОЙКА КАСКАДНЫХ СЛАЁЎ Парадак мае значэнне: база → актыўны → адладка ==================================== */
/* Вызначце парадак слаёў загадзя */ @layer base, active, debug;
/* Узровень 1: Базавыя стылі - выгляд па змаўчанні */ база @layer { .button { фон: #333; радыус мяжы: 50%; шырыня: 70 пікселяў; вышыня: 70 пікселяў; дысплей: гнуткі; апраўдаць змест: па цэнтры; align-items: center; }
.pause { шырыня: 20 пікселяў; вышыня: 70 пікселяў; фон: #333; адлюстраванне: inline-block; } }
/* Узровень 2: Актыўны стан - апрацоўвае націснутыя кнопкі */ @layer актыўны { .button.active { фон: #0f0; /* Ярка-зялёны пры націску */ пераўтварэнне: маштаб (1.1); /* Злёгку павялічвае кнопку */ }
.pause.active { фон: #0f0; пераўтварэнне: scaleY(1.1); /* Расцягваецца вертыкальна пры націску */ } }
/* Узровень 3: накладкі адладкі - інфармацыя пра распрацоўшчыка */ адладка @layer { .button::after { змест: attr(значэнне даных); /* Паказвае лікавае значэнне */ памер шрыфта: 12 пікселяў; колер: #fff; } }
Хараство гэтага падыходу ў тым, што кожны пласт мае дакладнае прызначэнне. Базавы ўзровень ніколі не можа перавызначыць актыўны, а актыўны ніколі не можа перавызначыць адладкавы, незалежна ад спецыфікі. Гэта пазбаўляе ад войнаў за спецыфіку CSS, якія звычайна пакутуюць ад інструментаў адладкі. Цяпер здаецца, што некаторыя кластары сядзяць на цёмным фоне. Шчыра кажучы, нядрэнна.
Даданне JavaScript Час JavaScript. Вось дзе кантролер сапраўды нешта робіць. Мы будзем будаваць гэта крок за крокам. Крок 1: Наладзьце кіраванне дзяржавай Па-першае, нам патрэбныя зменныя для адсочвання стану адладчыка: // ==================================== // ДЗЯРЖАЎНАЕ КІРАВАННЕ // ====================================
хай працуе = ілжыва; // Адсочвае, ці актыўны адладчык няхай rafId; // Захоўвае ID requestAnimationFrame для адмены
Гэтыя зменныя кіруюць цыклам анімацыі, які пастаянна счытвае ўвод геймпада. Крок 2: Захоп DOM References Далей мы атрымаем спасылкі на ўсе элементы HTML, якія мы будзем абнаўляць: // ==================================== // Спасылкі на элементы DOM // ====================================
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("статус");
Захаванне гэтых спасылак загадзя больш эфектыўна, чым паўторны запыт DOM. Крок 3: Дадайце запасную клавіятуру Для тэставання без фізічнага кантролера мы супаставім клавішы клавіятуры з кнопкамі: // ==================================== // РЭЗЕРВНАЯ КЛАВІЯТУРА (для тэставання без кантролера) // ====================================
const keyMap = { "a": btnA, "b": btnB, "x": btnX, "p": [pause1, pause2] // клавіша 'p' кіруе абедзвюма палосамі паўзы };
Гэта дазваляе праверыць карыстацкі інтэрфейс, націскаючы клавішы на клавіятуры. Крок 4: Стварыце асноўны цыкл абнаўлення Вось дзе адбываецца чараўніцтва. Гэтая функцыя працуе пастаянна і счытвае стан геймпада: // ==================================== // АСНОЎНЫ ЦЫКЛ АБНАЎЛЕННЯ ГЕЙМПАДА // ====================================
функцыя updateGamepad() { // Атрымаць усе падлучаныя геймпады const gamepads = navigator.getGamepads(); калі (!геймпады) вярнуцца;
// Выкарыстоўвайце першы падлучаны геймпад const gp = геймпады [0];
калі (gp) { // Абнавіць стан кнопкі шляхам пераключэння класа «актыўны». btnA.classList.toggle("актыўны", gp.buttons[0].націснуты); btnB.classList.toggle("актыўны", gp.buttons[1].націснуты); btnX.classList.toggle("актыўны", gp.buttons[2].націснуты);
// Кіраванне кнопкай паўзы (індэкс кнопкі 9 на большасці кантролераў) const pausePressed = gp.buttons[9].pressed; pause1.classList.toggle("актыўны", pausePressed); pause2.classList.toggle("актыўны", pausePressed);
// Стварэнне спісу націснутых кнопак для адлюстравання стану няхай націснута = []; gp.buttons.forEach((btn, i) => { калі (btn.pressed)pressed.push("Кнопка " + i); });
// Абнавіць тэкст статусу, калі націснута якая-небудзь кнопка if (pressed.length > 0) { status.textContent = "Націснута: " + pressed.join(", "); } }
// Працягнуць цыкл, калі адладчык працуе калі (працуе) { rafId = requestAnimationFrame(updateGamepad); } }
Метад classList.toggle() дадае або выдаляе актыўны клас у залежнасці ад таго, ці націснута кнопка, што запускае нашы стылі пласта CSS. Крок 5: Апрацоўка падзей клавіятуры Гэтыя слухачы падзей робяць працу рэзервовай клавіятуры: // ==================================== // АБРАБОТЧЫКІ ПАДЗЕЙ КЛАВІЯТУРЫ // ====================================
document.addEventListener("keydown", (e) => { if (keyMap[e.key]) { // Апрацоўка аднаго або некалькіх элементаў if (Array.isArray(keyMap[e.key])) { keyMap[e.key].forEach(el => el.classList.add("active")); } яшчэ { keyMap[e.key].classList.add("актыўны"); } status.textContent = "Націснутая клавіша: " + e.key.toUpperCase(); } });
document.addEventListener("keyup", (e) => { if (keyMap[e.key]) { // Выдаліць актыўны стан, калі ключ адпушчаны if (Array.isArray(keyMap[e.key])) { keyMap[e.key].forEach(el => el.classList.remove("active")); } яшчэ { keyMap[e.key].classList.remove("актыўны"); } status.textContent = "Ключ выпушчаны: " + e.key.toUpperCase(); } });
Крок 6: Дадайце кантроль Пуск/Стоп Нарэшце, нам патрэбны спосаб уключаць і выключаць адладчык: // ==================================== // УКЛЮЧЫЦЬ/ВЫКЛЮЧАЦЬ АДЛАДЗІК // ====================================
document.getElementById("пераключыць").addEventListener("клік", () => { бег = !бег; // Перавярнуць запушчаны стан
калі (працуе) { status.textContent = "Адладчык працуе..."; абнаўленнеGamepad(); // Запускаем цыкл абнаўлення } яшчэ { status.textContent = "Адладчык неактыўны"; cancelAnimationFrame(rafId); // Спыніць цыкл } });
Так, націсніце кнопку, і яна засвеціцца. Націсніце палку, і яна рухаецца. Вось і ўсё. Яшчэ адна рэч: сырыя каштоўнасці. Часам проста хочацца бачыць лічбы, а не святло.
На гэтым этапе вы павінны ўбачыць:
Просты экранны кантролер, Кнопкі, якія рэагуюць, калі вы з імі ўзаемадзейнічаеце, і Дадатковае счытванне адладкі, якое паказвае індэксы націснутых кнопак.
Каб зрабіць гэта менш абстрактным, вось кароткая дэманстрацыя экраннага кантролера, які рэагуе ў рэжыме рэальнага часу:
Цяпер, націснуўшы "Пачаць запіс", усё запісваецца ў журнал, пакуль вы не націснеце "Спыніць запіс". 2. Экспарт дадзеных у CSV/JSON Калі ў нас будзе журнал, мы захочам яго захаваць.
Крок 1: Стварыце Download Helper Па-першае, нам патрэбна дапаможная функцыя, якая апрацоўвае загрузку файлаў у браўзеры: // ==================================== // ПАМОЧНІК СПАМПУВАННЯ ФАЙЛА // ====================================
функцыя downloadFile(імя файла, кантэнт, тып = "тэкст/звычайны") { // Стварэнне кроплі з змесціва const blob = new Blob([кантэнт], {тып}); const url = URL.createObjectURL(blob);
// Стварыце часовую спасылку для загрузкі і націсніце яе const a = document.createElement("a"); a.href = URL; a.download = імя файла; a.click();
// Ачысціць URL аб'екта пасля загрузкі setTimeout(() => URL.revokeObjectURL(url), 100); }
Гэтая функцыя працуе, ствараючы Blob (вялікі двайковы аб'ект) з вашых даных, генеруючы для яго часовы URL і праграмна націскаючы спасылку для загрузкі. Ачыстка гарантуе, што мы не страцім памяць. Крок 2: апрацуйце экспарт JSON JSON ідэальна падыходзіць для захавання поўнай структуры дадзеных:
// ==================================== // ЭКСПАРТ ЯК JSON // ====================================
document.getElementById("export-json").addEventListener("клік", () => { // Праверце, ці ёсць што-небудзь для экспарту калі (!frames.length) { console.warn("Недаступны запіс для экспарту."); вяртанне; }
// Стварэнне карыснай нагрузкі з метададзенымі і фрэймамі const карысная нагрузка = { createdAt: новая дата().toISOString(), кадраў };
// Спампаваць у фармаце JSON спампаваць файл( "геймпад-log.json", JSON.stringify(карысная нагрузка, нуль, 2), "прыкладанне/json" ); });
У фармаце JSON усё структуравана і лёгка аналізуецца, што робіць яго ідэальным для загрузкі назад у інструменты распрацоўшчыка або абмену з таварышамі па камандзе. Крок 3: апрацуйце экспарт CSV Для экспарту CSV нам трэба звесці іерархічныя даныя ў радкі і слупкі:
//==================================== // ЭКСПАРТ ЯК CSV // ====================================
document.getElementById("export-csv").addEventListener("клік", () => { // Праверце, ці ёсць што-небудзь для экспарту калі (!frames.length) { console.warn("Недаступны запіс для экспарту."); вяртанне; }
// Стварэнне радка загалоўка CSV (слупкі для меткі часу, усе кнопкі, усе восі) const headerButtons = frames[0].buttons.map((_, i) => btn${i}); const headerAxes = frames[0].axes.map((_, i) => axis${i}); const header = ["t", ...headerButtons, ...headerAxes].join(",") + "\n";
// Стварэнне радкоў дадзеных CSV const rows = frames.map(f => { const btnVals = f.buttons.map(b => b.value); return [f.t, ...btnVals, ...f.axes].join(","); }).join("\n");
// Спампаваць як CSV downloadFile("gamepad-log.csv", загаловак + радкі, "тэкст/csv"); });
CSV выдатна падыходзіць для аналізу даных, таму што ён адкрываецца непасрэдна ў Excel або Google Sheets, дазваляючы ствараць дыяграмы, фільтраваць даныя або візуальна выяўляць шаблоны. Цяпер, калі з'явіліся кнопкі экспарту, вы ўбачыце дзве новыя опцыі на панэлі: Экспарт JSON і Экспарт CSV. JSON добры, калі вы хочаце вярнуць неапрацаваны журнал назад у інструменты распрацоўшчыка або пашукаць структуру. CSV, з іншага боку, адкрываецца прама ў Excel або Google Sheets, каб вы маглі складаць дыяграмы, фільтраваць або параўноўваць уведзеныя дадзеныя. На наступным малюнку паказана, як выглядае панэль з гэтымі дадатковымі элементамі кіравання.
3. Сістэма маментальных здымкаў Часам вам не патрэбна поўная запіс, проста кароткі «скрыншот» стану ўводу. Тут дапамагае кнопка "Зрабіць здымак".
І JavaScript:
// ==================================== // ЗРАБІЦЬ ЗДЫМ // ====================================
document.getElementById("здымак").addEventListener("клік", () => { // Атрымаць усе падлучаныя геймпады const pads = navigator.getGamepads(); const activePads = [];
// Праглядайце і фіксуйце стан кожнага падлучанага геймпада for (const gp калодак) { калі (!gp) працягваць; // Прапусціць пустыя слоты
activePads.push({ id: gp.id, // Імя/мадэль кантролера пазнака часу: performance.now(), кнопкі: gp.buttons.map(b => ({ націснуты: б.націснуты, значэнне: б.значэнне })), восі: [...gp.axes] }); }
// Праверце, ці знойдзены геймпады калі (!activePads.length) { console.warn("Няма падлучаных геймпадаў для здымка."); alert("Контролер не выяўлены!"); вяртанне; }
// Запіс і апавяшчэнне карыстальніка console.log("Здымак:", activePads); абвестка(Зроблены здымак! Захоплены кантролер(ы) ${activePads.length}.); });
Здымкі фіксуюць дакладны стан вашага кантролера ў пэўны момант часу. 4. Паўтор уводу прывіда Зараз цікавае: паўтор уводу прывіда. Гэта бярэ журнал і прайгравае яго візуальна, як быццам фантомны прайгравальнік выкарыстоўвае кантролер.
JavaScript для прайгравання: // ==================================== // Паўтор ПРЫВІДА // ====================================
document.getElementById("паўтор").addEventListener("клік", () => { // Пераканайцеся, што ў нас ёсць запіс для прайгравання калі (!frames.length) { alert("Няма запісу для прайгравання!"); вяртанне; }
console.log("Пачатак прайгравання прывіда...");
// Адсочванне часу для сінхранізаванага прайгравання няхай startTime = performance.now(); няхай frameIndex = 0;
// Прайграць цыкл анімацыі функцыя step() { const зараз = performance.now(); const прайшло = зараз - час пачатку;
// Апрацоўка ўсіх кадраў, якія павінны былі адбыцца да гэтага часу пакуль (frameIndex < frames.length && frames[frameIndex].t <= прайшло) { const frame = frames[frameIndex];
// Абнаўленне карыстальніцкага інтэрфейсу з дапамогай запісаных станаў кнопак btnA.classList.toggle("актыўны", frame.buttons[0].націснуты); btnB.classList.toggle("актыўны", frame.buttons[1].націснуты); btnX.classList.toggle("актыўны", frame.buttons[2].націснуты);
// Адлюстраванне стану абнаўлення няхай націснута = []; frame.buttons.forEach((btn, i) => { if (btn.pressed) pressed.push("Кнопка " + i); }); if (pressed.length > 0) { status.textContent = "Прывід: " + pressed.join(", "); }
frameIndex++; }
// Працягнуць цыкл, калі ёсць больш кадраў if (frameIndex < frames.length) { requestAnimationFrame(крок); } яшчэ { console.log("Паўторскончана."); status.textContent = "Паўтор завершаны"; } }
// Пачаць паўтор крок(); });
Каб зрабіць адладку больш практычнай, я дадаў прывіднае прайграванне. Пасля таго, як вы запісалі сеанс, вы можаце націснуць «Паўтор» і назіраць, як карыстальніцкі інтэрфейс выконвае гэта, амаль як фантомны гулец працуе па пэдах. Для гэтага на панэлі з'яўляецца новая кнопка Replay Ghost.
Націсніце "Запіс", трохі павазіцца з кантролерам, спыніцеся, а потым прайграйце. Карыстальніцкі інтэрфейс проста паўтарае ўсё, што вы рабілі, як прывід, які сочыць за вашымі ўводамі. Навошта турбавацца з гэтымі дадатковымі паслугамі?
Запіс/экспарт дазваляе тэстарам лёгка паказаць, што менавіта адбылося. Здымкі замарожваюць на імгненне ў часе, што вельмі карысна, калі вы шукаеце дзіўныя памылкі. Паўтор Ghost выдатна падыходзіць для навучальных дапаможнікаў, праверкі даступнасці або проста для параўнання налад кіравання побач.
На дадзены момант гэта ўжо не проста прыгожая дэманстрацыя, але тое, што вы сапраўды можаце папрацаваць. Выпадкі выкарыстання ў рэальным свеце Цяпер у нас ёсць гэты адладчык, які можа многае. Ён паказвае жывы ўвод, запісвае журналы, экспартуе іх і нават прайгравае рэчы. Але сапраўднае пытанне: каго гэта хвалюе? Каму гэта карысна? Распрацоўшчыкі гульняў Кантролеры з'яўляюцца часткай працы, але адладжваць іх? Звычайна боль. Уявіце, што вы выпрабоўваеце камбінацыю баявых гульняў, напрыклад ↓ → + удар. Замест таго, каб маліцца, вы двойчы націскаеце яго такім жа чынам, запісваеце адзін раз і прайграваеце. Гатова. Або вы абменьваецеся журналамі JSON з таварышам па камандзе, каб праверыць, ці рэагуе ваш шматкарыстальніцкі код аднолькава на іх машыне. Гэта велізарна. Спецыялісты па даступнасці Гэта мне блізка да сэрца. Не ўсе гуляюць са «стандартным» кантролерам. Адаптыўныя кантролеры часам выдаюць дзіўныя сігналы. З дапамогай гэтага інструмента вы можаце дакладна бачыць, што адбываецца. Настаўнікі, даследчыкі, хто заўгодна. Яны могуць захопліваць журналы, параўноўваць іх або прайграваць уводныя дадзеныя побач. Раптам нябачныя рэчы становяцца відавочнымі. Тэставанне якасці Тэсціроўшчыкі звычайна пішуць нататкі кшталту «Я націснуў тут гузікі, і яны зламаліся». Не вельмі дапамагае. Цяпер? Яны могуць фіксаваць дакладныя націскі, экспартаваць часопіс і адпраўляць яго. Ніякай здагадкі. Педагогі Калі вы ствараеце навучальныя дапаможнікі або відэа на YouTube, прайграванне прывідаў - гэта золата. Вы можаце літаральна сказаць: «Вось што я зрабіў з кантролерам», а інтэрфейс паказвае, што гэта адбываецца. Робіць тлумачэнні больш зразумелымі. Па-за гульнямі І так, гэта не толькі пра гульні. Людзі выкарыстоўвалі кантролеры для робатаў, мастацкіх праектаў і інтэрфейсаў спецыяльных магчымасцей. Кожны раз адна і тая ж праблема: што насамрэч бачыць браўзер? З гэтым вам не трэба гадаць. Заключэнне Адладка ўводу кантролера заўсёды была падобна на палёт ўсляпую. У адрозненне ад DOM або CSS, няма ўбудаванага інспектара для геймпадаў; гэта проста сырыя лічбы ў кансолі, якія лёгка губляюцца ў шуме. З дапамогай некалькіх сотняў радкоў HTML, CSS і JavaScript мы стварылі нешта іншае:
Візуальны адладчык, які робіць нябачныя ўваходы бачнымі. Шматслаёвая сістэма CSS, якая падтрымлівае карыстальніцкі інтэрфейс чыстым і адладжаным. Набор удасканаленняў (запіс, экспарт, здымкі, прайграванне прывідаў), якія ператвараюць яго з дэма-версіі ў інструмент распрацоўшчыка.
Гэты праект паказвае, наколькі далёка вы можаце зайсці, змяшаўшы моц вэб-платформы з крыху крэатыву ў CSS Cascade Layers. Інструмент, які я толькі што растлумачыў цалкам, з'яўляецца адкрытым зыходным кодам. Вы можаце кланаваць рэпазітар GitHub і паспрабаваць на сабе. Але што больш важна, вы можаце зрабіць гэта самастойна. Дадайце ўласныя пласты. Стварыце ўласную логіку прайгравання. Інтэгруйце яго з прататыпам вашай гульні. Ці нават выкарыстоўваць яго так, як я не ўяўляў. Для навучання, даступнасці або аналізу даных. У рэшце рэшт, гэта не толькі адладка геймпадаў. Гаворка ідзе пра асвятленне схаваных уводаў і прадастаўленне распрацоўнікам упэўненасці ў працы з апаратным забеспячэннем, якое ў сетцы яшчэ не цалкам ахоплена. Такім чынам, падключыце кантролер, адкрыйце рэдактар і пачынайце эксперыментаваць. Вы можаце быць здзіўлены тым, чаго сапраўды можа дасягнуць ваш браўзер і ваш CSS.