នៅពេលអ្នកដោតឧបករណ៍បញ្ជា អ្នកចុចប៊ូតុង រំកិលដំបង ទាញគន្លឹះ... ហើយក្នុងនាមជាអ្នកអភិវឌ្ឍន៍ អ្នកមិនឃើញវាទេ។ កម្មវិធីរុករកតាមអ៊ីនធឺណិតកំពុងយកវាឡើង ប្រាកដណាស់ ប៉ុន្តែលុះត្រាតែអ្នកកត់ត្រាលេខនៅក្នុងកុងសូល វាមិនអាចមើលឃើញបានទេ។ នោះគឺជាការឈឺក្បាលជាមួយនឹង 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,...]

តើអ្នកអាចប្រាប់បានទេថាប៊ូតុងអ្វីត្រូវបានចុច? ប្រហែលជា ប៉ុន្តែបន្ទាប់ពីច្របាច់ភ្នែករបស់អ្នក ហើយបាត់ការបញ្ចូលមួយចំនួន។ ដូច្នេះទេ ការកែកំហុសមិនងាយស្រួលទេ នៅពេលនិយាយអំពីការអានធាតុចូល។ បញ្ហាទី ៣៖ កង្វះរចនាសម្ព័ន្ធ ទោះបីជាអ្នកដាក់រូបភាពរហ័សរួមគ្នាក៏ដោយ រចនាប័ទ្មអាចមានភាពរញ៉េរញ៉ៃយ៉ាងឆាប់រហ័ស។ ស្ថានភាពលំនាំដើម សកម្ម និងបញ្ហាអាចត្រួតលើគ្នា ហើយដោយគ្មានរចនាសម្ព័ន្ធច្បាស់លាស់ CSS របស់អ្នកក្លាយជាផុយ និងពិបាកក្នុងការពង្រីក។ CSS Cascade Layers អាចជួយបាន។ ពួកគេដាក់រចនាប័ទ្មទៅជា "ស្រទាប់" ដែលត្រូវបានតម្រៀបតាមអាទិភាព ដូច្នេះអ្នកឈប់ប្រយុទ្ធនឹងភាពជាក់លាក់ ហើយស្មានថា "ហេតុអ្វីរចនាប័ទ្មបំបាត់កំហុសរបស់ខ្ញុំមិនបង្ហាញ?" ផ្ទុយទៅវិញ អ្នករក្សាការបារម្ភដាច់ដោយឡែកពីគ្នា៖

មូលដ្ឋាន៖ ស្តង់ដាររបស់ឧបករណ៍បញ្ជា រូបរាងដំបូង។ សកម្ម៖ រំលេចសម្រាប់ប៊ូតុងដែលបានចុច និងដំបងដែលបានផ្លាស់ទី។ បំបាត់កំហុស៖ ការត្រួតលើគ្នាសម្រាប់អ្នកអភិវឌ្ឍន៍ (ឧ. ការអានជាលេខ ការណែនាំ និងដូច្នេះនៅលើ)។

ប្រសិនបើ​យើង​កំណត់​ស្រទាប់​ក្នុង CSS តាម​នេះ យើង​នឹង​មាន៖ /* អទិភាពទាបបំផុតទៅខ្ពស់បំផុត*/ @layer base, សកម្ម, បំបាត់កំហុស;

@ស្រទាប់មូលដ្ឋាន { /*...*/ }

@layer សកម្ម { /*...*/ }

@layer debug { /*...*/ }

ដោយ​សារ​ស្រទាប់​នីមួយៗ​មាន​ការ​ព្យាករណ៍ អ្នក​តែង​តែ​ដឹង​ថា​ច្បាប់​ណា​ឈ្នះ។ ការព្យាករណ៍នោះធ្វើឱ្យការបំបាត់កំហុសមិនត្រឹមតែងាយស្រួលប៉ុណ្ណោះទេ ប៉ុន្តែតាមពិតអាចគ្រប់គ្រងបាន។ យើងបានគ្របដណ្តប់បញ្ហា (មើលមិនឃើញ ការបញ្ចូលរញ៉េរញ៉ៃ) និងវិធីសាស្រ្ត (ឧបករណ៍បំបាត់កំហុសដែលមើលឃើញដែលបង្កើតឡើងដោយស្រទាប់ Cascade) ។ ឥឡូវ​នេះ យើង​នឹង​ដើរ​តាម​ដំណើរ​ការ​មួយ​ជំហាន​ម្តងៗ​ដើម្បី​បង្កើត​កម្មវិធី​បំបាត់​កំហុស។ គំនិតបំបាត់កំហុស មធ្យោបាយងាយស្រួលបំផុតដើម្បីធ្វើឱ្យការបញ្ចូលដែលលាក់អាចមើលឃើញគឺគ្រាន់តែគូរវានៅលើអេក្រង់។ នោះហើយជាអ្វីដែលអ្នកបំបាត់កំហុសនេះធ្វើ។ ប៊ូតុង កេះ និងយ៉យស្ទីក សុទ្ធតែទទួលបានរូបភាព។

ចុច A: រង្វង់មួយភ្លឺឡើង។ រុញដំបង៖ រង្វង់រំកិលជុំវិញ។ ទាញគន្លឹះពាក់កណ្តាល៖ របារមួយបំពេញពាក់កណ្តាល។

ឥឡូវនេះ អ្នកមិនកំពុងសម្លឹងមើល 0s និង 1s ទេ ប៉ុន្តែតាមពិតការមើលឧបករណ៍បញ្ជាមានប្រតិកម្មផ្ទាល់។ ជាការពិតណាស់ នៅពេលដែលអ្នកចាប់ផ្តើមដាក់នៅលើរដ្ឋដូចជា default, pressed, debug info ប្រហែលជាសូម្បីតែរបៀបថតក៏ដោយ CSS ចាប់ផ្តើមកាន់តែធំ និងស្មុគស្មាញ។ នោះហើយជាកន្លែងដែលស្រទាប់ល្បាក់ចូលមកស្រួល។ នេះ​ជា​ឧទាហរណ៍​ដែល​បាន​ដក​ចេញ៖ @ស្រទាប់មូលដ្ឋាន { .ប៊ូតុង { ផ្ទៃខាងក្រោយ៖ #222; កាំព្រំដែន៖ ៥០%; ទទឹង: 40px; កម្ពស់: 40px; } }

@layer សកម្ម { .button.pressed { ផ្ទៃខាងក្រោយ៖ #0f0; /* បៃតងភ្លឺ */ } }

@layer debug { .button::after { មាតិកា៖ attr (ទិន្នន័យតម្លៃ); ទំហំពុម្ពអក្សរ៖ ១២ ភីច; ពណ៌៖ #ffff; } }

លំដាប់ស្រទាប់មានសារៈសំខាន់៖ មូលដ្ឋាន → សកម្ម → បំបាត់កំហុស។

មូលដ្ឋានទាញឧបករណ៍បញ្ជា។ ចំណុចទាញសកម្មដែលចុចរដ្ឋ។ បំបាត់​កំហុស​បោះ​លើ​ការ​ត្រួត​គ្នា។

ការបំបែកវាដូចនេះមានន័យថា អ្នកមិនប្រយុទ្ធនឹងសង្រ្គាមជាក់លាក់ចម្លែកនោះទេ។ ស្រទាប់នីមួយៗមានកន្លែងរបស់វា ហើយអ្នកតែងតែដឹងថាអ្វីដែលឈ្នះ។ ការកសាងវាចេញ ចូរយើងទទួលបានអ្វីមួយនៅលើអេក្រង់ជាមុនសិន។ វា​មិន​ចាំ​បាច់​មើល​ទៅ​ល្អ​ទេ - គ្រាន់​តែ​ត្រូវ​ការ​ដើម្បី​ឱ្យ​យើង​មាន​អ្វី​ដែល​ត្រូវ​ធ្វើ​ការ​ជាមួយ។

Gamepad Cascade Debugger

A
B
X

កម្មវិធីបំបាត់កំហុសអសកម្ម

នោះគ្រាន់តែជាប្រអប់។ មិនគួរឱ្យរំភើបនៅឡើយទេប៉ុន្តែវាផ្តល់ឱ្យយើងនូវចំណុចទាញដើម្បីចាប់យកនៅពេលក្រោយជាមួយ CSS និង JavaScript ។ មិនអីទេ ខ្ញុំកំពុងប្រើស្រទាប់ល្បាក់នៅទីនេះ ព្រោះវារក្សាការរៀបចំរបស់របរនៅពេលដែលអ្នកបន្ថែមរដ្ឋបន្ថែមទៀត។ នេះ​ជា​ការ​ឆ្លង​កាត់​ដ៏​លំបាក៖

/* ========================================== ការដំឡើងស្រទាប់ CASCADE បញ្ហាលំដាប់៖ មូលដ្ឋាន → សកម្ម → បំបាត់កំហុស =================================== */

/* កំណត់លំដាប់ស្រទាប់ខាងមុខ */ @layer base, សកម្ម, បំបាត់កំហុស;

/* ស្រទាប់ទី 1៖ រចនាប័ទ្មមូលដ្ឋាន - រូបរាងលំនាំដើម */ @ស្រទាប់មូលដ្ឋាន { .ប៊ូតុង { ផ្ទៃខាងក្រោយ៖ #333; កាំព្រំដែន៖ ៥០%; ទទឹង: 70px; កម្ពស់: 70px; បង្ហាញ៖ flex; justify-content: center; តម្រឹមធាតុ៖ កណ្តាល; }

.ផ្អាក { ទទឹង: 20px; កម្ពស់: 70px; ផ្ទៃខាងក្រោយ៖ #333; បង្ហាញ៖ inline-block; } }

/* ស្រទាប់ទី 2៖ ស្ថានភាពសកម្ម - គ្រប់គ្រងប៊ូតុងដែលបានចុច */ @layer សកម្ម { .button.active { ផ្ទៃខាងក្រោយ៖ #0f0; /* ពណ៌បៃតងភ្លឺនៅពេលចុច */ ការបំប្លែង៖ មាត្រដ្ឋាន (១.១); /* ពង្រីក​ប៊ូតុង​បន្តិច */ }

.pause.active { ផ្ទៃខាងក្រោយ៖ #0f0; ការបំប្លែង៖ មាត្រដ្ឋានY(១.១); /* លាតសន្ធឹងបញ្ឈរនៅពេលចុច */ } }

/* Layer 3: Debug overlays - developer info */ @layer debug { .button::after { មាតិកា៖ attr (ទិន្នន័យតម្លៃ); /* បង្ហាញតម្លៃលេខ */ ទំហំពុម្ពអក្សរ៖ ១២ ភីច; ពណ៌៖ #ffff; } }

ភាពស្រស់ស្អាតនៃវិធីសាស្រ្តនេះគឺថាស្រទាប់នីមួយៗមានគោលបំណងច្បាស់លាស់។ ស្រទាប់មូលដ្ឋានមិនអាចបដិសេធសកម្មបានទេ ហើយសកម្មមិនអាចបដិសេធការបំបាត់កំហុសបានទេ ដោយមិនគិតពីភាពជាក់លាក់។ នេះលុបបំបាត់សង្គ្រាមជាក់លាក់ CSS ដែលជាធម្មតាញាំញីឧបករណ៍បំបាត់កំហុស។ ឥឡូវនេះ វាហាក់ដូចជាក្រុមមួយចំនួនកំពុងអង្គុយនៅលើផ្ទៃខាងក្រោយងងឹត។ និយាយតាមត្រង់ទៅ មិនអាក្រក់ពេកទេ។

ការបន្ថែម JavaScript ពេលវេលា JavaScript ។ នេះគឺជាកន្លែងដែលឧបករណ៍បញ្ជាពិតជាធ្វើអ្វីមួយ។ យើង​នឹង​បង្កើត​នេះ​ជា​ជំហានៗ។ ជំហានទី 1: រៀបចំការគ្រប់គ្រងរដ្ឋ ជាដំបូង យើងត្រូវការអថេរ ដើម្បីតាមដានស្ថានភាពរបស់អ្នកបំបាត់កំហុស៖ // ========================================== // ការគ្រប់គ្រងរដ្ឋ // ==========================================

អនុញ្ញាតឱ្យរត់ = មិនពិត; // តាមដានថាតើកម្មវិធីបំបាត់កំហុសសកម្មឬអត់ អនុញ្ញាតឱ្យ rafId; // រក្សាទុក requestAnimationFrame ID សម្រាប់ការលុបចោល

អថេរទាំងនេះគ្រប់គ្រងរង្វិលជុំចលនាដែលអានការបញ្ចូល gamepad ជាបន្តបន្ទាប់។ ជំហានទី 2៖ ចាប់យកឯកសារយោង DOM បន្ទាប់មក យើងទទួលបានឯកសារយោងទៅធាតុ 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៖ បន្ថែម Keyboard Fallback សម្រាប់​ការ​សាកល្បង​ដោយ​គ្មាន​ឧបករណ៍​បញ្ជា​រាងកាយ យើង​នឹង​គូស​ផែនទី​ក្ដារចុច​ទៅ​ប៊ូតុង៖ // ========================================== // KEYBOARD FALLBACK (សម្រាប់ការធ្វើតេស្តដោយគ្មានឧបករណ៍បញ្ជា) // ==========================================

const keyMap = { "a": btnA, "b": btnB, "x": btnX, "p": [pause1, pause2] // 'p' key controls របារផ្អាកទាំងពីរ };

វាអនុញ្ញាតឱ្យយើងសាកល្បង UI ដោយចុចគ្រាប់ចុចនៅលើក្តារចុច។ ជំហានទី 4: បង្កើត Main Update Loop នេះជាកន្លែងដែលវេទមន្តកើតឡើង។ មុខងារនេះដំណើរការជាបន្តបន្ទាប់ និងអានស្ថានភាព gamepad៖ // ========================================== // MAIN GAMEPAD ធ្វើបច្ចុប្បន្នភាពរង្វិលជុំ // ==========================================

មុខងារអាប់ដេតGamepad() { // ទទួលបាន gamepads ដែលបានភ្ជាប់ទាំងអស់។ const gamepads = navigator.getGamepads(); ប្រសិនបើ (!gamepads) ត្រឡប់មកវិញ;

// ប្រើបន្ទះហ្គេមដែលបានភ្ជាប់ដំបូង const gp = gamepads[0];

ប្រសិនបើ (gp) { // ធ្វើបច្ចុប្បន្នភាពប៊ូតុងបញ្ជាក់ដោយបិទបើកថ្នាក់ "សកម្ម" btnA.classList.toggle("សកម្ម", gp.buttons[0].pressed); btnB.classList.toggle("សកម្ម", gp.buttons[1].pressed); btnX.classList.toggle("សកម្ម", gp.buttons[2].pressed);

// ដោះស្រាយប៊ូតុងផ្អាក (ប៊ូតុងសន្ទស្សន៍ 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); });

// ធ្វើបច្ចុប្បន្នភាពអត្ថបទស្ថានភាពប្រសិនបើប៊ូតុងណាមួយត្រូវបានចុច ប្រសិនបើ (pressed.length > 0) { status.textContent = "បានចុច៖ " + pressed.join(", "); } }

// បន្តរង្វិលជុំប្រសិនបើឧបករណ៍បំបាត់កំហុសកំពុងដំណើរការ ប្រសិនបើ (កំពុងដំណើរការ) { rafId = requestAnimationFrame(updateGamepad); } }

វិធីសាស្ត្រ classList.toggle() បន្ថែម ឬលុប class សកម្ម ដោយផ្អែកលើថាតើប៊ូតុងត្រូវបានចុច ដែលបង្កឱ្យរចនាប័ទ្មស្រទាប់ CSS របស់យើង។ ជំហានទី 5៖ ដោះស្រាយព្រឹត្តិការណ៍ក្តារចុច អ្នកស្តាប់ព្រឹត្តិការណ៍ទាំងនេះធ្វើឱ្យក្តារចុចថយក្រោយដំណើរការ៖ // ========================================== // អ្នកដោះស្រាយព្រឹត្តិការណ៍ក្តារចុច // ==========================================

document.addEventListener("keydown", (e) => { ប្រសិនបើ (keyMap[e.key]) { // ដោះស្រាយធាតុតែមួយ ឬច្រើន។ ប្រសិនបើ (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) => { ប្រសិនបើ (keyMap[e.key]) { // លុប​ស្ថានភាព​សកម្ម​ចេញ​ពេល​ចេញ​សោ ប្រសិនបើ (Array.isArray(keyMap[e.key])) { keyMap[e.key].forEach(el => el.classList.remove("សកម្ម")); } ផ្សេងទៀត { keyMap[e.key].classList.remove("សកម្ម"); } status.textContent = "កូនសោដែលបានចេញផ្សាយ៖ " + e.key.toUpperCase(); } });

ជំហានទី 6: បន្ថែមការគ្រប់គ្រងចាប់ផ្តើម / បញ្ឈប់ ជាចុងក្រោយ យើងត្រូវការវិធីមួយដើម្បីបិទ/បើកកម្មវិធីបំបាត់កំហុស៖ // ========================================== // បិទ/បើកការបំបាត់កំហុស // ==========================================

document.getElementById("toggle").addEventListener("click", () => { រត់ = !រត់; // ត្រឡប់ស្ថានភាពដែលកំពុងដំណើរការ

ប្រសិនបើ (កំពុងដំណើរការ) { status.textContent = "កម្មវិធីបំបាត់កំហុសកំពុងដំណើរការ..."; updateGamepad(); // ចាប់ផ្តើមរង្វិលជុំអាប់ដេត } ផ្សេងទៀត { status.textContent = "កម្មវិធីបំបាត់កំហុសអសកម្ម"; លុបចោល AnimationFrame(rafId); // បញ្ឈប់រង្វិលជុំ } });

បាទ ចុចប៊ូតុងមួយ ហើយវាភ្លឺ។ រុញដំបងហើយវាផ្លាស់ទី។ នោះហើយជាវា។ រឿងមួយទៀត៖ តម្លៃឆៅ។ ពេលខ្លះអ្នកគ្រាន់តែចង់ឃើញលេខ មិនមែនភ្លើងទេ។

នៅដំណាក់កាលនេះអ្នកគួរតែឃើញ៖

ឧបករណ៍បញ្ជានៅលើអេក្រង់សាមញ្ញ, ប៊ូតុងដែលមានប្រតិកម្មនៅពេលអ្នកធ្វើអន្តរកម្មជាមួយពួកគេ និង ការអានការបំបាត់កំហុសជាជម្រើសបង្ហាញសន្ទស្សន៍ប៊ូតុងដែលបានចុច។

ដើម្បីធ្វើឱ្យវាមានភាពអរូបីតិច នេះជាការបង្ហាញរហ័សនៃឧបករណ៍បញ្ជានៅលើអេក្រង់ដែលមានប្រតិកម្មក្នុងពេលវេលាជាក់ស្តែង៖

ឥឡូវនេះ ចុច Start Recording កត់ត្រាអ្វីគ្រប់យ៉ាងរហូតដល់អ្នកចុច Stop Recording។ 2. ការនាំចេញទិន្នន័យទៅ CSV/JSON នៅពេលដែលយើងមានកំណត់ហេតុ យើងនឹងចង់រក្សាទុកវា។

ជំហានទី 1: បង្កើតកម្មវិធីជំនួយការទាញយក ដំបូងយើងត្រូវការមុខងារជំនួយដែលគ្រប់គ្រងការទាញយកឯកសារនៅក្នុងកម្មវិធីរុករក៖ // ========================================== // ឯកសារទាញយកជំនួយ // ==========================================

មុខងារទាញយកឯកសារ(ឈ្មោះឯកសារ មាតិកា ប្រភេទ = "អត្ថបទ/ធម្មតា") { // បង្កើតប្លុកពីមាតិកា const blob = ថ្មី 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("click", () => { // ពិនិត្យមើលថាតើមានអ្វីដែលត្រូវនាំចេញ ប្រសិនបើ (!frames.length) { console.warn("គ្មានការថតដែលអាចនាំចេញបានទេ។"); ត្រឡប់មកវិញ; }

// បង្កើត payload ជាមួយ metadata និង frames const payload = { createdAt: new Date().toISOSTring(), ស៊ុម };

// ទាញយកជាទម្រង់ JSON ឯកសារទាញយក( "gamepad-log.json", JSON.stringify(payload, null, 2), "កម្មវិធី/json" ); });

ទម្រង់ JSON រក្សាអ្វីៗគ្រប់យ៉ាងឱ្យមានរចនាសម្ព័ន្ធ និងអាចញែកបានយ៉ាងងាយស្រួល ដែលធ្វើឱ្យវាល្អសម្រាប់ការផ្ទុកឡើងវិញទៅក្នុងឧបករណ៍អភិវឌ្ឍន៍ ឬចែករំលែកជាមួយមិត្តរួមក្រុម។ ជំហានទី 3៖ ដោះស្រាយការនាំចេញ CSV សម្រាប់ការនាំចេញ CSV យើងត្រូវបង្រួមទិន្នន័យឋានានុក្រមទៅជាជួរដេក និងជួរឈរ៖

//========================================== // នាំចេញជា CSV // ==========================================

document.getElementById("export-csv").addEventListener("click", () => { // ពិនិត្យមើលថាតើមានអ្វីដែលត្រូវនាំចេញ ប្រសិនបើ (!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); ត្រឡប់ [f.t, ...btnVals, ...f.axes].join(","); }).ចូលរួម("\n");

// ទាញយកជា CSV downloadFile("gamepad-log.csv", បឋមកថា + ជួរដេក, "text/csv"); });

CSV គឺអស្ចារ្យសម្រាប់ការវិភាគទិន្នន័យ ព្រោះវាបើកដោយផ្ទាល់នៅក្នុង Excel ឬ Google Sheets ដែលអនុញ្ញាតឱ្យអ្នកបង្កើតគំនូសតាង ត្រងទិន្នន័យ ឬលំនាំមើលឃើញ។ ឥឡូវនេះ ប៊ូតុងនាំចេញចូលហើយ អ្នកនឹងឃើញជម្រើសថ្មីពីរនៅលើបន្ទះ៖ នាំចេញ JSON និងនាំចេញ CSV ។ JSON គឺល្អប្រសិនបើអ្នកចង់បោះកំណត់ហេតុឆៅចូលទៅក្នុងឧបករណ៍អភិវឌ្ឍន៍របស់អ្នក ឬវាយជុំវិញរចនាសម្ព័ន្ធ។ ម្យ៉ាងវិញទៀត CSV បើកដោយផ្ទាល់ទៅក្នុង Excel ឬ Google Sheets ដូច្នេះអ្នកអាចធ្វើតារាង ត្រង ឬប្រៀបធៀបធាតុបញ្ចូល។ តួលេខខាងក្រោមបង្ហាញពីអ្វីដែលបន្ទះមើលទៅដូចជាមួយនឹងការគ្រប់គ្រងបន្ថែមទាំងនោះ។

3. ប្រព័ន្ធខ្ទាស់ ពេលខ្លះអ្នកមិនត្រូវការការថតពេញលេញទេ គ្រាន់តែ "រូបថតអេក្រង់" រហ័សនៃស្ថានភាពបញ្ចូល។ នោះហើយជាកន្លែងដែលប៊ូតុង Take Snapshot ជួយ។

និង JavaScript៖

// ========================================== // ចាប់យករូបភាព // ==========================================

document.getElementById("snapshot").addEventListener("click", () => { // ទទួលបាន gamepads ដែលបានភ្ជាប់ទាំងអស់។ const pads = navigator.getGamepads(); const activePads = [];

// រង្វិលជុំ និងចាប់យកស្ថានភាពនៃបន្ទះហ្គេមដែលបានភ្ជាប់នីមួយៗ សម្រាប់ (const gp នៃ pads) { ប្រសិនបើ (!gp) បន្ត; // រំលងរន្ធទទេ

activePads.push({ id: gp.id, // ឈ្មោះឧបករណ៍បញ្ជា/ម៉ូដែល ត្រាពេលវេលា៖ performance.now(), ប៊ូតុង៖ gp.buttons.map(b => ({ ចុច៖ ខ.ចុច, តម្លៃ៖ b.value })) អ័ក្ស៖ [...gp.axes] }); }

// ពិនិត្យមើលថាតើ gamepads ណាមួយត្រូវបានរកឃើញ ប្រសិនបើ (!activePads.length) { console.warn("គ្មាន gamepads ភ្ជាប់សម្រាប់ការថតរូប។"); ការដាស់តឿន ("រកមិនឃើញឧបករណ៍បញ្ជាទេ!"); ត្រឡប់មកវិញ; }

// កត់ត្រា និងជូនដំណឹងដល់អ្នកប្រើប្រាស់ console.log("រូបថត៖", activePads); ដាស់តឿន(ថតបាន! ថតបាន ${activePads.length} controller(s)); });

រូបថតបង្កកស្ថានភាពពិតប្រាកដនៃឧបករណ៍បញ្ជារបស់អ្នកក្នុងពេលតែមួយ។ 4. ការចាក់បញ្ចូលខ្មោចឡើងវិញ ឥឡូវនេះសម្រាប់ការសប្បាយមួយ៖ ការចាក់បញ្ចូលខ្មោចឡើងវិញ។ វា​យក​កំណត់​ហេតុ​មួយ ហើយ​ចាក់​វា​ឡើងវិញ​ដោយ​មើល​ឃើញ​ថា​អ្នក​លេង​ខ្មោច​កំពុង​ប្រើ​ឧបករណ៍​បញ្ជា។

JavaScript សម្រាប់ចាក់ឡើងវិញ៖ // ========================================== // ចាក់ឡើងវិញខ្មោច // ==========================================

document.getElementById("replay").addEventListener("click", () => { // ត្រូវប្រាកដថាយើងមានថតដើម្បីចាក់ឡើងវិញ ប្រសិនបើ (!frames.length) { ការដាស់តឿន ("គ្មានការថតដើម្បីចាក់ឡើងវិញទេ!"); ត្រឡប់មកវិញ; }

console.log("ចាប់ផ្តើមលេងខ្មោចឡើងវិញ...");

// តាមដានពេលវេលាសម្រាប់ការចាក់សារថ្មីដែលបានធ្វើសមកាលកម្ម អនុញ្ញាតឱ្យ startTime = performance.now(); អនុញ្ញាតឱ្យ frameIndex = 0;

// ចាក់ឡើងវិញនូវចលនាចលនា ជំហាន​មុខងារ () { const now = performance.now(); const កន្លងផុតទៅ = ឥឡូវនេះ - startTime;

// ដំណើរការស៊ុមទាំងអស់ដែលគួរតែកើតឡើងនៅពេលនេះ while (frameIndex < frames.length && frames[frameIndex].t <= កន្លងផុត) { const frame = ស៊ុម[frameIndex];

// ធ្វើបច្ចុប្បន្នភាព UI ជាមួយនឹងស្ថានភាពប៊ូតុងដែលបានកត់ត្រា btnA.classList.toggle("សកម្ម", frame.buttons[0].pressed); btnB.classList.toggle("សកម្ម", frame.buttons[1].pressed); btnX.classList.toggle("សកម្ម", frame.buttons[2].pressed);

// ធ្វើបច្ចុប្បន្នភាពការបង្ហាញស្ថានភាព អនុញ្ញាតឱ្យចុច = []; frame.buttons.forEach((btn, i) => { ប្រសិនបើ (btn.pressed) pressed.push("ប៊ូតុង" + i); }); ប្រសិនបើ (pressed.length > 0) { status.textContent = "ខ្មោច៖ " + pressed.join(", "); }

សន្ទស្សន៍ស៊ុម ++; }

// បន្តរង្វិលជុំប្រសិនបើមានស៊ុមច្រើនទៀត ប្រសិនបើ (frameIndex < frames.length) { ស្នើសុំ AnimationFrame (ជំហាន); } ផ្សេងទៀត { console.log("ចាក់ឡើងវិញបានបញ្ចប់។"); status.textContent = "ចាក់ឡើងវិញពេញលេញ"; } }

// ចាប់ផ្តើមការលេងឡើងវិញ ជំហាន (); });

ដើម្បីធ្វើការកែកំហុសបន្តិច ខ្ញុំបានបន្ថែមការលេងខ្មោចឡើងវិញ។ នៅពេលដែលអ្នកបានថតវគ្គមួយ អ្នកអាចចុចលេងឡើងវិញ ហើយមើល UI ធ្វើសកម្មភាពវា ស្ទើរតែដូចជាអ្នកលេងខ្មោចកំពុងដំណើរការបន្ទះ។ ប៊ូតុង Replay Ghost ថ្មីបង្ហាញនៅក្នុងបន្ទះសម្រាប់ការនេះ។

ចុច Record, រញ៉េរញ៉ៃជាមួយឧបករណ៍បញ្ជាបន្តិច, បញ្ឈប់, បន្ទាប់មកចាក់ម្តងទៀត។ UI គ្រាន់​តែ​បន្ទរ​អ្វី​គ្រប់​យ៉ាង​ដែល​អ្នក​បាន​ធ្វើ ដូច​ជា​ខ្មោច​តាម​ការ​បញ្ចូល​របស់​អ្នក។ ហេតុអ្វីបានជារំខានជាមួយការបន្ថែមទាំងនេះ?

ការកត់ត្រា/នាំចេញធ្វើឱ្យអ្នកសាកល្បងងាយស្រួលបង្ហាញនូវអ្វីដែលបានកើតឡើង។ រូប​ថត​បង្កក​មួយ​ស្របក់​ទាន់​ពេល មានប្រយោជន៍​ខ្លាំង​ពេល​អ្នក​កំពុង​ដេញ​តាម​កំហុស​សេស។ Ghost replay គឺល្អសម្រាប់ការបង្រៀន ការត្រួតពិនិត្យលទ្ធភាពប្រើប្រាស់ ឬគ្រាន់តែប្រៀបធៀបការដំឡើងការគ្រប់គ្រងដោយចំហៀង។

នៅពេលនេះ វាមិនមែនគ្រាន់តែជាការបង្ហាញដ៏ស្អាតស្អំទៀតទេ ប៉ុន្តែជាអ្វីមួយដែលអ្នកអាចដាក់ឱ្យដំណើរការបាន។ ករណីប្រើប្រាស់ពិភពលោកពិត ឥឡូវនេះ យើងមានកម្មវិធីបំបាត់កំហុសនេះ ដែលអាចធ្វើបានច្រើន។ វាបង្ហាញការបញ្ចូលផ្ទាល់ កត់ត្រាកំណត់ហេតុ នាំចេញពួកវា និងសូម្បីតែចាក់ឡើងវិញនូវវត្ថុផ្សេងៗ។ ប៉ុន្តែសំណួរពិតប្រាកដគឺ: តើអ្នកណាយកចិត្តទុកដាក់? តើនេះមានប្រយោជន៍សម្រាប់អ្នកណា? អ្នកអភិវឌ្ឍន៍ហ្គេម ឧបករណ៍បញ្ជាគឺជាផ្នែកមួយនៃការងារ ប៉ុន្តែការបំបាត់កំហុសពួកគេ? ជាធម្មតាមានការឈឺចាប់។ ស្រមៃថាអ្នកកំពុងសាកល្បងបន្សំហ្គេមប្រយុទ្ធ ដូចជា ↓ → + punch ។ ជំនួស​ឱ្យ​ការ​អធិស្ឋាន អ្នក​ចុច​វា​ដូច​គ្នា​ពីរដង អ្នក​កត់ត្រា​វា​ម្តង ហើយ​ចាក់​វា​ឡើងវិញ។ រួចរាល់។ ឬអ្នកប្តូរកំណត់ហេតុ JSON ជាមួយមិត្តរួមក្រុម ដើម្បីពិនិត្យមើលថាតើលេខកូដអ្នកលេងច្រើនរបស់អ្នកមានប្រតិកម្មដូចគ្នានៅលើម៉ាស៊ីនរបស់ពួកគេដែរឬទេ។ នោះធំណាស់។ អ្នកអនុវត្តមធ្យោបាយងាយស្រួល មួយនេះគឺនៅជិតបេះដូងខ្ញុំ។ មិនមែនគ្រប់គ្នាលេងជាមួយឧបករណ៍បញ្ជា "ស្តង់ដារ" ទេ។ ឧបករណ៍បញ្ជាអាដាប់ធ័របញ្ចេញសញ្ញាចំលែកពេលខ្លះ។ ជាមួយនឹងឧបករណ៍នេះ អ្នកអាចមើលឃើញយ៉ាងច្បាស់នូវអ្វីដែលកំពុងកើតឡើង។ គ្រូបង្រៀន អ្នកស្រាវជ្រាវ អ្នកណាក៏ដោយ ។ ពួកគេអាចចាប់យកកំណត់ហេតុ ប្រៀបធៀបពួកវា ឬចាក់សារឡើងវិញដោយចំហៀង។ រំពេចនោះ វត្ថុដែលមើលមិនឃើញក្លាយជាជាក់ស្តែង។ ការធ្វើតេស្តធានាគុណភាព អ្នកសាកល្បងជាធម្មតាសរសេរកំណត់ចំណាំដូចជា "ខ្ញុំបានបុកប៊ូតុងនៅទីនេះ ហើយវាខូច"។ មិនមានប្រយោជន៍ខ្លាំងណាស់។ ឥឡូវនេះ? ពួកគេអាចចាប់យកការចុចពិតប្រាកដ នាំចេញកំណត់ហេតុ និងផ្ញើវាចេញ។ គ្មានការទាយទេ។ អ្នកអប់រំ ប្រសិនបើអ្នកកំពុងបង្កើតការបង្រៀន ឬវីដេអូ YouTube ការចាក់ឡើងវិញខ្មោចគឺជាមាស។ អ្នកអាចនិយាយតាមន័យត្រង់ថា "នេះជាអ្វីដែលខ្ញុំបានធ្វើជាមួយឧបករណ៍បញ្ជា" ខណៈពេលដែល UI បង្ហាញថាវាកើតឡើង។ ធ្វើឱ្យការពន្យល់កាន់តែច្បាស់។ លើសពីហ្គេម មែនហើយ នេះមិនមែនគ្រាន់តែអំពីហ្គេមប៉ុណ្ណោះទេ។ មនុស្សបានប្រើឧបករណ៍បញ្ជាសម្រាប់មនុស្សយន្ត គម្រោងសិល្បៈ និងចំណុចប្រទាក់ភាពងាយស្រួល។ បញ្ហាដូចគ្នារាល់ពេល៖ តើកម្មវិធីរុករកតាមអ៊ីនធឺណិតឃើញអ្វី? ជាមួយនេះ អ្នកមិនចាំបាច់ទាយទេ។ សេចក្តីសន្និដ្ឋាន ការបំបាត់កំហុសការបញ្ចូលឧបករណ៍បញ្ជាតែងតែមានអារម្មណ៍ដូចជាហោះហើរងងឹត។ មិនដូច DOM ឬ CSS ទេ មិនមានអ្នកត្រួតពិនិត្យដែលភ្ជាប់មកជាមួយសម្រាប់ gamepads ទេ។ វាគ្រាន់តែជាលេខឆៅនៅក្នុងកុងសូល ងាយបាត់បង់សំលេងរំខាន។ ជាមួយនឹង HTML, CSS, និង JavaScript ពីរបីរយបន្ទាត់ យើងបានបង្កើតអ្វីដែលប្លែក៖

ឧបករណ៍បំបាត់កំហុសដែលមើលឃើញដែលធ្វើឱ្យធាតុចូលមើលមិនឃើញ។ ប្រព័ន្ធ CSS ដែលមានស្រទាប់ដែលរក្សា UI ស្អាត និងអាចបំបាត់កំហុសបាន។ សំណុំនៃការកែលម្អ (ការថត ការនាំចេញ ការថតរូប ការលេងខ្មោចឡើងវិញ) ដែលលើកវាពីការបង្ហាញទៅជាឧបករណ៍អ្នកអភិវឌ្ឍន៍។

គម្រោងនេះបង្ហាញពីចម្ងាយដែលអ្នកអាចទៅបានដោយលាយថាមពលរបស់ Web Platform ជាមួយនឹងការច្នៃប្រឌិតបន្តិចបន្តួចនៅក្នុង CSS Cascade Layers។ ឧបករណ៍​ដែល​ខ្ញុំ​ទើប​តែ​ពន្យល់​ទាំង​ស្រុង​គឺ​ប្រភព​បើកចំហ។ អ្នកអាចក្លូន GitHub repo ហើយសាកល្បងវាដោយខ្លួនឯង។ ប៉ុន្តែសំខាន់ជាងនេះទៅទៀត អ្នកអាចធ្វើវាដោយខ្លួនឯងបាន។ បន្ថែមស្រទាប់ផ្ទាល់ខ្លួនរបស់អ្នក។ បង្កើតតក្កវិជ្ជាចាក់ឡើងវិញផ្ទាល់ខ្លួនរបស់អ្នក។ បញ្ចូលវាជាមួយគំរូហ្គេមរបស់អ្នក។ ឬសូម្បីតែប្រើវាតាមរបៀបដែលខ្ញុំមិននឹកស្មានដល់។ សម្រាប់ការបង្រៀន ភាពងាយស្រួល ឬការវិភាគទិន្នន័យ។ នៅចុងបញ្ចប់នៃថ្ងៃនេះ នេះមិនមែនគ្រាន់តែអំពីការបំបាត់កំហុស gamepads ប៉ុណ្ណោះទេ។ វានិយាយអំពីការបំភ្លឺលើធាតុបញ្ចូលដែលលាក់ ហើយផ្តល់ឱ្យអ្នកអភិវឌ្ឍន៍នូវទំនុកចិត្តក្នុងការធ្វើការជាមួយផ្នែករឹងដែលគេហទំព័រនៅតែមិនទទួលយកពេញលេញ។ ដូច្នេះ សូមដោតឧបករណ៍បញ្ជារបស់អ្នក បើកកម្មវិធីនិពន្ធរបស់អ្នក ហើយចាប់ផ្តើមពិសោធន៍។ អ្នកប្រហែលជាភ្ញាក់ផ្អើលចំពោះអ្វីដែលកម្មវិធីរុករករបស់អ្នក និង 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