جب آپ کسی کنٹرولر کو پلگ ان کرتے ہیں، تو آپ بٹنوں کو میش کرتے ہیں، لاٹھیوں کو حرکت دیتے ہیں، محرکات کو کھینچتے ہیں… اور ایک ڈویلپر کے طور پر، آپ کو اس میں سے کچھ نظر نہیں آتا ہے۔ براؤزر اسے اٹھا رہا ہے، یقینی طور پر، لیکن جب تک آپ کنسول میں نمبر لاگ ان نہیں کر رہے ہیں، یہ پوشیدہ ہے۔ گیم پیڈ API کے ساتھ یہ سر درد ہے۔ یہ برسوں سے چل رہا ہے، اور یہ حقیقت میں کافی طاقتور ہے۔ آپ بٹن، لاٹھی، محرکات، کام پڑھ سکتے ہیں۔ لیکن زیادہ تر لوگ اسے ہاتھ نہیں لگاتے۔ کیوں؟ کیونکہ کوئی رائے نہیں ہے۔ ڈویلپر ٹولز میں کوئی پینل نہیں ہے۔ یہ جاننے کا کوئی واضح طریقہ نہیں ہے کہ آیا کنٹرولر بھی وہی کر رہا ہے جو آپ سوچتے ہیں۔ ایسا لگتا ہے جیسے اڑنا اندھا ہو۔ اس نے مجھے ایک چھوٹا سا ٹول بنانے کے لئے کافی بگاڑ دیا: گیم پیڈ کاسکیڈ ڈیبگر۔ کنسول آؤٹ پٹ کو گھورنے کے بجائے، آپ کو کنٹرولر کا لائیو، انٹرایکٹو نظارہ ملتا ہے۔ کچھ دبائیں اور یہ اسکرین پر رد عمل ظاہر کرتا ہے۔ اور 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 کیسکیڈ پرتیں مدد کر سکتی ہیں۔ وہ اسٹائلز کو "پرتوں" میں گروپ کرتے ہیں جو ترجیح کے لحاظ سے ترتیب دی جاتی ہیں، لہذا آپ مخصوصیت سے لڑنا بند کر دیتے ہیں اور اندازہ لگاتے ہیں، "میرا ڈیبگ اسٹائل کیوں نہیں دکھا رہا ہے؟" اس کے بجائے، آپ الگ الگ خدشات برقرار رکھتے ہیں:
بنیاد: کنٹرولر کا معیاری، ابتدائی ظاہری شکل۔ فعال: دبائے ہوئے بٹنوں اور منتقل شدہ لاٹھیوں کی جھلکیاں۔ ڈیبگ: ڈویلپرز کے لیے اوورلیز (جیسے، عددی ریڈ آؤٹ، گائیڈز، وغیرہ)۔
اگر ہم اس کے مطابق سی ایس ایس میں پرتوں کی وضاحت کرتے تو ہمارے پاس ہوتا: /* سب سے کم سے اعلیٰ ترجیح */ پرت کی بنیاد، فعال، ڈیبگ؛
@layer بیس { /*...*/ }
@layer فعال { /*...*/ }
@layer ڈیبگ { /*...*/ }
چونکہ ہر پرت پیشین گوئی کے مطابق اسٹیک ہوتی ہے، آپ ہمیشہ جانتے ہیں کہ کون سے اصول جیتتے ہیں۔ یہ پیشن گوئی ڈیبگنگ کو نہ صرف آسان بناتی ہے، بلکہ حقیقت میں قابل انتظام ہے۔ ہم نے مسئلہ (غیر مرئی، گندا ان پٹ) اور نقطہ نظر (کاسکیڈ پرتوں کے ساتھ بنایا ہوا ایک بصری ڈیبگر) کا احاطہ کیا ہے۔ اب ہم ڈیبگر بنانے کے لیے مرحلہ وار عمل سے گزریں گے۔ ڈیبگر کا تصور پوشیدہ ان پٹ کو مرئی بنانے کا سب سے آسان طریقہ یہ ہے کہ اسے صرف اسکرین پر کھینچیں۔ یہ ڈیبگر یہی کرتا ہے۔ بٹن، ٹرگرز، اور جوائے اسٹک سبھی کو ایک بصری ملتا ہے۔
A دبائیں: ایک دائرہ روشن ہوتا ہے۔ چھڑی کو جھکانا: دائرہ چاروں طرف پھسلتا ہے۔ ایک ٹرگر کو آدھے راستے پر کھینچیں: ایک بار آدھے راستے پر بھر جاتا ہے۔
اب آپ 0s اور 1s کو نہیں دیکھ رہے ہیں، لیکن اصل میں کنٹرولر کا لائیو رد عمل دیکھ رہے ہیں۔ بلاشبہ، ایک بار جب آپ پہلے سے طے شدہ، پریسڈ، ڈیبگ انفارمیشن، شاید ریکارڈنگ موڈ جیسی ریاستوں پر ڈھیر لگانا شروع کر دیتے ہیں، CSS بڑا اور پیچیدہ ہونا شروع ہو جاتا ہے۔ اسی جگہ جھرن کی پرتیں کام آتی ہیں۔ یہاں ایک سٹرپ ڈاون مثال ہے: @layer بیس { بٹن { پس منظر: #222؛ سرحدی رداس: 50٪؛ چوڑائی: 40px؛ اونچائی: 40px؛ } }
پرت فعال { .button.pressed { پس منظر: #0f0؛ /* چمکدار سبز*/ } }
@layer ڈیبگ { بٹن::بعد { مواد: attr(ڈیٹا ویلیو)؛ فونٹ سائز: 12px؛ رنگ: #fff؛ } }
پرت آرڈر کی اہمیت ہے: بیس → فعال → ڈیبگ۔
بیس کنٹرولر کو کھینچتا ہے۔ فعال ہینڈل پریس ریاستوں. اوورلیز پر ڈیبگ پھینکتا ہے۔
اسے اس طرح توڑ دینے کا مطلب ہے کہ آپ عجیب و غریب جنگیں نہیں لڑ رہے ہیں۔ ہر پرت کی اپنی جگہ ہوتی ہے، اور آپ ہمیشہ جانتے ہیں کہ کیا جیتتا ہے۔ اسے باہر کی تعمیر آئیے پہلے اسکرین پر کچھ حاصل کریں۔ اسے اچھا نظر آنے کی ضرورت نہیں ہے - بس موجود ہونے کی ضرورت ہے لہذا ہمارے پاس کام کرنے کے لیے کچھ ہے۔
گیم پیڈ کاسکیڈ ڈیبگر
یہ لفظی طور پر صرف بکس ہیں۔ ابھی تک دلچسپ نہیں ہے، لیکن یہ ہمیں بعد میں CSS اور JavaScript کے ساتھ پکڑنے کے لیے ہینڈل دیتا ہے۔ ٹھیک ہے۔ یہاں ایک مشکل پاس ہے:
/* =================================== کیسکیڈ پرتوں کا سیٹ اپ آرڈر کے معاملات: بنیاد → فعال → ڈیبگ =====================================*/
/* پرت کے آرڈر کی پہلے سے وضاحت کریں */ پرت کی بنیاد، فعال، ڈیبگ؛
/* پرت 1: بنیادی طرزیں - پہلے سے طے شدہ ظاہری شکل */ @layer بیس { بٹن { پس منظر: #333؛ سرحدی رداس: 50٪؛ چوڑائی: 70px؛ اونچائی: 70px؛ ڈسپلے: فلیکس؛ justify-content: مرکز؛ align-items: مرکز؛ }
.pause { چوڑائی: 20px؛ اونچائی: 70px؛ پس منظر: #333؛ ڈسپلے: ان لائن بلاک؛ } }
/* پرت 2: فعال حالتیں - دبائے ہوئے بٹنوں کو ہینڈل کرتا ہے */ پرت فعال { .button.active { پس منظر: #0f0؛ /* دبانے پر چمکدار سبز*/ تبدیلی: پیمانے (1.1)؛ /* بٹن کو تھوڑا بڑا کرتا ہے */ }
.pause.active { پس منظر: #0f0؛ ٹرانسفارم: سکیل وائی(1.1)؛ /* جب دبایا جائے تو عمودی طور پر پھیل جاتا ہے */ } }
/* پرت 3: ڈیبگ اوورلیز - ڈویلپر کی معلومات */ @layer ڈیبگ { بٹن::بعد { مواد: attr(ڈیٹا ویلیو)؛ /* عددی قدر دکھاتا ہے */ فونٹ سائز: 12px؛ رنگ: #fff؛ } }
اس نقطہ نظر کی خوبصورتی یہ ہے کہ ہر پرت کا ایک واضح مقصد ہے۔ بیس لیئر کبھی بھی ایکٹو کو اوور رائیڈ نہیں کر سکتی، اور ایکٹو کبھی بھی ڈیبگ کو اوور رائیڈ نہیں کر سکتا، قطع نظر اس کے کہ مخصوصیت کچھ بھی ہو۔ یہ سی ایس ایس کی مخصوص جنگوں کو ختم کرتا ہے جو عام طور پر ڈیبگنگ ٹولز کو طاعون دیتے ہیں۔ اب ایسا لگتا ہے کہ کچھ جھرمٹ سیاہ پس منظر پر بیٹھے ہیں۔ ایمانداری سے، بہت برا نہیں.
جاوا اسکرپٹ کو شامل کرنا جاوا اسکرپٹ کا وقت۔ یہ وہ جگہ ہے جہاں کنٹرولر اصل میں کچھ کرتا ہے۔ ہم اسے مرحلہ وار بنائیں گے۔ مرحلہ 1: اسٹیٹ مینجمنٹ کو ترتیب دیں۔ سب سے پہلے، ہمیں ڈیبگر کی حالت کو ٹریک کرنے کے لیے متغیرات کی ضرورت ہے: // ================================== // ریاستی انتظام // ==================================
چلو = جھوٹا؛ // ٹریک کرتا ہے کہ آیا ڈیبگر فعال ہے۔ rafId دو // منسوخی کے لیے درخواست کی اینیمیشن فریم 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("status")؛
ان حوالوں کو سامنے رکھنا DOM سے بار بار استفسار کرنے سے زیادہ کارآمد ہے۔ مرحلہ 3: کی بورڈ فال بیک شامل کریں۔ فزیکل کنٹرولر کے بغیر جانچ کے لیے، ہم کی بورڈ کیز کو بٹنوں پر نقشہ بنائیں گے: // ================================== // کی بورڈ فال بیک (کنٹرولر کے بغیر جانچ کے لیے) // ==================================
const keyMap = { "a": btnA، "b": btnB، "x": btnX، "p": [pause1, pause2] // 'p' کلید دونوں توقف بار کو کنٹرول کرتی ہے۔ };
یہ ہمیں کی بورڈ پر کیز دبا کر UI کی جانچ کرنے دیتا ہے۔ مرحلہ 4: مین اپ ڈیٹ لوپ بنائیں یہ وہ جگہ ہے جہاں جادو ہوتا ہے۔ یہ فنکشن مسلسل چلتا ہے اور گیم پیڈ کی حالت پڑھتا ہے: // ================================== // مین گیم پیڈ اپ ڈیٹ لوپ // ==================================
فنکشن اپڈیٹ گیم پیڈ () { // تمام منسلک گیم پیڈ حاصل کریں۔ const gamepads = navigator.getGamepads(); اگر (!gamepads) واپس آئے؛
// پہلا منسلک گیم پیڈ استعمال کریں۔ const gp = گیم پیڈز[0]؛
اگر (جی پی) { // "فعال" کلاس کو ٹوگل کرکے بٹن اسٹیٹس کو اپ ڈیٹ کریں۔ btnA.classList.toggle("active"، gp.buttons[0].pressed)؛ btnB.classList.toggle("active", gp.buttons[1].pressed); btnX.classList.toggle("active"، gp.buttons[2].pressed)؛
// توقف کے بٹن کو ہینڈل کریں (زیادہ تر کنٹرولرز پر بٹن انڈیکس 9) const pausePressed = gp.buttons[9].pressed; pause1.classList.toggle("فعال"، توقف دبایا)؛ pause2.classList.toggle("فعال"، pausePpressed)؛
// اسٹیٹس ڈسپلے کے لیے فی الحال دبائے گئے بٹنوں کی فہرست بنائیں let pressed = []؛ gp.buttons.forEach((btn, i) => { اگر (btn.pressed)pressed.push("بٹن" + i)؛ });
// اگر کوئی بٹن دبائے جائیں تو اسٹیٹس ٹیکسٹ کو اپ ڈیٹ کریں۔ اگر (دبائی گئی لمبائی > 0) { status.textContent = "دبا ہوا: " + pressed.join(", "); } }
// اگر ڈیبگر چل رہا ہے تو لوپ کو جاری رکھیں اگر (چل رہا ہے) { rafId = requestAnimationFrame(updateGamepad)؛ } }
classList.toggle() طریقہ اس بات کی بنیاد پر فعال کلاس کو شامل کرتا ہے یا ہٹاتا ہے کہ آیا بٹن دبایا گیا ہے، جو ہماری CSS پرت کے انداز کو متحرک کرتا ہے۔ مرحلہ 5: کی بورڈ ایونٹس کو ہینڈل کریں۔ یہ ایونٹ سننے والے کی بورڈ فال بیک کام کرتے ہیں: // ================================== // کی بورڈ ایونٹ ہینڈلرز // ==================================
document.addEventListener("keydown"، (e) => { اگر (keyMap[e.key]) { // سنگل یا ایک سے زیادہ عناصر کو ہینڈل کریں۔ اگر (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) => { اگر (keyMap[e.key]) { // چابی جاری ہونے پر فعال حالت کو ہٹا دیں۔ اگر (Array.isArray(keyMap[e.key])) { keyMap[e.key].forEach(el => el.classList.remove("active"))؛ } اور { keyMap[e.key].classList.remove("active")؛ } status.textContent = "کلید جاری کی گئی:" + e.key.toUpperCase(); } });
مرحلہ 6: اسٹارٹ/اسٹاپ کنٹرول شامل کریں۔ آخر میں، ہمیں ڈیبگر کو آن اور آف کرنے کا ایک طریقہ درکار ہے: // ================================== // ٹوگل ڈیبگر آن/آف // ==================================
document.getElementById("toggle").addEventListener("click"، () => { چل رہا ہے = !چل رہا ہے // چلنے والی حالت کو پلٹائیں۔
اگر (چل رہا ہے) { status.textContent = "ڈیبگر چل رہا ہے..."؛ اپ ڈیٹ گیم پیڈ ()؛ // اپ ڈیٹ لوپ شروع کریں۔ } اور { status.textContent = "ڈیبگر غیر فعال"؛ کینسل اینیمیشن فریم(rafId)؛ // لوپ بند کرو } });
تو ہاں، ایک بٹن دبائیں اور یہ چمکتا ہے۔ چھڑی کو دبائیں اور یہ حرکت کرتا ہے۔ یہ ہے. ایک اور چیز: خام اقدار۔ کبھی کبھی آپ صرف نمبر دیکھنا چاہتے ہیں، روشنی نہیں.
اس مرحلے پر، آپ کو دیکھنا چاہئے:
ایک سادہ آن اسکرین کنٹرولر، بٹن جو آپ کے ان کے ساتھ تعامل کرتے وقت رد عمل ظاہر کرتے ہیں، اور ایک اختیاری ڈیبگ ریڈ آؤٹ دبائے ہوئے بٹن کے اشاریے دکھا رہا ہے۔
اس کو کم تجریدی بنانے کے لیے، یہاں آن اسکرین کنٹرولر کا ایک فوری ڈیمو ہے جو حقیقی وقت میں رد عمل ظاہر کرتا ہے:
اب، اسٹارٹ ریکارڈنگ کو دبانے سے سب کچھ لاگ ان ہوجاتا ہے جب تک کہ آپ سٹاپ ریکارڈنگ کو نہیں مارتے۔ 2. CSV/JSON میں ڈیٹا برآمد کرنا ایک بار جب ہمارے پاس لاگ ہے، ہم اسے محفوظ کرنا چاہیں گے۔
مرحلہ 1: ڈاؤن لوڈ مددگار بنائیں سب سے پہلے، ہمیں ایک مددگار فنکشن کی ضرورت ہے جو براؤزر میں فائل ڈاؤن لوڈز کو سنبھالے: // ================================== // فائل ڈاؤن لوڈ ہیلپر // ==================================
فنکشن ڈاؤن لوڈ فائل (فائل کا نام، مواد، قسم = "متن/سادہ") { // مواد سے ایک بلاب بنائیں 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); }
یہ فنکشن آپ کے ڈیٹا سے ایک بلاب (بائنری بڑی آبجیکٹ) بنا کر، اس کے لیے ایک عارضی یو آر ایل بنا کر، اور پروگرام کے مطابق ڈاؤن لوڈ لنک پر کلک کر کے کام کرتا ہے۔ صفائی یقینی بناتی ہے کہ ہم میموری کو لیک نہیں کرتے ہیں۔ مرحلہ 2: JSON ایکسپورٹ کو ہینڈل کریں۔ JSON مکمل ڈیٹا سٹرکچر کو محفوظ رکھنے کے لیے بہترین ہے:
// ================================== // JSON کے طور پر برآمد کریں۔ // ==================================
document.getElementById("export-json").addEventListener("click"، () => { // چیک کریں کہ آیا برآمد کرنے کے لیے کچھ ہے۔ اگر (!frames.length) { console.warn("برآمد کرنے کے لیے کوئی ریکارڈنگ دستیاب نہیں ہے۔")؛ واپسی }
// میٹا ڈیٹا اور فریموں کے ساتھ ایک پے لوڈ بنائیں const payload = { تخلیق کے وقت: نئی تاریخ().toISOSstring(), فریم };
// فارمیٹ شدہ JSON کے بطور ڈاؤن لوڈ کریں۔ فائل ڈاؤن لوڈ کریں "gamepad-log.json"، JSON.stringify(پے لوڈ، 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 کے بطور ڈاؤن لوڈ کریں۔ فائل ڈاؤن لوڈ کریں });
CSV ڈیٹا کے تجزیہ کے لیے شاندار ہے کیونکہ یہ براہ راست Excel یا Google Sheets میں کھلتا ہے، جس سے آپ کو چارٹ، ڈیٹا فلٹر، یا اسپاٹ پیٹرن کو بصری طور پر تخلیق کرنے دیتا ہے۔ اب جب کہ ایکسپورٹ بٹن موجود ہیں، آپ کو پینل پر دو نئے اختیارات نظر آئیں گے: JSON برآمد کریں اور CSV برآمد کریں۔ JSON اچھا ہے اگر آپ خام لاگ کو اپنے دیو ٹولز میں واپس پھینکنا چاہتے ہیں یا ڈھانچے کے ارد گرد پوک کرنا چاہتے ہیں۔ دوسری طرف، CSV سیدھے Excel یا Google Sheets میں کھلتا ہے تاکہ آپ ان پٹ کو چارٹ، فلٹر یا موازنہ کر سکیں۔ مندرجہ ذیل اعداد و شمار سے پتہ چلتا ہے کہ ان اضافی کنٹرولز کے ساتھ پینل کیسا لگتا ہے۔
3. سنیپ شاٹ سسٹم بعض اوقات آپ کو مکمل ریکارڈنگ کی ضرورت نہیں ہوتی، صرف ان پٹ سٹیٹس کا ایک فوری "اسکرین شاٹ"۔ اسی جگہ ٹیک اسنیپ شاٹ بٹن مدد کرتا ہے۔
اور جاوا اسکرپٹ:
// ================================== // سنیپ شاٹ لیں۔ // ==================================
document.getElementById("snapshot").addEventListener("click"، () => { // تمام منسلک گیم پیڈ حاصل کریں۔ const pads = navigator.getGamepads(); const activePads = []؛
// ہر منسلک گیم پیڈ کی حالت کو لوپ کریں اور کیپچر کریں۔ کے لیے (پیڈز کا جی پی) { اگر (!gp) جاری رکھیں؛ // خالی سلاٹوں کو چھوڑ دیں۔
ActivePads.push({ id: gp.id، // کنٹرولر کا نام/ماڈل ٹائم اسٹیمپ: performance.now() بٹن: gp.buttons.map(b => ({ pressed: b.pressed، قدر: b.value })) محور: [...gp.axes] }); }
// چیک کریں کہ آیا کوئی گیم پیڈ ملا ہے۔ اگر (!activePads.length) { console.warn("اسنیپ شاٹ کے لیے کوئی گیم پیڈ منسلک نہیں ہے۔")؛ الرٹ ("کوئی کنٹرولر نہیں ملا!")؛ واپسی }
// لاگ ان کریں اور صارف کو مطلع کریں۔ console.log("اسنیپ شاٹ:"، ایکٹیو پیڈز)؛ الرٹ (اسنیپ شاٹ لیا گیا! ${activePads.length} کنٹرولر کو پکڑ لیا گیا)؛ });
سنیپ شاٹس وقت میں ایک لمحے میں آپ کے کنٹرولر کی صحیح حالت کو منجمد کر دیتے ہیں۔ 4. گھوسٹ ان پٹ ری پلے اب تفریح کے لئے: گھوسٹ ان پٹ ری پلے۔ یہ ایک لاگ لیتا ہے اور اسے بصری طور پر چلاتا ہے جیسے کوئی پریت کھلاڑی کنٹرولر استعمال کر رہا ہو۔
ری پلے کے لیے جاوا اسکرپٹ: // ================================== // گھوسٹ ری پلے // ==================================
document.getElementById("replay").addEventListener("click"، () => { // یقینی بنائیں کہ ہمارے پاس دوبارہ چلانے کے لیے ریکارڈنگ موجود ہے۔ اگر (!frames.length) { الرٹ ("دوبارہ چلانے کے لیے کوئی ریکارڈنگ نہیں!")؛ واپسی }
console.log("بھوت ری پلے شروع کر رہا ہے...")؛
// مطابقت پذیر پلے بیک کے لیے ٹریک ٹائمنگ let startTime = performance.now(); فریم انڈیکس = 0؛
// حرکت پذیری لوپ کو دوبارہ چلائیں۔ فنکشن مرحلہ () { const now = performance.now(); const elapsed = now - starttime;
// ان تمام فریموں پر کارروائی کریں جو اب تک ہو چکے ہوں گے۔ جبکہ (frameIndex < frames.length && frames[frameIndex].t <= گزر گیا) { const frame = frames[frameIndex]؛
// ریکارڈ شدہ بٹن ریاستوں کے ساتھ UI کو اپ ڈیٹ کریں۔ btnA.classList.toggle("active", frame.buttons[0].pressed); btnB.classList.toggle("active", frame.buttons[1].pressed); btnX.classList.toggle("active"، frame.buttons[2].pressed)؛
// اسٹیٹس ڈسپلے کو اپ ڈیٹ کریں۔ let pressed = []؛ frame.buttons.forEach((btn, i) => { اگر (btn.pressed) pressed.push("بٹن" + i)؛ }); اگر (دبائی گئی لمبائی > 0) { status.textContent = "Ghost:" + pressed.join(", "); }
frameIndex++; }
// اگر مزید فریم ہوں تو لوپ جاری رکھیں
اگر (frameIndex // ری پلے شروع کریں۔
قدم ()؛
}); ڈیبگنگ کو کچھ زیادہ ہینڈ آن کرنے کے لیے، میں نے ایک گھوسٹ ری پلے شامل کیا۔ ایک بار جب آپ سیشن ریکارڈ کر لیتے ہیں، تو آپ ری پلے کو مار سکتے ہیں اور UI کو اس پر عمل کرتے ہوئے دیکھ سکتے ہیں، تقریباً اس طرح جیسے کوئی فینٹم پلیئر پیڈ چلا رہا ہو۔ اس کے لیے پینل میں ایک نیا ری پلے گوسٹ بٹن ظاہر ہوتا ہے۔ ریکارڈ کو دبائیں، کنٹرولر کے ساتھ تھوڑا سا گڑبڑ کریں، رکیں، پھر دوبارہ چلائیں۔ UI آپ کے ہر کام کی بازگشت کرتا ہے، جیسے آپ کے ان پٹس کی پیروی کرنے والا بھوت۔
ان اضافی چیزوں سے پریشان کیوں؟ ریکارڈنگ/ایکسپورٹ ٹیسٹرز کے لیے یہ دکھانا آسان بناتا ہے کہ کیا ہوا ہے۔
سنیپ شاٹس وقت کے ساتھ ایک لمحے کو منجمد کر دیتے ہیں، جب آپ عجیب و غریب کیڑوں کا پیچھا کر رہے ہوتے ہیں تو بہت مفید ہوتا ہے۔
گھوسٹ ری پلے ٹیوٹوریلز، ایکسیسبیلٹی چیکس، یا صرف کنٹرول سیٹ اپس کا ساتھ ساتھ موازنہ کرنے کے لیے بہت اچھا ہے۔ اس وقت، یہ اب صرف ایک صاف ستھرا ڈیمو نہیں ہے، بلکہ کچھ ایسا ہے جسے آپ حقیقت میں کام کر سکتے ہیں۔
حقیقی دنیا کے استعمال کے معاملات
اب ہمارے پاس یہ ڈیبگر ہے جو بہت کچھ کرسکتا ہے۔ یہ لائیو ان پٹ دکھاتا ہے، نوشتہ جات کو ریکارڈ کرتا ہے، انہیں برآمد کرتا ہے، اور یہاں تک کہ چیزیں دوبارہ چلاتا ہے۔ لیکن اصل سوال یہ ہے کہ: اصل میں کون پرواہ کرتا ہے؟ یہ کس کے لیے مفید ہے؟
کھیل ڈویلپرز
کنٹرولرز کام کا حصہ ہیں، لیکن انہیں ڈیبگ کرنا؟ عام طور پر درد ہوتا ہے۔ تصور کریں کہ آپ فائٹنگ گیم کومبو کی جانچ کر رہے ہیں، جیسے ↓ → + پنچ۔ نماز پڑھنے کے بجائے، آپ نے اسے دو بار اسی طرح دبایا، آپ اسے ایک بار ریکارڈ کریں، اور اسے دوبارہ چلائیں۔ ہو گیا یا آپ JSON لاگز کو ٹیم کے ساتھی کے ساتھ تبدیل کرتے ہیں تاکہ یہ چیک کیا جا سکے کہ آیا آپ کا ملٹی پلیئر کوڈ ان کی مشین پر ایک جیسا رد عمل ظاہر کرتا ہے۔ یہ بہت بڑا ہے۔
ایکسیسبیلٹی پریکٹیشنرز
یہ میرے دل کے قریب ہے۔ ہر کوئی "معیاری" کنٹرولر کے ساتھ نہیں کھیلتا ہے۔ انکولی کنٹرولرز بعض اوقات عجیب و غریب سگنل پھینک دیتے ہیں۔ اس ٹول کے ساتھ، آپ بالکل دیکھ سکتے ہیں کہ کیا ہو رہا ہے۔ اساتذہ، محققین، کوئی بھی۔ وہ نوشتہ جات کو پکڑ سکتے ہیں، ان کا موازنہ کر سکتے ہیں، یا ان پٹ کو ساتھ ساتھ دوبارہ چلا سکتے ہیں۔ اچانک، پوشیدہ چیزیں واضح ہو جاتی ہیں.
کوالٹی اشورینس ٹیسٹنگ
ٹیسٹر عام طور پر نوٹ لکھتے ہیں جیسے "میں نے یہاں بٹن میش کیے اور یہ ٹوٹ گیا۔" بہت مددگار نہیں۔ اب؟ وہ عین مطابق پریس کو پکڑ سکتے ہیں، لاگ کو برآمد کر سکتے ہیں اور اسے بھیج سکتے ہیں۔ کوئی اندازہ نہیں۔
معلمین
اگر آپ سبق یا YouTube vids بنا رہے ہیں، تو بھوت ری پلے سونے کا ہے۔ آپ لفظی طور پر کہہ سکتے ہیں، "میں نے کنٹرولر کے ساتھ کیا کیا،" جب کہ UI یہ ظاہر کرتا ہے۔ وضاحتوں کو مزید واضح کرتا ہے۔
گیمز سے آگے
اور ہاں، یہ صرف گیمز کے بارے میں نہیں ہے۔ لوگوں نے روبوٹ، آرٹ پروجیکٹس، اور ایکسیسبیلٹی انٹرفیس کے لیے کنٹرولرز کا استعمال کیا ہے۔ ہر بار ایک ہی مسئلہ: براؤزر اصل میں کیا دیکھ رہا ہے؟ اس کے ساتھ، آپ کو اندازہ لگانے کی ضرورت نہیں ہے۔
نتیجہ
کنٹرولر ان پٹ کو ڈیبگ کرنا ہمیشہ اندھا ہونے کی طرح محسوس ہوتا ہے۔ DOM یا CSS کے برعکس، گیم پیڈز کے لیے کوئی بلٹ ان انسپکٹر نہیں ہے۔ یہ کنسول میں صرف کچے نمبر ہیں، شور میں آسانی سے کھو جاتے ہیں۔
HTML، CSS اور JavaScript کی چند سو لائنوں کے ساتھ، ہم نے کچھ مختلف بنایا: ایک بصری ڈیبگر جو پوشیدہ ان پٹ کو مرئی بناتا ہے۔
ایک تہوں والا CSS سسٹم جو UI کو صاف اور ڈیبگ ایبل رکھتا ہے۔
اضافہ کا ایک سیٹ (ریکارڈنگ، ایکسپورٹنگ، سنیپ شاٹس، گھوسٹ ری پلے) جو اسے ڈیمو سے ڈویلپر ٹول تک بڑھاتا ہے۔ یہ پروجیکٹ دکھاتا ہے کہ آپ ویب پلیٹ فارم کی طاقت کو CSS Cascade Layers میں تھوڑی تخلیقی صلاحیتوں کے ساتھ ملا کر کتنی دور جا سکتے ہیں۔
جس ٹول کی میں نے ابھی پوری وضاحت کی ہے وہ اوپن سورس ہے۔ آپ GitHub ریپو کو کلون کر سکتے ہیں اور اسے اپنے لیے آزما سکتے ہیں۔
لیکن زیادہ اہم بات یہ ہے کہ آپ اسے اپنا بنا سکتے ہیں۔ اپنی اپنی پرتیں شامل کریں۔ اپنی خود کی ری پلے منطق بنائیں۔ اسے اپنے گیم پروٹو ٹائپ کے ساتھ مربوط کریں۔ یا یہاں تک کہ اسے ان طریقوں سے استعمال کریں جن کا میں نے تصور بھی نہیں کیا ہے۔ تعلیم، رسائی، یا ڈیٹا کے تجزیہ کے لیے۔
دن کے اختتام پر، یہ صرف گیم پیڈ کو ڈیبگ کرنے کے بارے میں نہیں ہے۔ یہ پوشیدہ ان پٹس پر روشنی ڈالنے، اور ڈویلپرز کو ہارڈ ویئر کے ساتھ کام کرنے کا اعتماد دینے کے بارے میں ہے جسے ویب ابھی بھی پوری طرح سے قبول نہیں کرتا ہے۔
لہذا، اپنے کنٹرولر کو پلگ ان کریں، اپنا ایڈیٹر کھولیں، اور تجربہ کرنا شروع کریں۔ آپ حیران ہوں گے کہ آپ کا براؤزر اور آپ کا CSS واقعی کیا کر سکتا ہے۔