Երբ դուք միացնում եք կարգավորիչը, սեղմում եք կոճակները, տեղափոխում փայտիկները, քաշում ձգանները… և որպես մշակող՝ դուք դրանցից ոչ մեկը չեք տեսնում: Բրաուզերը, իհարկե, վերցնում է այն, բայց եթե դուք թվեր չեք գրանցում վահանակում, այն անտեսանելի է: Դա գլխացավանք է Gamepad 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, ակտիվ, կարգաբերում;
@շերտի հիմք { /* ... */ }
@շերտ ակտիվ { /* ... */ }
@շերտի վրիպազերծում { /* ... */ }
Քանի որ յուրաքանչյուր շերտ կուտակվում է կանխատեսելիորեն, դուք միշտ գիտեք, թե որ կանոններն են հաղթում: Այդ կանխատեսելիությունը դարձնում է վրիպազերծումը ոչ միայն հեշտ, այլ իրականում կառավարելի: Մենք լուսաբանել ենք խնդիրը (անտեսանելի, խառնաշփոթ մուտքագրում) և մոտեցումը (տեսողական վրիպազերծիչ, որը կառուցվել է Կասկադի շերտերով): Այժմ մենք քայլ առ քայլ կանցնենք վրիպազերծիչը կառուցելու համար: Debugger-ի հայեցակարգը Թաքնված մուտքագրումը տեսանելի դարձնելու ամենահեշտ ձևը պարզապես այն էկրանին նկարելն է: Դա այն է, ինչ անում է այս վրիպազերծիչը: Կոճակները, ձգանները և ջոյստիկները բոլորն էլ տեսողական տեսք են ստանում:
Սեղմեք A: Շրջանակը լուսավորվում է: Հպեք փայտը. շրջանը սահում է շուրջը: Ձգանը կիսով չափ քաշեք. բարը կիսով չափ լցվում է:
Այժմ դուք չեք նայում 0-ին և 1-ին, այլ իրականում դիտում եք վերահսկիչի արձագանքը ուղիղ եթերում: Իհարկե, երբ դուք սկսում եք կուտակել վիճակներ, ինչպիսիք են լռելյայն, սեղմված, վրիպազերծման տեղեկատվությունը, գուցե նույնիսկ ձայնագրման ռեժիմը, CSS-ը սկսում է ավելի մեծ և բարդ դառնալ: Այստեղ կասկադային շերտերը հարմար են: Ահա մի հանված օրինակ. @շերտի հիմք { .կոճակ { ֆոն՝ #222; սահման-շառավիղ` 50%; լայնությունը՝ 40px; բարձրությունը՝ 40px; } }
@շերտ ակտիվ { .button.սեղմված { ֆոն՝ #0f0; /* վառ կանաչ */ } }
@շերտի վրիպազերծում { .կոճակ::հետո { բովանդակություն՝ attr (տվյալների արժեք); տառաչափը՝ 12px; գույնը՝ #fff; } }
Շերտերի կարգը կարևոր է՝ հիմք → ակտիվ → վրիպազերծում։
բազան նկարում է կարգավորիչը: ակտիվ բռնակներ սեղմված վիճակներ: վրիպազերծումը նետում է ծածկույթների վրա:
Այսպես կոտրելը նշանակում է, որ դուք չեք պայքարում տարօրինակ հատուկ պատերազմների մեջ: Յուրաքանչյուր շերտ ունի իր տեղը, և դուք միշտ գիտեք, թե ինչ է հաղթում: Կառուցելով այն Եկեք նախ ինչ-որ բան տեսնենք էկրանին: Այն պետք չէ լավ տեսք ունենալ, պարզապես պետք է գոյություն ունենա, որպեսզի մենք ինչ-որ բան ունենանք աշխատելու:
Gamepad Cascade Debugger
Դա բառացիորեն պարզապես տուփեր են: Դեռևս հետաքրքիր չէ, բայց այն մեզ հնարավորություն է տալիս ավելի ուշ օգտագործել CSS-ի և JavaScript-ի միջոցով: Լավ, ես այստեղ օգտագործում եմ կասկադային շերտեր, քանի որ այն պահում է իրերը կազմակերպված, երբ ավելացնեք ավելի շատ վիճակներ: Ահա կոպիտ անցում.
/* ==================================== ԿԱՍԿԱԴԻ ՇԵՐՏԵՐԻ ԿԱՐԳԱՎՈՐՈՒՄԸ Կարևոր է պատվերը՝ բազա → ակտիվ → վրիպազերծում =================================== */
/* Նախապես սահմանեք շերտերի կարգը */ @layer base, ակտիվ, կարգաբերում;
/* Շերտ 1. Հիմնական ոճեր - լռելյայն տեսք */ @շերտի հիմք { .կոճակ { ֆոն՝ #333; սահման-շառավիղ` 50%; լայնությունը՝ 70px; բարձրությունը՝ 70px; ցուցադրում: flex; հիմնավորում-բովանդակություն՝ կենտրոն; align-իրեր՝ կենտրոն; }
.դադար { լայնությունը՝ 20px; բարձրությունը՝ 70px; ֆոն՝ #333; ցուցադրում: inline-block; } }
/* Շերտ 2. Ակտիվ վիճակներ - կարգավորում է սեղմված կոճակները */ @շերտ ակտիվ { .button.active { ֆոն՝ #0f0; /* Վառ կանաչ, երբ սեղմված է */ փոխակերպում՝ մասշտաբ (1.1); /* Մի փոքր մեծացնում է կոճակը */ }
.pause.active { ֆոն՝ #0f0; փոխակերպում՝ scaleY (1.1); /* Ձգվում է ուղղահայաց սեղմելիս */ } }
/* Շերտ 3. վրիպազերծել ծածկույթները - մշակողի տեղեկություններ */ @շերտի վրիպազերծում { .կոճակ::հետո { բովանդակություն՝ attr (տվյալների արժեք); /* Ցույց է տալիս թվային արժեքը */ տառաչափը՝ 12px; գույնը՝ #fff; } }
Այս մոտեցման գեղեցկությունն այն է, որ յուրաքանչյուր շերտ ունի հստակ նպատակ: Հիմնական շերտը երբեք չի կարող անտեսել ակտիվը, իսկ ակտիվը երբեք չի կարող վերացնել վրիպազերծումը, անկախ կոնկրետությունից: Սա վերացնում է CSS-ի առանձնահատկությունների պատերազմները, որոնք սովորաբար պատուհասում են վրիպազերծման գործիքներին: Այժմ թվում է, թե որոշ կլաստերներ նստած են մուգ ֆոնի վրա: Անկեղծ ասած, այնքան էլ վատ չէ:
JavaScript-ի ավելացում JavaScript ժամանակ. Սա այն վայրն է, որտեղ վերահսկիչը իրականում ինչ-որ բան է անում: Մենք սա կկառուցենք քայլ առ քայլ: Քայլ 1. Ստեղծեք պետական կառավարում Նախ, մեզ անհրաժեշտ են փոփոխականներ՝ վրիպազերծողի վիճակին հետևելու համար. // ==================================== // ՊԵՏԱԿԱՆ ԿԱՌԱՎԱՐՈՒՄ // ====================================
թող վազում = կեղծ; // Հետևում է, թե արդյոք վրիպազերծիչը ակտիվ է թող rafId; // Պահպանում է requestAnimationFrame ID-ն չեղարկման համար
Այս փոփոխականները կառավարում են անիմացիոն օղակը, որն անընդհատ կարդում է խաղային վահանակի մուտքագրումը: Քայլ 2. Վերցրեք DOM հղումները Հաջորդը, մենք հղումներ ենք ստանում բոլոր HTML տարրերին, որոնք մենք կթարմացնենք. // ==================================== // ԴՈՄ ՏԱՐՐԵՐԻ ՀԻՄՆԱԿԱՆՆԵՐ // ====================================
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. Ավելացնել ստեղնաշարի հետադարձ կապ Առանց ֆիզիկական կարգավորիչի փորձարկման համար մենք ստեղնաշարի ստեղները կնշենք կոճակներին. // ==================================== // KEYBOARD FALLBACK (առանց կարգավորիչի փորձարկման համար) // ====================================
const keyMap = { «a»: btnA, «b»: btnB, «x»: btnX, «p»: [դադար1, դադար2] // «p» ստեղնը կառավարում է դադարի երկու տողերը };
Սա թույլ է տալիս մեզ փորձարկել միջերեսը՝ սեղմելով ստեղնաշարի ստեղները: Քայլ 4. Ստեղծեք հիմնական թարմացման հանգույցը Ահա թե որտեղ է տեղի ունենում կախարդանքը. Այս ֆունկցիան անընդհատ աշխատում է և կարդում է խաղային պահոցի վիճակը. // ==================================== // ՀԻՄՆԱԿԱՆ GAMEPAD UPDATE LOOP // ====================================
ֆունկցիա updateGamepad() { // Ստացեք բոլոր միացված խաղային վահանակները const gamepads = navigator.getGamepads(); եթե (!gamepads) վերադառնան;
// Օգտագործեք առաջին միացված gamepad-ը const gp = gamepads[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].սեղմված; pause1.classList.toggle("ակտիվ", pausePressed); pause2.classList.toggle ("ակտիվ", pausePressed);
// Ստեղծեք ներկայումս սեղմված կոճակների ցանկ՝ կարգավիճակի ցուցադրման համար թող սեղմված = []; gp.buttons.forEach((btn, i) => { եթե (btn.սեղմված)pressed.push ("Button" + i); });
// Թարմացրեք կարգավիճակի տեքստը, եթե որևէ կոճակ սեղմված է եթե (սեղմված. երկարություն > 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 ("ակտիվ")); } ուրիշ { 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 ("ակտիվ")); } ուրիշ { keyMap[e.key].classList.remove(«ակտիվ»); } status.textContent = "Բանալին թողարկվեց. " + e.key.toUpperCase(); } });
Քայլ 6. Ավելացնել Start/Stop Control Վերջապես, մեզ անհրաժեշտ է մի միջոց՝ վրիպազերծիչը միացնելու և անջատելու համար. // ==================================== // ՄԻԱՑՆԵԼ/ԱՆՋԱՏԵԼ ՎՈՒՂԵՐԱՓՈԽՄԱՆԸ // ====================================
document.getElementById("toggle").addEventListener("click", () => { վազում = !վազում; // Շրջեք գործարկման վիճակը
եթե (վազում) { status.textContent = "Վրիպազերծիչն աշխատում է..."; updateGamepad(); // Սկսեք թարմացման հանգույցը } ուրիշ { status.textContent = «Վրիպազերծիչն ակտիվ չէ»; cancelAnimationFrame (rafId); // Դադարեցրեք հանգույցը } });
Այսպիսով, այո, սեղմեք կոճակը և այն փայլում է: Հրել փայտիկը, և այն շարժվում է: Ահա և վերջ։ Եվս մեկ բան՝ հում արժեքներ։ Երբեմն դուք պարզապես ցանկանում եք տեսնել թվեր, ոչ թե լույսեր:
Այս փուլում դուք պետք է տեսնեք.
Պարզ էկրանի վերահսկիչ, Կոճակներ, որոնք արձագանքում են, երբ դուք շփվում եք նրանց հետ, և Ընտրովի վրիպազերծման ընթերցում, որը ցույց է տալիս սեղմված կոճակի ինդեքսները:
Սա ավելի քիչ վերացական դարձնելու համար, ահա էկրանին կարգավորիչի արագ ցուցադրումը, որն արձագանքում է իրական ժամանակում.
Այժմ, սեղմելով «Սկսել ձայնագրումը», ամեն ինչ գրանցվում է, մինչև սեղմեք «Դադարեցնել ձայնագրումը»: 2. Տվյալների արտահանում CSV/JSON Երբ մենք գրանցամատյան ունենանք, մենք կցանկանանք պահպանել այն:
Քայլ 1. Ստեղծեք Ներբեռնման օգնականը Նախ, մեզ անհրաժեշտ է օգնական գործառույթ, որը կարգավորում է բրաուզերում ֆայլերի ներբեռնումը. // ==================================== // Ֆայլի ներբեռնման օգնական // ====================================
ֆունկցիա ներբեռնելՖայլ (ֆայլի անվանում, բովանդակություն, տեսակ = «տեքստ/պարզ») { // Բովանդակությունից բլոբ ստեղծեք const blob = new Blob ([բովանդակություն], {type }); 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("click", () => { // Ստուգեք, արդյոք արտահանելու բան կա if (!frames.length) { console.warn («Արտահանման համար հասանելի ձայնագրություն չկա»); վերադարձ; }
// Ստեղծեք օգտակար բեռ մետատվյալներով և շրջանակներով Const ծանրաբեռնվածություն = { createAt: new Date().toISOSstring(), շրջանակներ };
// Ներբեռնեք որպես ձևաչափված JSON ներբեռնել ֆայլ ( «gamepad-log.json», JSON.stringify (payload, null, 2), «հավելված/json» ); });
JSON ձևաչափը պահպանում է ամեն ինչ կառուցվածքային և հեշտությամբ վերլուծելի՝ դարձնելով այն իդեալական մշակող գործիքներում նորից բեռնելու կամ թիմակիցների հետ կիսվելու համար: Քայլ 3. Կառավարեք CSV արտահանումը CSV արտահանման համար մենք պետք է հարթեցնենք հիերարխիկ տվյալները տողերի և սյունակների մեջ.
//=================================== // ԱՐՏԱՀԱՆՈՒՄ AS CSV // ====================================
document.getElementById("export-csv").addEventListener("click", () => { // Ստուգեք, արդյոք արտահանելու բան կա if (!frames.length) { console.warn («Արտահանման համար հասանելի ձայնագրություն չկա»); վերադարձ; }
// Կառուցեք CSV վերնագրի տող (սյունակներ՝ ժամանակի դրոշմակնիքի, բոլոր կոճակների, բոլոր առանցքների համար) const headerButtons = frames[0].buttons.map((_, i) => btn${i}); const headerAxes = frames[0].axes.map((_, i) => առանցք${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(","); }).միանալ("\n");
// Ներբեռնեք որպես CSV downloadFile («gamepad-log.csv», վերնագիր + տողեր, «տեքստ/csv»); });
CSV-ը փայլուն է տվյալների վերլուծության համար, քանի որ այն բացվում է անմիջապես Excel-ում կամ Google Sheets-ում՝ թույլ տալով ստեղծել գծապատկերներ, զտել տվյալները կամ տեսողականորեն նկատել նախշերը: Այժմ, երբ արտահանման կոճակները միացված են, վահանակի վրա կտեսնեք երկու նոր տարբերակ՝ Արտահանել JSON և Արտահանել CSV: JSON-ը լավ է, եթե ցանկանում եք չմշակված գրանցամատյանը հետ նետել ձեր մշակող գործիքների մեջ կամ շրջել կառուցվածքը: Մյուս կողմից, CSV-ը բացվում է անմիջապես Excel-ի կամ Google Sheets-ի մեջ, որպեսզի կարողանաք գծապատկերում, զտել կամ համեմատել մուտքերը: Հետևյալ նկարը ցույց է տալիս, թե ինչ տեսք ունի վահանակը այդ լրացուցիչ կառավարիչների հետ:
3. Snapshot System Երբեմն ձեզ հարկավոր չէ ամբողջական ձայնագրություն, պարզապես մուտքագրման վիճակների արագ «սքրինշոթ»: Ահա թե որտեղ է օգնում Take Snapshot կոճակը:
Իսկ JavaScript-ը.
// ==================================== // TAKE SNAPSHOT // ====================================
document.getElementById("snapshot").addEventListener("click", () => { // Ստացեք բոլոր միացված խաղային վահանակները const բարձիկներ = navigator.getGamepads(); const activePads = [];
// Անցեք և ֆիքսեք յուրաքանչյուր միացված gamepad-ի վիճակը for (const gp of pads) { եթե (!gp) շարունակվի; // Բաց թողնել դատարկ անցքերը
activePads.push({ id՝ gp.id, // Կարգավորիչի անունը/մոդելը ժամադրոշմ՝ performance.now(), կոճակներ՝ gp.buttons.map(b => ({ սեղմված՝ բ.սեղմված, արժեք՝ բ.արժեք })), axes՝ [...gp.axes] }); }
// Ստուգեք, արդյոք գտնվել են խաղային վահանակներ if (!activePads.length) { console.warn («Պատկերի համար միացված խաղադաշտեր չկան»); alert («Կարգավորիչ չի հայտնաբերվել»); վերադարձ; }
// Մուտք գործեք և տեղեկացրեք օգտվողին console.log ("Snapshot:", activePads); alert(Պատկերն արված է: Գրված է ${activePads.length} կարգավորիչ(ներ):); });
Snapshots-ը սառեցնում է ձեր կարգավորիչի ճշգրիտ վիճակը ժամանակի ընթացքում: 4. Ghost Input Replay Հիմա զվարճալի մեկի համար. ուրվականների մուտքագրման կրկնություն: Սա վերցնում է գրանցամատյան և այն տեսողականորեն ցուցադրում է, կարծես ֆանտոմ նվագարկիչը օգտագործում է վերահսկիչը:
JavaScript վերարտադրման համար. // ==================================== // GHOST REPLAY // ====================================
document.getElementById("replay").addEventListener("click", () => { // Համոզվեք, որ մենք ունենք ձայնագրություն վերարտադրելու համար if (!frames.length) { alert («Ձայնագրություն չկա վերարտադրելու համար»); վերադարձ; }
console.log ("Starting ghost replay...");
// Հետևեք համաժամացված նվագարկման ժամանակին թող startTime = performance.now(); թող frameIndex = 0;
// Կրկնել անիմացիոն հանգույց ֆունկցիայի քայլ() { const now = performance.now(); const elapsed = now - startTime;
// Մշակել բոլոր շրջանակները, որոնք մինչ այժմ պետք է հայտնվեին while (frameIndex < frames.length && frames[frameIndex].t <= անցած) { const շրջանակ = շրջանակներ[frameIndex];
// Թարմացրեք UI-ը ձայնագրված կոճակի վիճակներով btnA.classList.toggle(«ակտիվ», շրջանակ.կոճակներ[0].սեղմված); btnB.classList.toggle(«ակտիվ», շրջանակ.կոճակներ[1].սեղմված); btnX.classList.toggle («ակտիվ», շրջանակ.կոճակներ[2].սեղմված);
// Թարմացնել կարգավիճակի ցուցադրումը թող սեղմված = []; frame.buttons.forEach((btn, i) => { if (btn.pressed) pressed.push("Button" + i); }); եթե (սեղմված. երկարություն > 0) { status.textContent = "Ghost: " + pressed.join(", "); }
frameIndex++; }
// Շարունակեք հանգույցը, եթե ավելի շատ շրջանակներ կան if (frameIndex < frames.length) { requestAnimationFrame (քայլ); } ուրիշ { console.log ("Replayավարտված»); status.textContent = «Վերականգնումն ավարտված է»; } }
// Սկսեք կրկնությունը քայլ (); });
Վրիպազերծումը մի փոքր ավելի գործնական դարձնելու համար ես ավելացրեցի ուրվականների կրկնությունը: Նիստը ձայնագրելուց հետո կարող եք սեղմել «Replay» և դիտել, թե ինչպես է ինտերֆեյսը ցուցադրում այն, գրեթե այնպես, ինչպես ֆանտոմային նվագարկիչը վարում է պահոցը: Դրա համար վահանակում հայտնվում է Replay Ghost-ի նոր կոճակ:
Կտտացրեք Record, մի փոքր խառնվեք կարգավորիչի հետ, կանգ առեք, ապա նորից նվագարկեք: UI-ն ուղղակի արձագանքում է այն ամենին, ինչ դուք արել եք, ինչպես ուրվականը, որը հետևում է ձեր մուտքերին: Ինչու՞ անհանգստանալ այս հավելյալներից:
Ձայնագրումը/արտահանումը հեշտացնում է փորձարկողների համար ճշգրիտ ցույց տալ, թե ինչ է տեղի ունեցել: Պատկերները մի պահ սառչում են, ինչը շատ օգտակար է, երբ հետապնդում եք տարօրինակ վրիպակներ: Ghost replay-ը հիանալի է ձեռնարկների, մատչելիության ստուգումների կամ պարզապես կողք կողքի կառավարման կարգավորումները համեմատելու համար:
Այս պահին դա այլևս պարզապես կոկիկ ցուցադրություն չէ, այլ մի բան, որը դուք կարող եք իրականում գործի դնել: Իրական աշխարհի օգտագործման դեպքեր Այժմ մենք ունենք այս կարգաբերիչը, որը կարող է շատ բան անել: Այն ցույց է տալիս կենդանի մուտքագրում, գրանցում է տեղեկամատյանները, արտահանում դրանք և նույնիսկ վերարտադրում իրերը: Բայց իրական հարցն այն է, թե իրականում ո՞ւմ է դա հետաքրքրում: Ու՞մ համար է սա օգտակար: Խաղի ծրագրավորողներ Կարգավորիչները աշխատանքի մի մասն են, բայց վրիպազերծե՞լ դրանք: Սովորաբար ցավ: Պատկերացրեք, որ դուք փորձարկում եք մարտական խաղի կոմբինացիա, օրինակ՝ ↓ → + դակիչ: Աղոթելու փոխարեն երկու անգամ սեղմել ես նույն կերպ, մեկ անգամ ձայնագրել և նորից նվագարկել։ Կատարված է: Կամ դուք փոխանակում եք JSON տեղեկամատյանները թիմակցի հետ՝ ստուգելու համար, թե արդյոք ձեր բազմախաղացող կոդը նույնն է արձագանքում նրանց ապարատին: Դա հսկայական է: Մատչելիության պրակտիկանտներ Այս մեկն ինձ հոգեհարազատ է. Ոչ բոլորն են խաղում «ստանդարտ» կարգավորիչով: Հարմարվողական կարգավորիչները երբեմն տարօրինակ ազդանշաններ են նետում: Այս գործիքի միջոցով դուք կարող եք ճշգրիտ տեսնել, թե ինչ է տեղի ունենում: Ուսուցիչներ, հետազոտողներ, ովքեր էլ որ լինեն: Նրանք կարող են բռնել տեղեկամատյանները, համեմատել դրանք կամ վերարտադրել մուտքերը կողք կողքի: Հանկարծ ակնհայտ է դառնում անտեսանելի իրերը։ Որակի ապահովման փորձարկում Փորձարկողները սովորաբար գրում են նշումներ, ինչպիսիք են «Ես այստեղ կոճակները տրորեցի, և այն կոտրվեց»: Ոչ շատ օգտակար: Հիմա? Նրանք կարող են գրավել ճշգրիտ մամլիչները, արտահանել տեղեկամատյանը և ուղարկել այն: Ոչ մի գուշակություն: Դաստիարակներ Եթե դուք ձեռնարկներ կամ YouTube-ի տեսանյութեր եք պատրաստում, ապա ուրվականների վերարտադրումը ոսկե է: Դուք կարող եք բառացիորեն ասել, «Ահա, թե ինչ եմ ես արել վերահսկիչի հետ», մինչդեռ UI-ն ցույց է տալիս, որ դա տեղի է ունենում: Բացատրությունները ավելի պարզ է դարձնում: Խաղերից այն կողմ Եվ այո, սա միայն խաղերի մասին չէ: Մարդիկ օգտագործել են կարգավորիչներ ռոբոտների, արվեստի նախագծերի և հասանելիության ինտերֆեյսների համար: Ամեն անգամ նույն խնդիրը. ի՞նչ է իրականում տեսնում զննարկիչը: Դրանով դուք պետք չէ գուշակել. Եզրակացություն Կարգավորիչի մուտքագրման վրիպազերծումը միշտ զգացել է որպես կույր թռչող: Ի տարբերություն DOM-ի կամ CSS-ի, խաղային վահանակների համար ներկառուցված տեսուչ չկա. դա պարզապես հում թվեր են վահանակում, որոնք հեշտությամբ կորչում են աղմուկի մեջ: HTML, CSS և JavaScript-ի մի քանի հարյուր տողով մենք տարբեր բան ենք կառուցել.
Տեսողական վրիպազերծիչ, որը տեսանելի է դարձնում անտեսանելի մուտքերը: Շերտավոր CSS համակարգ, որը պահպանում է UI-ը մաքուր և կարգաբերելի: Բարելավումների մի շարք (ձայնագրում, արտահանում, նկարներ, ուրվականների վերարտադրում), որոնք այն դարձնում են ցուցադրականից մինչև մշակողի գործիք:
Այս նախագիծը ցույց է տալիս, թե որքան հեռու կարող եք գնալ՝ խառնելով Վեբ պլատֆորմի հզորությունը CSS Cascade Layers-ում մի փոքր ստեղծագործականության հետ: Գործիքը, որը ես պարզապես բացատրեցի ամբողջությամբ, բաց կոդով է: Դուք կարող եք կլոնավորել GitHub ռեպո-ն և փորձել այն ինքներդ: Բայց ավելի կարևոր է, որ դուք կարող եք այն դարձնել ձեր սեփականը: Ավելացրեք ձեր սեփական շերտերը: Կառուցեք ձեր սեփական վերարտադրման տրամաբանությունը: Ինտեգրեք այն ձեր խաղի նախատիպի հետ: Կամ նույնիսկ օգտագործել այն այնպես, ինչպես ես չէի պատկերացնում: Դասավանդման, մատչելիության կամ տվյալների վերլուծության համար: Ի վերջո, սա միայն խաղային վահանակների վրիպազերծման մասին չէ: Խոսքը թաքնված մուտքերի վրա լույս սփռելու մասին է և ծրագրավորողներին վստահություն տալով աշխատելու ապարատային սարքերի հետ, որոնք համացանցը դեռևս ամբողջությամբ չի ընդգրկում: Այսպիսով, միացրեք ձեր կարգավորիչը, բացեք ձեր խմբագրիչը և սկսեք փորձարկել: Դուք կարող եք զարմանալ, թե ինչ կարող են իրականում իրականացնել ձեր զննարկիչը և ձեր CSS-ը: