Sɛ wo plug in controller a, wo mash buttons, move sticks no, twe triggers no... na sɛ developer no, wunhu emu biara. Browser no refa no, ampa, nanso gye sɛ worekyerɛw nɔma wɔ console no mu a, wontumi nhu. Ɛno ne tiyɛ a ɛwɔ Gamepad API no mu. Ɛwɔ hɔ mfe pii, na nokwarem no, ɛwɔ tumi kɛse. Wubetumi akenkan buttons, sticks, triggers, nnwuma no. Nanso nnipa dodow no ara mfa wɔn nsa nka. Adɛn? Efisɛ n’asɛm biara nni hɔ a wɔde bɛma. Panel biara nni developer nnwinnade mu. Ɔkwan a emu da hɔ biara nni hɔ a wobɛfa so ahu sɛ ebia controller’s no reyɛ nea wususuw mpo anaa. Ɛte sɛ nea woretu wimhyɛn anifuraefo. Ɛno yɛɛ me bɔne araa ma meyɛɛ adwinnade ketewaa bi: Gamepad Cascade Debugger. Sɛ́ anka wobɛhwɛ console output no, wubenya controller no ho adwene a ɛte ase, a ɛne ne ho di nkitaho. Mia biribi so na ɛyɛ n’ade wɔ screen no so. Na CSS Cascade Layers no, styles no kɔ so yɛ nhyehyɛe, enti ɛho tew sɛ wobɛsiesie debug. Wɔ saa post yi mu no, mɛkyerɛ wo nea enti a debugging controllers yɛ yaw saa, sɛnea CSS boa ma ɛho tew, ne sɛnea wubetumi ayɛ visual debugger a wotumi de di dwuma bio ama w’ankasa nnwuma.
Sɛ mpo wotumi kyerɛw ne nyinaa a, wobɛwie ntɛm ara wɔ console spam a wontumi nkenkan. Sɛ nhwɛso no: [0,0,1,0,0,0.5,0,...]. [0,0,0,0,1,0,0,...]. [0,0,1,0,0,0,0,...].
So wubetumi ahu bɔtn a wɔde miaa so? Ebia, nanso bere a woayɛ w’ani so den na woayera nsɛm kakraa bi a wode hyɛ mu akyi nkutoo. Enti, dabi, debugging mma mmerɛw bere a ɛfa akenkan inputs ho no. Ɔhaw 3: Nhyehyɛe a Wonnya Sɛ wotow mfonini a wɔde yɛ mfonini ntɛmntɛm mpo bom a, ntadehyɛ ahorow betumi ayɛ basabasa ntɛmntɛm. Default, active, ne debug tebea betumi abɔ, na sɛ nhyehyɛe a emu da hɔ nni hɔ a, wo CSS no bɛyɛ brittle na ɛyɛ den sɛ wobɛtrɛw mu. CSS Cascade Layers betumi aboa. Wɔkyekyɛ styles mu yɛ no “layers” a wɔahyehyɛ no sɛnea di kan, enti wugyae ko tia specificity na guessing, “Why isn’t my debug style showing?” Mmom no, wokura nneɛma ahorow a ɛhaw wo mu:
Base: Controller’s standard, mfiase no hwɛbea. Active: Nsɛntitiriw ma bɔton a wɔamia ne nnua a wɔatu. Debug: Overlays ma developers (e.g., akontabuo akenkan, akwankyerɛ, ne nea ɛkeka ho).
Sɛ yɛkyerɛkyerɛ layers mu wɔ CSS mu sɛdeɛ yei teɛ a, anka yɛbɛnya: /* nea ɛba fam koraa kosi nea ɛkorɔn sen biara */ @layer base, ɛyɛ adwuma, debug;
@layer nnyinaso { . /* ... */ } .
@layer a ɛyɛ adwuma { /* ... */ } .
@layer debug { . /* ... */ } .
Esiane sɛ layer biara stack sɛnea wɔahyɛ ho nkɔm nti, bere nyinaa wunim mmara a edi nkonim. Saa nkɔmhyɛ no mma debugging nyɛ mmerɛw nko, na mmom wotumi di ho dwuma ankasa. Yɛaka ɔhaw no ho asɛm (invisible, messy input) ne ɔkwan a wɔfa so yɛ no (visual debugger a wɔde Cascade Layers asi). Afei yɛbɛfa anammɔn anammɔn nhyehyɛeɛ no mu de ayɛ debugger no. Debugger Adwene no Ɔkwan a ɛyɛ mmerɛw a wobɛfa so ama nsɛm a wɔde asie no ada adi ne sɛ wobɛtwetwe wɔ screen no so kɛkɛ. Ɛno ne nea saa debugger yi yɛ. Buttons, triggers, ne joysticks nyinaa nya nea wotumi hu.
Mia A: Kurukuruwa bi hyerɛn. Pia dua no: Kurukuruwa no twetwe twa ho hyia. Twe agyan bi fã: Bar bi hyɛ fã ma.
Seesei wo n’ani nhwɛ 0s ne 1s, na mmom nokwarem no worehwɛ sɛnea controller no yɛ n’ade live. Nokwarem no, sɛ wufi ase piling wɔ states te sɛ default, pressed, debug info, ebia mpo recording mode a, CSS no fi ase yɛ kɛse na ɛyɛ den. Ɛhɔ na cascade layers no boa. Nhwɛsoɔ a wɔayiyi afiri mu nie: @layer nnyinaso { . .button { . akyi: #222; ɔhye-trɛw: 50%; ne tɛtrɛtɛ: 40px; ne sorokɔ: 40px; } . } .
@layer a ɛyɛ adwuma { .button.wɔabɔ { . akyi: #0f0; /* ahabammono a ɛhyerɛn */ . } . } .
@layer debug { . .button::akyi { . emu nsɛm: attr (data-botae); nkyerɛwde-kɛse: 12px; kɔla: #fff; } . } .
Layer nhyehyɛe no ho hia: base → active → debug.
base twetwe controller no. active handles pressed tebea horow. debug tow wɔ overlays so.
Sɛ wobubu no saa a, ɛkyerɛ sɛ worenko weird specificity wars. Layer biara wɔ ne gyinabea, na bere nyinaa wunim nea edi nkonim. Ɛbɛkyekyere No Momma yenni kan nnya biribi wɔ screen so. Ɛho nhia sɛ ɛyɛ fɛ — ɛhia sɛ ɛwɔ hɔ ara kwa enti yɛwɔ biribi a yɛde bɛyɛ adwuma.
Agorudi krataa Cascade Debugger
Ɛno yɛ nnaka kɛkɛ ankasa. Ɛnyɛ anigyeɛ de besi nnɛ, nanso ɛma yɛn nsa a yɛde bɛfa akyiri yi denam CSS ne JavaScript so. Okay, I’m using cascade layers here efisɛ ɛma nneɛma yɛ nhyehyɛe bere a wode states pii aka ho no. Ɛha na ɛyɛ rough pass:
/* ================================================================================== CASCADE LAYERS NHYEHYƐE Nsɛm a ɛfa nhyehyɛe ho: base → active → debug ==================================== */
/* Kyerɛkyerɛ layer nhyehyɛe mu ansa */ @layer base, ɛyɛ adwuma, debug;
/* Layer 1: Base styles - default a ɛda adi */ . @layer nnyinaso { . .button { . akyi: #333; ɔhye-trɛw: 50%; ne tɛtrɛtɛ: 70px; ne sorokɔ: 70px; ɔyɛkyerɛ: flex; justify-content: mfinimfini; align-nneɛma: mfinimfini; } .
.pause { . ne tɛtrɛtɛ: 20px; ne sorokɔ: 70px; akyi: #333; ɔyɛkyerɛ: inline-block; } . } .
/* Layer 2: Active states - di bɔtn a wɔamia ho dwuma */ @layer a ɛyɛ adwuma { .button.a ɛyɛ adwuma { . akyi: #0f0; /* Ɛyɛ ahabammono a ɛhyerɛn bere a wɔabɔ no */ . nsakrae: nsenia (1.1); /* Ɛma bɔtn no yɛ kɛse kakra */ . } .
.pause.adwuma { . akyi: #0f0; nsakrae: nseniaY (1.1); /* Ɛtrɛw tẽẽ bere a wɔabɔ no */ . } . } .
/* Layer 3: Debug nkatasoɔ - developer info */ @layer debug { . .button::akyi { . emu nsɛm: attr (data-botae); /* Kyerɛ akontaahyɛde botae */ . nkyerɛwde-kɛse: 12px; kɔla: #fff; } . } .
Nea ɛyɛ fɛ wɔ saa kwan yi so ne sɛ, ɔfa biara wɔ atirimpɔw a emu da hɔ. Base layer no ntumi nhyɛ active so da, na active ntumi nto debug so da, a specificity mfa ho. Wei yi CSS specificity akodi a ɛtaa haw debugging nnwinnade no fi hɔ. Seesei ɛte sɛ nea akuwakuw bi te akyi a ɛyɛ sum. Nokwarem no, ɛnyɛ bɔne dodo.
JavaScript no a wode bɛka ho JavaScript bere. Eyi ne baabi a controller no yɛ biribi ankasa. Yɛbɛkyekyere eyi anammɔn anammɔn. Anamɔn 1: Hyehyɛ Ɔman no sohwɛ Nea edi kan no, yehia variables a yɛde bɛdi debugger’s state no akyi: // ==================================================================================== // ƆMAN NHYEHYƐEƐ // ====================================================================================
ma mmirikatu = atoro; // Tracks sɛ ebia debugger no yɛ adwuma anaa ma rafId; // Sie requestAnimationFrame ID no ma wɔtwa mu
Saa nsakraeɛ yi di animation loop a ɛkɔ so kenkan gamepad input no so. Anamɔn 2: Fa DOM Nkyerɛkyerɛmu Afei, yɛnya references a ɛfa HTML elements a yɛbɛyɛ updated nyinaa ho: // ==================================================================================== // DOM ELEMENT NKYERƐKYERƐMU // ====================================================================================
const btnA = krataa.gyeElementById ("btn-a"); const btnB = krataa.gyeElementById ("btn-b"); const btnX = krataa.gyeElementById ("btn-x"); const pause1 = krataa.gyeElementById ("pause1"); const pause2 = krataa.gyeElementById ("pause2"); const tebea = krataa.getElementById ("gyinabea");
Saa nkyerɛkyerɛmu yi a wode besie anim no yɛ nea etu mpɔn sen sɛ wubebisa DOM no mpɛn pii. Anamɔn 3: Fa Keyboard Fallback ka ho Sɛ wopɛ sɛ wosɔ hwɛ a wunni honam fam controller a, yɛbɛma keyboard keys akɔ buttons so: // ==================================================================================== // KEYBOARD FALLBACK (ma sɔhwɛ a wonni controller) // ====================================================================================
const safoaMap = { "a": btnA, . "b": btnB, . "x": btnX, . "p": [pause1, pause2] // 'p' safoa no di pause bars abien no nyinaa so };
Wei ma yɛsɔ UI no hwɛ denam keys a yɛbɛmia so wɔ keyboard so. Anamɔn 4: Yɛ Main Update Loop no Ɛha na nkonyaayi no si. Saa dwumadie yi kɔ so yɛ adwuma na ɛkenkan gamepad tebea: // ==================================================================================== // MAIN GAMEPAD NKYERƐKYERƐMU LOOP // ====================================================================================
dwumadie updateGamepad () { . // Nya gamepads a ɛka bom nyinaa const gamepads = ɔkwankyerɛfo.gyeGamepads (); sɛ (!gamepads) san ba a;
// Fa gamepad a edi kan a ɛka bom no di dwuma const gp = agodie ho nsɛm [0];
sɛ (gp) { . // Update button states denam toggling "active" class no so btnA.classList.toggle ("adwuma", gp.buttons [0]. wɔamia); btnB.classList.toggle ("adwuma", gp.buttons [1]. wɔamia); btnX.classList.toggle ("adwuma", gp.buttons [2]. wɔamia);
// Di pause button no ho dwuma (button index 9 wɔ controller dodow no ara so) . const pauseWɔabɔ = gp.buttons [9].wɔabɔ; pause1.classList.toggle ("adwuma", pauseWɔahyɛ so); pause2.classList.toggle ("adwuma", pauseWɔahyɛ so);
// Yɛ list a ɛwɔ buttons a wɔabɔ mprempren ma status display ma wɔamia = []; gp.buttons.forEach ((btn, me) => { sɛ (btn.wɔabɔ) .pressed.push ("Bɔtɔn " + me); });
// Update status text sɛ wo mia buttons biara a sɛ (wɔabɔ.tenten > 0) { . status.textContent = "Wɔabɔ so: " + wɔamia.kɔka (", "); } . } .
// Toa loop no so sɛ debugger reyɛ adwuma a sɛ (retu mmirika) { . rafId = abisaAnimationFrame (Agodie krataa a wɔayɛ no foforo); } . } .
classList.toggle() kwan no de adesuakuw a ɛyɛ adwuma no ka ho anaasɛ eyi fi hɔ a egyina sɛ ebia wɔabɔ bɔtn no so, a ɛkanyan yɛn CSS layer styles no. Anamɔn 5: Di Keyboard Nsɛm a Esisii ho dwuma Saa adeyɛ atiefo yi ma keyboard fallback no yɛ adwuma: // ==================================================================================== // KEYBOARD NSƐM HO NKYERƐKYERƐMU // ====================================================================================
document.addEventListener ("safoa no ase", (e) => { sɛ (safoaMap [e.safo]) { . // Di nneɛma biako anaa pii ho dwuma sɛ (Array.isArray (safoaMap [e.safo])) { keyMap [e.key].forEach (el => el.classList.add ("adwuma")); } else { . keyMap [e.key].classList.add ("adwuma"); } . status.textContent = "Wɔapia safoa: " + e.safoa.kɔUpperCase (); } . });
document.addEventListener ("safoa", (e) => { sɛ (safoaMap [e.safo]) { . // Yi active state bere a wɔayi key no adi sɛ (Array.isArray (safoaMap [e.safo])) { keyMap [e.key].forEach (el => el.classList.yi ("adwuma")); } else { . keyMap [e.key].classList.yi ("adwuma"); } . status.textContent = "Safoa a wɔayi no adi: " + e.key.toUpperCase (); } . });
Anamɔn 6: Fa Start/Stop Control ka ho Awiei koraa no, yehia ɔkwan bi a yɛbɛfa so adan debugger no akɔ so na yɛadum: // ==================================================================================== // TOGGLE DEBUGGER ON/DUM // ====================================================================================
document.getElementById ("toggle").faEventListener ka ho ("klik", () => { mmirikatu = !tu mmirika; // Flip tebea a ɛretu mmirika no
sɛ (retu mmirika) { . status.textContent = "Debugger a ɛreyɛ adwuma..."; updateGamepad (); // Fi ase yɛ update loop no } else { . status.textContent = "Debugger a ɛnyɛ adwuma"; twaAnimationFrame (rafId) no mu; // Gyae loop no } . });
Enti yeah, press button bi na ɛhyerɛn. Pia dua no na ɛkɔ. Ɛno ne no. Ade biako bio: gyinapɛn ahorow a wɔmfa nhyehyɛ mu. Ɛtɔ da bi a, wopɛ sɛ wuhu nɔma ara kwa, na ɛnyɛ akanea.
Saa bere yi de, ɛsɛ sɛ wuhu sɛ:
Afiri a ɛnyɛ den a wɔde di dwuma wɔ screen so, . Buttons a ɛyɛ n’ade bere a wo ne wɔn di nkitaho no, na Debug akenkan a wopɛ a ɛkyerɛ button indices a wɔamia.
Sɛnea ɛbɛyɛ a eyi bɛyɛ nea ɛnyɛ adwene kɛse no, ɛha na ɔyɛ ntɛm demo a ɛkyerɛ sɛ on-screen controller no yɛ n’ade wɔ bere ankasa mu:
Afei, sɛ wobɔ Start Recording a, wobɛkyerɛw biribiara kosi sɛ wobɛbɔ Stop Recording. 2. Data a wode bɛkɔ CSV/JSON Sɛ yɛnya log wie a, yɛbɛpɛ sɛ yɛde sie.
Anamɔn 1: Yɛ Download Helper no Nea edi kan no, yehia ɔboafo adwuma bi a ɛhwɛ fael a wɔtwe wɔ browser no so ho dwuma: // ==================================================================================== // FILE DOWNLOAD ƆBOAFO // ====================================================================================
function downloadFile (fael din, emu nsɛm, type = "nkyerɛwee/a ɛnyɛ den") { // Yɛ blob bi fi emu nsɛm no mu const blob = Blob foforo ([nneɛma a ɛwɔ mu], { type }); const url = URL.bɔAdeɛURL (blob);
// Yɛ bere tiaa mu download link na klik so const a = krataa.bɔElement ("a"); a.href = url a wɔde di dwuma; a.download = fael din; a.klik (klik ();
// Siesie ade no URL bere a woatwe awie no setTimeout (() => URL.tweAdeɛURL (url), 100); } .
Saa dwumadie yi yɛ adwuma denam Blob (binary kɛseɛ adeɛ) a wobɛbɔ afiri wo data mu, ayɛ bere tiaa mu URL ama no, ne nhyehyɛeɛ a wobɛkliki download link bi so. Ahotew no hwɛ hu sɛ yɛrentu memory. Anamɔn 2: Di JSON Export ho dwuma JSON yɛ pɛpɛɛpɛ ma data nhyehyɛe a edi mũ no a wɔbɛkora so:
// ==================================================================================== // EXPORT SƐ JSON // ====================================================================================
document.getElementById ("export-json").faEventListener ka ho ("klik", () => { // Hwɛ sɛ biribi wɔ hɔ a wobɛtumi de akɔ amannɔne anaa sɛ (!frames.tenten) { . console.warn("Nkyerɛwde biara nni hɔ a wobetumi de akɔ amannɔne."); san kɔ; } .
// Yɛ payload a metadata ne frames wom const payload = { wɔabɔAt: Date foforo ().toISOString (), . frame ahorow a wɔde yɛ nneɛma };
// Twe sɛnea wɔahyehyɛ JSON downloadFile( "gamepad-log.json" a wɔde di dwuma wɔ ɔkwan a ɛfata so. JSON.stringify (adesoa a mfaso wɔ so, null, 2), . "adwumayɛ/json". ); });
JSON format no ma biribiara yɛ nhyehyɛɛ na ɛnyɛ den sɛ wobɛtumi atwa mu, na ɛma ɛyɛ papa ma loading back into dev tools anaasɛ kyɛ ne teammates. Anamɔn 3: Di CSV Export ho dwuma Wɔ CSV exports ho no, ɛhia sɛ yɛ flatten hierarchical data no kɔ rows ne columns mu:
//============================================================================================== // EXPORT SƐ CSV // ====================================================================================
document.getElementById ("export-csv").faEventListener ka ho ("klik", () => { // Hwɛ sɛ biribi wɔ hɔ a wobɛtumi de akɔ amannɔne anaa sɛ (!frames.tenten) { . console.warn("Nkyerɛwde biara nni hɔ a wobetumi de akɔ amannɔne."); san kɔ; } .
// Si CSV header row (columns ma bere nsɔano, bɔtn nyinaa, axes nyinaa) const headerButtons = frames [0].buttons.map ((_, me) => btn $ {me}); const headerAxes = frames [0].axes.map ((_, me) => axis $ {me}); const header = ["t", ...atiriButtons, ...atiriAxes].join (",") + "\n";
// Yɛ CSV data row ahorow const rows = mfonini ahorow.map (f => { . const btnVals = f.buttons.map (b => b.bo a ɛsom); san kɔ [f.t, ...btnVals, ...f.axes]. kɔka (","); }).join ("\ n");
// Twe sɛ CSV downloadFile ("gamepad-log.csv", atiri + nkyerɛwde, "nkyerɛwee/csv"); });
CSV yɛ nwonwa ma data nhwehwɛmu ɛfiri sɛ ɛbue tẽẽ wɔ Excel anaa Google Sheets mu, ɛma wotumi yɛ charts, yiyi data, anaa wohu nhwɛsoɔ wɔ aniwa so. Seesei a export buttons no wɔ mu no, wobɛhunu akwan foforɔ mmienu wɔ panel no so: Export JSON ne Export CSV. JSON yɛ fɛ sɛ wopɛ sɛ woto raw log no san kɔ wo dev nnwinnade mu anaasɛ wo poke twa structure no ho hyia. CSV deɛ, ɛbue tẽẽ kɔ Excel anaa Google Sheets mu sɛdeɛ ɛbɛyɛ a wobɛtumi ayɛ chart, filter, anaa de atoto inputs ho. Mfonini a edidi so yi kyerɛ sɛnea panel no te wɔ saa controls foforo no ho.
3. Snapshot Nhyehyɛe a Wɔde Di Dwuma Ɛtɔ da bi a, wunhia sɛ wobɛkyere agu hama so a edi mũ, na mmom “screenshot” a ɛyɛ ntɛm a ɛkyerɛ sɛnea nsɛm a wɔde hyɛ mu no. Ɛhɔ na Take Snapshot button bi boa.
Na JavaScript no nso:
// ==================================================================================== // FA NSƐM HO NSƐM // ====================================================================================
document.getElementById ("mfonini a wɔagye").faEventListener ("klik", () => { // Nya gamepads a ɛka bom nyinaa const pads = ɔkwankyerɛfo.gyeGamepads (); const activePads = [];
// Loop through na kyere tebea a gamepad biara a ɛka ho no na (const gp a ɛwɔ pads) { . sɛ (!gp) kɔ so a; // Skip slots a hwee nni mu
activePads.push ({ id: gp.id, // Controller din/nhwɛso bere nsɔano: adwumayɛ.seesei (), . bɔton ahorow: gp.buttons.map (b => ({ mia: b.mia, . botae: b.bo a ɛsom })), . agyan: [...gp.agyan]. }); } .
// Hwɛ sɛ wɔahu gamepads biara anaa sɛ (!activePads.tenten) { . console.warn("Gamepads biara nni hɔ a wɔde abɔ mu ama mfoninitwa."); alert("Wɔanhu controller biara!"); san kɔ; } .
// Log na bɔ ɔdefo no amanneɛ console.log ("Mfonini a Wɔagye:", activePads); alert (Snapshot a wɔafa! Wɔakyere $ {activePads.length} controller (s).); });
Snapshots freeze wo controller no tebea pɔtee wɔ bere bi mu. 4. Ahonhommɔne Input Replay Afei deɛ ɛyɛ anigyeɛ no: ghost input replay. Eyi gye log bi na ɛbɔ no wɔ aniwa so te sɛ nea phantom player bi de controller no redi dwuma.
JavaScript a wode bɛsan abɔ bio: // ==================================================================================== // GHOST REPLAY NKYERƐKYERƐMU // ====================================================================================
document.getElementById ("san bɔ").faEventListener ("klik", () => { // Hwɛ sɛ yɛwɔ recording a yɛbɛsan abɔ sɛ (!frames.tenten) { . alert("No recording biara nni hɔ a wobɛsan abɔ!"); san kɔ; } .
console.log ("Wɔrefi ase abɔ ahonhonsɛm bio...");
// Track bere ma synced playback ma startTime = adwumayɛ.seesei (); ma frameIndex = 0 na ɛnyɛ nea ɛfata;
// San bɔ animation loop no bio adwuma anammɔn () { . const seesei = adwumayɛ.seesei (); const atwam = seesei - bere a wɔde fi ase;
// Di frame ahorow a anka ɛsɛ sɛ ɛba mprempren no nyinaa ho dwuma bere a (frameIndex < frames.tenten && frames[frameIndex].t <= atwam) { const frame = mfonini ahorow [frameIndex];
// Fa UI no foforo ne button states a wɔakyere agu hama so btnA.classList.toggle ("adwuma", frame.buttons [0]. wɔamia); btnB.classList.toggle ("adwuma", frame.buttons [1]. wɔamia); btnX.classList.toggle ("adwuma", frame.buttons [2]. wɔamia);
// Update tebea ho nkyerɛkyerɛmu ma wɔamia = []; frame.buttons.forEach ((btn, me) => { sɛ (btn.wɔabɔ) mia.push ("Button " + i); }); sɛ (wɔabɔ.tenten > 0) { . status.textContent = "Ghost: " + wɔamia.kɔka (", "); } .
frameIndex ++ na ɛwɔ hɔ; } .
// Toa loop so sɛ frame pii wɔ hɔ a sɛ (frameIndex < frame.tenten) { . requestAnimationFrame (anammɔn); } else { . console.log("Saa bɔ bio."awie."); status.textContent = "Sɛ san bɔ awie"; } . } .
// Fi ase replay no bio anammɔn (); });
Sɛnea ɛbɛyɛ a debugging bɛyɛ nsaanodwuma kakra no, mede ghost replay kaa ho. Sɛ wokyere session bi wie a, wobɛtumi abɔ replay na woahwɛ UI no ayɛ no, ɛkame ayɛ sɛ phantom player reyɛ pad no. Replay Ghost button foforo bi bɛda adi wɔ panel no mu ama eyi.
Hit Record, mess around the controller kakra, gyae, afei san bɔ. UI no ka biribiara a woyɛe no ho asɛm kɛkɛ, te sɛ sunsum bi a odi wo inputs akyi. Dɛn nti na ɛsɛ sɛ wohaw wo ho wɔ saa nneɛma foforo yi ho?
Recording/export ma ɛyɛ mmerɛw ma testers sɛ wɔbɛkyerɛ nea esii no pɛpɛɛpɛ. Snapshots freeze bere tiaa bi wɔ bere mu, super mfaso bere a wo’re chasing odd bugs. Ghost replay yɛ kɛse ma nkyerɛkyerɛ, accessibility checks, anaasɛ kɛkɛ a wɔde toto control setups nkyɛnkyɛn.
Saa bere yi, ɛnyɛ demo a ɛyɛ fɛ kɛkɛ bio, na mmom biribi a wubetumi de ayɛ adwuma ankasa. Wiase Ankasa mu Nsɛm a Wɔde Di Dwuma Seesei yɛanya saa debugger yi a ɛtumi yɛ pii. Ɛkyerɛ live input, kyerɛw logs, de kɔ amannɔne, na mpo ɛsan bɔ nneɛma. Nanso asɛmmisa ankasa ne sɛ: hena na odwen ho ankasa? Hena na eyi ho wɔ mfaso ma? Wɔn a Wɔyɛ Agodie Controllers yɛ adwuma no fã, nanso debugging wɔn? Mpɛn pii no, ɛyɛ ɛyaw. Fa no sɛ woresɔ akodi agodie combo ahwɛ, te sɛ ↓ → + punch. Sɛ́ anka wobɛbɔ mpae no, womiaa no saa ara mprenu, wokyere guu kasɛt so pɛnkoro, na wosan bɔ bio. Wɔayɛ. Anaasɛ wo ne teammate bi sesa JSON logs de hwɛ sɛ wo multiplayer code no yɛ n’ade saa ara wɔ wɔn mfiri no so anaa. Ɛno yɛ kɛse. Wɔn a Wɔyɛ Nnuruyɛfo a Wɔyɛ Nneɛma a Wɔde Kɔ Hɔ Oyi bɛn me koma. Ɛnyɛ obiara na ɔde controller “a ɛyɛ gyinapɛn” di agoru. Adaptive controllers tow nsɛnkyerɛnne a ɛyɛ nwonwa gu ɛtɔ mmere bi a. Sɛ wode saa adwinnade yi di dwuma a, wubetumi ahu nea ɛrekɔ so no pɛpɛɛpɛ. Akyerɛkyerɛfo, nhwehwɛmufo, obiara. Wobetumi agye logs, de atoto ho, anaasɛ wɔasan abɔ inputs no nkyɛnkyɛn. Mpofirim ara, nneɛma a aniwa nhu da adi pefee. Sɔhwɛ a Wɔde Hwɛ Nneɛma a Ɛyɛ Paara Wɔn a wɔsɔ hwɛ no taa kyerɛw nsɛm te sɛ “Me mashed buttons wɔ ha na ɛbubui.” Ɛnyɛ nea ɛboa kɛse. Afei deɛ? Wobetumi akyere mfiri a wɔde tintim no pɛpɛɛpɛ, de log no akɔ amannɔne, na wɔde akɔ. No guessing. Akyerɛkyerɛfo Sɛ woreyɛ tutorials anaa YouTube vids a, ghost replay yɛ sika kɔkɔɔ. Wubetumi aka ankasa sɛ, “Here’s what I did with the controller,” bere a UI no kyerɛ sɛ ɛrekɔ so. Ɛma nkyerɛkyerɛmu ahorow mu da hɔ yiye. Agodie a Ɛboro So Na yeah, eyi nnyɛ agodie nko ara. Nkurɔfo de controllers adi dwuma ama robɔt, adwinni adwuma, ne accessibility interfaces. Asɛm koro no ara bere biara: dɛn na browser no rehu ankasa? Sɛ wode eyi di dwuma a, ɛnsɛ sɛ wususuw ho. Awiei Debugging a controller input ayɛ te sɛ nea ɛretu anifurae bere nyinaa. Nea ɛnte sɛ DOM anaa CSS no, inspector biara nni hɔ a wɔde ahyɛ mu ma gamepads; ɛyɛ raw numbers kɛkɛ wɔ console no mu, ɛnyɛ den sɛ ɛbɛyera wɔ dede no mu. Yɛde HTML, CSS, ne JavaScript nkyerɛwde ɔhaha kakraa bi sii biribi soronko:
Visual debugger a ɛma inputs a aniwa nhu no da adi. CSS nhyehyɛe a ɛwɔ layered a ɛma UI no ho tew na wotumi debuggable. Nkɔsoɔ ahodoɔ bi (recording, exporting, snapshots, ghost replay) a ɛma no kɔ soro firi demo kɔ developer adwinnadeɛ.
Saa dwumadie yi kyerɛ baabi a wobɛtumi akɔ denam Web Platform’s tumi a wode bɛfrafra ne adebɔ kakra wɔ CSS Cascade Layers mu. Adwinnade a mekyerɛkyerɛɛ mu seesei ara no nyinaa yɛ open-source. Wubetumi ayɛ GitHub repo no clone na w’ankasa woasɔ ahwɛ. Nanso nea ɛho hia sen saa no, wubetumi ayɛ no w’ankasa de. Fa w’ankasa layers ka ho. Si w’ankasa replay logic. Fa ka wo game prototype no ho. Anaasɛ mpo fa di dwuma wɔ akwan horow a minsusuw ho so. Wɔ nkyerɛkyerɛ, akwan a wɔfa so nya, anaa data nhwehwɛmu ho. Wɔ da no awiei no, eyi nyɛ gamepads debugging kɛkɛ. Ɛfa hann a wobɛhyerɛn wɔ inputs a ahintaw so, na ama developers anya ahotoso sɛ wɔde hardware a wɛb no da so ara nnye ntom koraa bɛyɛ adwuma. Enti, fa wo controller no hyɛ mu, bue wo editor no, na fi ase sɔ hwɛ. Ebia ɛbɛyɛ wo nwonwa wɔ nea wo browser ne wo CSS betumi ayɛ ankasa no ho.