როდესაც აერთებთ კონტროლერს, ამუშავებთ ღილაკებს, ამოძრავებთ ჯოხებს, აჭერთ ტრიგერებს… და როგორც დეველოპერი, ვერაფერს ხედავთ. რა თქმა უნდა, ბრაუზერი ირჩევს მას, მაგრამ თუ კონსოლში ნომრებს არ ჩაწერთ, ის უხილავია. ეს არის თავის ტკივილი 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-ში ამის მიხედვით, გვექნებოდა: /* ყველაზე დაბალიდან უმაღლეს პრიორიტეტამდე */ @ფენის ბაზა, აქტიური, გამართვა;

@ფენის საფუძველი { /* ... */ }

@ფენა აქტიური { /* ... */ }

@ფენის გამართვა { /* ... */ }

იმის გამო, რომ თითოეული ფენა დაწყობილია პროგნოზირებად, თქვენ ყოველთვის იცით, რომელი წესები იმარჯვებს. ეს პროგნოზირებადობა ხდის გამართვას არა მხოლოდ უფრო მარტივ, არამედ რეალურად მართვადს. ჩვენ გავაშუქეთ პრობლემა (უხილავი, ბინძური შეყვანა) და მიდგომა (კასკადი ფენებით აშენებული ვიზუალური გამართვა). ახლა ჩვენ გავივლით ნაბიჯ-ნაბიჯ პროცესს გამართვის შესაქმნელად. Debugger-ის კონცეფცია ფარული შეყვანის ხილვადობის უმარტივესი გზაა მისი უბრალოდ ეკრანზე დახატვა. ეს არის ის, რასაც აკეთებს ეს გამართვა. ღილაკები, ტრიგერები და ჯოისტიკები ვიზუალს იძენს.

დააჭირეთ A: წრე ანათებს. აწიეთ ჯოხი: წრე სრიალებს გარშემო. ჩახმახი ნახევრად გაიყვანეთ: ზოლი ნახევრად ივსება.

ახლა თქვენ არ უყურებთ 0-ებსა და 1-ებს, მაგრამ რეალურად უყურებთ კონტროლერის რეაქციას პირდაპირ ეთერში. რა თქმა უნდა, როგორც კი დაიწყებთ ისეთი მდგომარეობების დაგროვებას, როგორიცაა ნაგულისხმევი, დაჭერილი, გამართვის ინფორმაცია, შესაძლოა ჩაწერის რეჟიმიც კი, CSS უფრო დიდი და რთული გახდება. სწორედ აქ გამოდგება კასკადის ფენები. აქ არის მოხსნილი მაგალითი: @ფენის საფუძველი { .ღილაკი { ფონი: #222; საზღვარი-რადიუსი: 50%; სიგანე: 40px; სიმაღლე: 40px; } }

@ფენა აქტიური { .ღილაკი.დაჭერილი { ფონი: #0f0; /* ნათელი მწვანე */ } }

@ფენის გამართვა { .ღილაკი:: შემდეგ { შინაარსი: attr(data-value); შრიფტის ზომა: 12px; ფერი: #fff; } }

ფენების წესრიგს აქვს მნიშვნელობა: ბაზა → აქტიური → გამართვა.

ბაზა ხატავს კონტროლერს. აქტიური ამუშავებს დაჭერილ მდგომარეობას. გამართვის აგდებს გადაფარვაზე.

მისი ასე დაშლა ნიშნავს, რომ თქვენ არ ებრძვით უცნაურ სპეციფიკურ ომებს. თითოეულ ფენას აქვს თავისი ადგილი და თქვენ ყოველთვის იცით რა იმარჯვებს. აშენება მოდი ჯერ რაღაც გამოვიჩინოთ ეკრანზე. არ არის აუცილებელი, რომ კარგად გამოიყურებოდეს - უბრალოდ უნდა არსებობდეს, რომ ჩვენ გვქონდეს რაიმე სამუშაო.

Gamepad Cascade Debugger

A
B
X

გამმართველი არააქტიურია

ეს ფაქტიურად მხოლოდ ყუთებია. ჯერ არ არის ამაღელვებელი, მაგრამ ის გვაძლევს სახელურებს, რომ მოგვიანებით ავიღოთ CSS და JavaScript. კარგი, მე ვიყენებ კასკადის შრეებს აქ, რადგან ის ინახავს პერსონალის ორგანიზებას მას შემდეგ, რაც დაამატებთ მეტ მდგომარეობას. აი უხეში გადასასვლელი:

/* =================================== კასკადის ფენების დაყენება შეკვეთა მნიშვნელოვანია: ბაზა → აქტიური → გამართვა =================================== */

/* წინასწარ განსაზღვრეთ ფენების რიგი */ @ფენის ბაზა, აქტიური, გამართვა;

/* Layer 1: Base styles - ნაგულისხმევი გარეგნობა */ @ფენის საფუძველი { .ღილაკი { ფონი: #333; საზღვარი-რადიუსი: 50%; სიგანე: 70px; სიმაღლე: 70px; ჩვენება: flex; დასაბუთება-შინაარსი: ცენტრი; align-items: ცენტრი; }

.პაუზა { სიგანე: 20px; სიმაღლე: 70px; ფონი: #333; ჩვენება: inline-block; } }

/* ფენა 2: აქტიური მდგომარეობები - ამუშავებს დაჭერილ ღილაკებს */ @ფენა აქტიური { .ღილაკი.აქტიური { ფონი: #0f0; /* ღია მწვანე ფერის დაჭერისას */ ტრანსფორმაცია: მასშტაბი (1.1); /* ოდნავ ადიდებს ღილაკს */ }

.პაუზა.აქტიური { ფონი: #0f0; ტრანსფორმაცია: scaleY(1.1); /* იჭიმება ვერტიკალურად დაჭერისას */ } }

/* ფენა 3: გადაფარვების გამართვა - დეველოპერის ინფორმაცია */ @ფენის გამართვა { .ღილაკი:: შემდეგ { შინაარსი: attr(data-value); /* აჩვენებს ციფრულ მნიშვნელობას */ შრიფტის ზომა: 12px; ფერი: #fff; } }

ამ მიდგომის სილამაზე ის არის, რომ თითოეულ ფენას აქვს მკაფიო დანიშნულება. საბაზისო ფენა ვერასოდეს არღვევს აქტიურს და აქტიური ვერასოდეს არღვევს გამართვას, მიუხედავად სპეციფიკისა. ეს გამორიცხავს CSS სპეციფიკურ ომებს, რომლებიც ჩვეულებრივ აწუხებს გამართვის ინსტრუმენტებს. ახლა, როგორც ჩანს, რამდენიმე კლასტერი ზის მუქ ფონზე. პატიოსნად, არც ისე ცუდი.

JavaScript-ის დამატება JavaScript დრო. ეს არის სადაც კონტროლერი რეალურად აკეთებს რაღაცას. ჩვენ ავაშენებთ ამას ეტაპობრივად. ნაბიჯი 1: დააყენეთ სახელმწიფო მენეჯმენტი პირველ რიგში, ჩვენ გვჭირდება ცვლადები, რათა თვალყური ადევნოთ გამართვის მდგომარეობას: // ==================================== // სახელმწიფო მენეჯმენტი // ====================================

ნება გაშვებული = ყალბი; // თვალყურს ადევნებს, არის თუ არა გამამართველი აქტიური let rafId; // ინახავს requestAnimationFrame ID-ს გაუქმებისთვის

ეს ცვლადები აკონტროლებენ ანიმაციის ციკლს, რომელიც განუწყვეტლივ კითხულობს გეიმპედის შეყვანას. ნაბიჯი 2: აიღეთ DOM ცნობები შემდეგი, ჩვენ ვიღებთ მითითებებს ყველა HTML ელემენტზე, რომელსაც განვაახლებთ: // ==================================== // DOM ELEMENT REFERENCES // ====================================

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": [pause1, pause2] // 'p' ღილაკი აკონტროლებს ორივე პაუზის ზოლს };

ეს საშუალებას გვაძლევს შევამოწმოთ UI კლავიატურაზე ღილაკების დაჭერით. ნაბიჯი 4: შექმენით ძირითადი განახლების ციკლი აი სად ხდება მაგია. ეს ფუნქცია მუშაობს განუწყვეტლივ და კითხულობს გეიმპდის მდგომარეობას: // ==================================== // MAIN GAMEPAD UPDATE ციკლი // ====================================

ფუნქცია updateGamepad() { // მიიღეთ ყველა დაკავშირებული გეიმპედი const gamepads = navigator.getGamepads(); თუ (!gamepads) დაბრუნდება;

// გამოიყენეთ პირველი დაკავშირებული გეიმპედი const gp = gamepads[0];

თუ (gp) { // განახლების ღილაკის მდგომარეობები "აქტიური" კლასის გადართვით btnA.classList.toggle("active", gp.buttons[0].დაჭერილი); btnB.classList.toggle("active", gp.buttons[1].დაჭერილია); btnX.classList.toggle("active", gp.buttons[2].დაჭერილია);

// პაუზის ღილაკი (ღილაკის ინდექსი 9 უმეტეს კონტროლერებზე) const pausePressed = gp.buttons[9].დაჭერილი; pause1.classList.toggle("active", pausePressed); pause2.classList.toggle("active", pausePressed);

// შექმენით ამჟამად დაჭერილი ღილაკების სია სტატუსის ჩვენებისთვის დაჭერით = []; gp.buttons.forEach((btn, i) => { თუ (btn.დაჭერილია)დაჭერილი.ბიჭერი ("ღილაკი" + i); });

// განაახლეთ სტატუსის ტექსტი, თუ რომელიმე ღილაკზეა დაჭერილი თუ (დაჭერით.სიგრძე > 0) { status.textContent = "დაჭერილია: " + pressed.join(", "); } }

// გააგრძელეთ მარყუჟი, თუ გამართული მუშაობს თუ (გაშვებული) { rafId = requestAnimationFrame(updateGamepad); } }

classList.toggle() მეთოდი ამატებს ან შლის აქტიურ კლასს ღილაკზე დაჭერის საფუძველზე, რაც იწვევს ჩვენი CSS ფენის სტილებს. ნაბიჯი 5: კლავიატურის მოვლენების მართვა ღონისძიების ეს მსმენელები კლავიატურას ამუშავებენ: // ==================================== // KEYBOARD EVENT HANDLERS // ====================================

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("დაწკაპუნება", () => { გაშვებული = !გარბენი; // გადაატრიალეთ გაშვებული მდგომარეობა

თუ (გაშვებული) { status.textContent = "გამშვები მუშაობს..."; updateGamepad(); // განახლების ციკლის დაწყება } სხვა { status.textContent = "გამმართველი არააქტიურია"; cancelAnimationFrame(rafId); // ციკლის შეჩერება } });

ჰო, დააჭირე ღილაკს და ანათებს. დააწექი ჯოხი და ის მოძრაობს. ესე იგი. კიდევ ერთი რამ: ნედლი ღირებულებები. ზოგჯერ თქვენ უბრალოდ გინდათ იხილოთ რიცხვები და არა შუქები.

ამ ეტაპზე თქვენ უნდა ნახოთ:

მარტივი ეკრანის კონტროლერი, ღილაკები, რომლებიც რეაგირებენ მათთან ურთიერთობისას და არასავალდებულო გამართვის წაკითხვა, რომელიც აჩვენებს დაჭერილი ღილაკის ინდექსებს.

იმისათვის, რომ ეს ნაკლებად აბსტრაქტული იყოს, აქ არის ეკრანზე კონტროლერის რეაქციის სწრაფი დემო ვერსია რეალურ დროში:

ახლა ჩაწერის დაწყებაზე დაჭერით ყველაფერი იწერება, სანამ არ დააჭერთ ჩაწერის შეწყვეტას. 2. მონაცემთა ექსპორტი CSV/JSON-ში როგორც კი გვექნება ჟურნალი, ჩვენ გვინდა მისი შენახვა.

ნაბიჯი 1: შექმენით ჩამოტვირთვის დამხმარე პირველ რიგში, ჩვენ გვჭირდება დამხმარე ფუნქცია, რომელიც ამუშავებს ფაილების ჩამოტვირთვას ბრაუზერში: // ==================================== // FILE DOWNLOAD HELPER // ====================================

ფუნქცია downloadFile (ფაილის სახელი, შინაარსი, ტიპი = "ტექსტი/უბრალო") { // შიგთავსიდან ბლომის შექმნა const blob = new Blob([content], {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("დაწკაპუნება", () => { // შეამოწმეთ არის თუ არა რაიმე ექსპორტისთვის if (!frames.length) { console.warn ("არ არის ხელმისაწვდომი ჩანაწერი ექსპორტისთვის."); დაბრუნება; }

// შექმენით დატვირთვა მეტამონაცემებით და ფრეიმებით მუდმივი დატვირთვა = { შეიქმნა at: new Date().toISOString(), ჩარჩოები };

// ჩამოტვირთეთ JSON ფორმატით ფაილის ჩამოტვირთვა ( "gamepad-log.json", JSON.stringify(payload, null, 2), "აპლიკაცია/json" ); });

JSON ფორმატი ინახავს ყველაფერს სტრუქტურულად და ადვილად გასაანალიზებლად, რაც მას იდეალურს ხდის დეველოპერის ინსტრუმენტებში დასაბრუნებლად ან თანაგუნდელებთან გასაზიარებლად. ნაბიჯი 3: CSV ექსპორტის მართვა CSV ექსპორტისთვის, ჩვენ უნდა გავაბრტყოთ იერარქიული მონაცემები რიგებად და სვეტებად:

//==================================== // EXPORT AS CSV // ====================================

document.getElementById("export-csv").addEventListener("დაწკაპუნება", () => { // შეამოწმეთ არის თუ არა რაიმე ექსპორტისთვის 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); დაბრუნება [f.t, ...btnVals, ...f.axes].join(","); }).join("\n");

// ჩამოტვირთვა როგორც CSV downloadFile ("gamepad-log.csv", სათაური + რიგები, "ტექსტი/csv"); });

CSV ბრწყინვალეა მონაცემთა ანალიზისთვის, რადგან ის იხსნება პირდაპირ Excel-ში ან Google Sheets-ში, რაც საშუალებას გაძლევთ შექმნათ სქემები, გაფილტროთ მონაცემები ან დააფიქსიროთ შაბლონები ვიზუალურად. ახლა, როდესაც ექსპორტის ღილაკები ჩართულია, პანელზე ნახავთ ორ ახალ ვარიანტს: Export JSON და Export CSV. JSON კარგია, თუ გსურთ დაუმუშავებელი ჟურნალის გადაგდება თქვენს დეველოპერის ინსტრუმენტებში ან სტრუქტურის გარშემო. მეორეს მხრივ, CSV იხსნება პირდაპირ Excel-ში ან Google Sheets-ში, ასე რომ თქვენ შეგიძლიათ ჩაწეროთ, გაფილტროთ ან შეადაროთ შეყვანები. შემდეგი ფიგურა გვიჩვენებს, თუ როგორ გამოიყურება პანელი ამ დამატებითი კონტროლით.

3. Snapshot სისტემა ზოგჯერ არ გჭირდებათ სრული ჩაწერა, უბრალოდ შეყვანის მდგომარეობების სწრაფი „სკრინშოტი“. სწორედ აქ ეხმარება ღილაკი "Snapshot"-ის გადაღება.

და JavaScript:

// ==================================== // TAKE SNAPSHOT // ====================================

document.getElementById("snapshot").addEventListener("დაწკაპუნება", () => { // მიიღეთ ყველა დაკავშირებული გეიმპედი const pads = navigator.getGamepads(); const activePads = [];

// გადახედეთ და დააფიქსირეთ თითოეული დაკავშირებული გეიმპედის მდგომარეობა for (const gp of pads) { თუ (!gp) გაგრძელდება; // ცარიელი სლოტების გამოტოვება

activePads.push({ id: gp.id, // კონტროლერის სახელი/მოდელი დროის ანაბეჭდი: performance.now(), ღილაკები: gp.buttons.map(b => ({ დაჭერილი: ბ.დაჭერილი, ღირებულება: ბ.ღირებულება })) ცულები: [...gp.axes] }); }

// შეამოწმეთ, ნაპოვნია თუ არა სათამაშო პანელები if (!activePads.length) { console.warn("სნეპშოტისთვის არ არის დაკავშირებული სათამაშო პანელები."); alert ("კონტროლერი არ არის აღმოჩენილი!"); დაბრუნება; }

// შესვლა და შეატყობინეთ მომხმარებელს console.log("Snapshot:", activePads); alert(ფოტო გადაღებულია! გადაღებული ${activePads.length} კონტროლერი(ები).); });

Snapshots ყინავს თქვენი კონტროლერის ზუსტ მდგომარეობას დროის ერთ მომენტში. 4. Ghost Input Replay ახლა სახალისო: ghost input replay. ეს იღებს ჟურნალს და უკრავს ვიზუალურად ისე, თითქოს მოჩვენებითი მოთამაშე იყენებდა კონტროლერს.

JavaScript განმეორებისთვის: // ==================================== // GHOST REPLAY // ====================================

document.getElementById("გამეორება").addEventListener("დაწკაპუნება", () => { // დარწმუნდით, რომ გვაქვს ჩანაწერი ხელახლა დასაკრავად if (!frames.length) { alert ("არ არის ჩანაწერი გასამეორებლად!"); დაბრუნება; }

console.log ("მოჩვენებების გამეორების დაწყება...");

// აკონტროლეთ დრო სინქრონიზებული დაკვრისთვის მოდით startTime = performance.now(); მოდით frameIndex = 0;

// ანიმაციური ციკლის გამეორება ფუნქციის ნაბიჯი() { const now = performance.now(); const elapsed = now - startTime;

// დაამუშავეთ ყველა ფრეიმი, რომელიც აქამდე უნდა მომხდარიყო while (frameIndex < frames.length && frames[frameIndex].t <= გასული) { const frame = ჩარჩოები[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 ("გამეორებადასრულდა."); status.textContent = "გამეორება დასრულებულია"; } }

// გამეორების დაწყება ნაბიჯი(); });

იმისთვის, რომ გამართვა უფრო პრაქტიკული ყოფილიყო, მე დავამატე ghost replay. სესიის ჩაწერის შემდეგ, შეგიძლიათ დააჭიროთ გამეორებას და უყუროთ ინტერფეისის მოქმედებას, თითქმის ისე, როგორც მოჩვენებითი პლეერი მუშაობს ბალიშზე. ამისთვის პანელზე გამოჩნდება ახალი Replay Ghost ღილაკი.

დააწკაპუნეთ ჩანაწერზე, ცოტა აურიეთ კონტროლერს, გააჩერეთ და შემდეგ კვლავ დაუკარით. UI უბრალოდ ეხმიანება ყველაფერს, რაც თქვენ გააკეთეთ, როგორც მოჩვენება, რომელიც მიჰყვება თქვენს შეყვანას. რატომ აწუხებთ ამ დამატებით?

ჩაწერა/ექსპორტი ტესტერებს უადვილებს ზუსტად აჩვენონ რა მოხდა. სნეპშოტები იყინება დროის მომენტში, ძალიან სასარგებლოა, როცა უცნაურ შეცდომებს დევნით. Ghost-ის გამეორება შესანიშნავია გაკვეთილებისთვის, ხელმისაწვდომობის შემოწმებისთვის ან უბრალოდ კონტროლის პარამეტრების გვერდიგვერდ შედარებისთვის.

ამ ეტაპზე, ეს აღარ არის უბრალოდ სუფთა დემო ვერსია, არამედ ის, რაც რეალურად შეგიძლიათ განახორციელოთ. რეალურ სამყაროში გამოყენების შემთხვევები ახლა ჩვენ მივიღეთ ეს გამართვა, რომელსაც ბევრის გაკეთება შეუძლია. ის აჩვენებს პირდაპირ შეყვანას, ჩაწერს ჟურნალებს, ახორციელებს მათ ექსპორტს და კიდევ იმეორებს პერსონალს. მაგრამ ნამდვილი კითხვაა: ვის აინტერესებს სინამდვილეში? ვისთვის არის ეს სასარგებლო? თამაშის დეველოპერები კონტროლერები სამუშაოს ნაწილია, მაგრამ მათი გამართვა? ჩვეულებრივ ტკივილი. წარმოიდგინეთ, რომ თქვენ ცდილობთ საბრძოლო თამაშის კომბინაციას, როგორიცაა ↓ → + პუნჩი. ლოცვის ნაცვლად, თქვენ დააჭერთ მას ორჯერ ერთნაირად, ჩაწერთ ერთხელ და ხელახლა უკრავთ. შესრულებულია. ან შეცვალეთ JSON ჟურნალები თანაგუნდელთან, რათა შეამოწმოთ, თქვენი მრავალმოთამაშის კოდი იგივე რეაგირებს მათ აპარატზე. ეს უზარმაზარია. ხელმისაწვდომობის პრაქტიკოსები ეს ჩემს გულთან ახლოსაა. ყველა არ თამაშობს „სტანდარტულ“ კონტროლერთან. ადაპტაციური კონტროლერები ხანდახან უცნაურ სიგნალებს აგდებენ. ამ ხელსაწყოს საშუალებით თქვენ ხედავთ ზუსტად რა ხდება. მასწავლებლები, მკვლევარები, ვინც არ უნდა იყოს. მათ შეუძლიათ აითვისონ ჟურნალები, შეადარონ ისინი ან გაიმეორონ შენატანები გვერდიგვერდ. მოულოდნელად, უხილავი ნივთები აშკარა ხდება. ხარისხის უზრუნველყოფის ტესტირება ტესტერები, როგორც წესი, წერენ შენიშვნებს, როგორიცაა: „მე აქ ღილაკები დავამარცხე და ის გატყდა“. არ არის ძალიან სასარგებლო. ახლა? მათ შეუძლიათ ზუსტი პრესის დაჭერა, ჟურნალის ექსპორტი და გაგზავნა. არავითარი გამოცნობა. განმანათლებლები თუ თქვენ აკეთებთ გაკვეთილებს ან YouTube-ის ვიდეოებს, ghost replay არის ოქრო. თქვენ შეგიძლიათ სიტყვასიტყვით თქვათ, "აი, რა გავაკეთე მე კონტროლერთან", ხოლო UI აჩვენებს, რომ ეს ხდება. ახსნა-განმარტებებს უფრო ნათელს ხდის. თამაშების მიღმა დიახ, ეს არ ეხება მხოლოდ თამაშებს. ხალხმა გამოიყენა კონტროლერები რობოტებისთვის, ხელოვნების პროექტებისთვის და ხელმისაწვდომობის ინტერფეისებისთვის. ყოველ ჯერზე იგივე პრობლემა: რას ხედავს ბრაუზერი სინამდვილეში? ამასთან, თქვენ არ გჭირდებათ გამოცნობა. დასკვნა კონტროლერის შეყვანის გამართვა ყოველთვის იგრძნობოდა, როგორც ბრმა. DOM-ისა და CSS-ისგან განსხვავებით, სათამაშო პადებისთვის ჩაშენებული ინსპექტორი არ არის; ეს არის მხოლოდ დაუმუშავებელი რიცხვები კონსოლში, რომლებიც ადვილად იკარგება ხმაურში. რამდენიმე ასეული ხაზით HTML, CSS და JavaScript, ჩვენ ავაშენეთ რაღაც განსხვავებული:

ვიზუალური გამართვა, რომელიც ხილულს ხდის უხილავ შენატანს. ფენიანი CSS სისტემა, რომელიც ინარჩუნებს UI სუფთა და გამართვას. გაუმჯობესებების კომპლექტი (ჩაწერა, ექსპორტი, სნეპშოტები, მოჩვენებათა გამეორება), რომელიც ამაღლებს მას დემოდან დეველოპერის ინსტრუმენტამდე.

ეს პროექტი გვიჩვენებს, თუ რამდენად შორს შეგიძლიათ წახვიდეთ ვებ პლატფორმის სიმძლავრის შერევით CSS Cascade Layers-ში მცირე კრეატიულობით. ინსტრუმენტი, რომელიც ახლახან ავხსენი მთლიანად, არის ღია წყარო. შეგიძლიათ GitHub-ის რეპოს კლონირება და თავად სცადოთ. მაგრამ რაც მთავარია, თქვენ შეგიძლიათ გააკეთოთ ის საკუთარი. დაამატეთ თქვენი საკუთარი ფენები. შექმენით საკუთარი გამეორების ლოგიკა. გააერთიანეთ იგი თქვენი თამაშის პროტოტიპთან. ან თუნდაც ისე გამოვიყენო, როგორიც არ წარმომედგინა. სწავლების, ხელმისაწვდომობის ან მონაცემთა ანალიზისთვის. დღის ბოლოს, ეს არ არის მხოლოდ თამაშის პანელების გამართვა. საუბარია ფარულ შენატანებზე შუქის გაშუქებაზე და დეველოპერებს თავდაჯერებულობის მინიჭებაზე, რათა იმუშაონ აპარატურასთან, რომელსაც ვები ჯერ კიდევ არ მოიცავს. ასე რომ, შეაერთეთ თქვენი კონტროლერი, გახსენით თქვენი რედაქტორი და დაიწყეთ ექსპერიმენტები. შეიძლება გაგიკვირდეთ, რისი მიღწევა შეუძლია თქვენს ბრაუზერს და თქვენს CSS-ს.

You May Also Like

Enjoyed This Article?

Get weekly tips on growing your audience and monetizing your content — straight to your inbox.

No spam. Join 138,000+ creators. Unsubscribe anytime.

Create Your Free Bio Page

Join 138,000+ creators on Seemless.

Get Started Free