যখন আপনি একটি কন্ট্রোলার প্লাগ ইন করেন, আপনি বোতামগুলি ম্যাশ করেন, লাঠিগুলি সরান, ট্রিগারগুলি টানুন... এবং একজন বিকাশকারী হিসাবে, আপনি এর কিছুই দেখতে পান না। ব্রাউজার এটি তুলে নিচ্ছে, নিশ্চিত, কিন্তু আপনি যদি কনসোলে নম্বর লগিং না করেন, এটি অদৃশ্য। গেমপ্যাড API এর সাথে এটি মাথাব্যথা। এটি বছরের পর বছর ধরে চলছে এবং এটি আসলে বেশ শক্তিশালী। আপনি বোতাম, লাঠি, ট্রিগার, কাজগুলি পড়তে পারেন। কিন্তু অধিকাংশ মানুষ এটা স্পর্শ করে না। কেন? কারণ কোন প্রতিক্রিয়া নেই। বিকাশকারী সরঞ্জামগুলিতে কোনও প্যানেল নেই৷ কন্ট্রোলার এমনকি আপনি যা ভাবছেন তা করছেন কিনা তা জানার কোনও পরিষ্কার উপায় নেই। উড়ন্ত অন্ধের মতো লাগছে। এটি আমাকে একটি ছোট টুল তৈরি করতে যথেষ্ট বাগ করেছে: গেমপ্যাড ক্যাসকেড ডিবাগার। কনসোল আউটপুটের দিকে তাকানোর পরিবর্তে, আপনি কন্ট্রোলারের একটি লাইভ, ইন্টারেক্টিভ ভিউ পাবেন। কিছু টিপুন এবং এটি স্ক্রিনে প্রতিক্রিয়া দেখায়। এবং CSS ক্যাসকেড স্তরগুলির সাথে, শৈলীগুলি সংগঠিত থাকে, তাই এটি ডিবাগ করা আরও পরিষ্কার। এই পোস্টে, আমি আপনাকে দেখাব কেন ডিবাগিং কন্ট্রোলারগুলি এত ব্যথা, কীভাবে CSS এটি পরিষ্কার করতে সহায়তা করে এবং কীভাবে আপনি আপনার নিজের প্রকল্পগুলির জন্য একটি পুনরায় ব্যবহারযোগ্য ভিজ্যুয়াল ডিবাগার তৈরি করতে পারেন।

এমনকি যদি আপনি সেগুলি সবগুলি লগ করতে সক্ষম হন, আপনি দ্রুত অপঠিত কনসোল স্প্যামের সাথে শেষ হয়ে যাবেন৷ যেমন: [০,০,১,০,০,০.৫,০,...] [০,০,০,০,১,০,০,...] [0,0,1,0,0,0,0,...]

বলতে পারেন কোন বোতাম টিপে? হতে পারে, কিন্তু শুধুমাত্র আপনার চোখ স্ট্রেন এবং কয়েক ইনপুট অনুপস্থিত পরে. সুতরাং, না, ইনপুট পড়ার ক্ষেত্রে ডিবাগিং সহজে আসে না। সমস্যা 3: কাঠামোর অভাব এমনকি আপনি একটি দ্রুত ভিজ্যুয়ালাইজার একসাথে নিক্ষেপ করলেও, শৈলীগুলি দ্রুত অগোছালো হয়ে যেতে পারে। ডিফল্ট, সক্রিয় এবং ডিবাগ স্টেটগুলি ওভারল্যাপ করতে পারে এবং একটি পরিষ্কার কাঠামো ছাড়াই, আপনার CSS ভঙ্গুর এবং প্রসারিত করা কঠিন হয়ে যায়। CSS ক্যাসকেড স্তর সাহায্য করতে পারে। তারা শৈলীগুলিকে "স্তরগুলিতে" গোষ্ঠীভুক্ত করে যা অগ্রাধিকার অনুসারে অর্ডার করা হয়, তাই আপনি নির্দিষ্টতার সাথে লড়াই করা বন্ধ করেন এবং অনুমান করেন, "কেন আমার ডিবাগ শৈলী দেখা যাচ্ছে না?" পরিবর্তে, আপনি পৃথক উদ্বেগ বজায় রাখুন:

বেস: নিয়ামকের মান, প্রাথমিক চেহারা। সক্রিয়: চাপা বোতাম এবং সরানো লাঠিগুলির জন্য হাইলাইট। ডিবাগ: ডেভেলপারদের জন্য ওভারলে (যেমন, সাংখ্যিক রিডআউট, গাইড ইত্যাদি)।

আমরা যদি এটি অনুসারে CSS-এ স্তরগুলিকে সংজ্ঞায়িত করতে চাই, তাহলে আমাদের থাকবে: /* সর্বনিম্ন থেকে সর্বোচ্চ অগ্রাধিকার */ @লেয়ার বেস, সক্রিয়, ডিবাগ;

@লেয়ার বেস { /* ... */ }

@লেয়ার সক্রিয় { /* ... */ }

@লেয়ার ডিবাগ { /* ... */ }

যেহেতু প্রতিটি স্তর পূর্বাভাসিতভাবে স্ট্যাক করে, আপনি সর্বদা জানেন কোন নিয়মগুলি জিতবে। এই ভবিষ্যদ্বাণী ডিবাগিংকে সহজ করে না, কিন্তু আসলে পরিচালনাযোগ্য করে তোলে। আমরা সমস্যা (অদৃশ্য, অগোছালো ইনপুট) এবং পদ্ধতি (ক্যাসকেড স্তরগুলির সাথে নির্মিত একটি ভিজ্যুয়াল ডিবাগার) কভার করেছি। এখন আমরা ডিবাগার তৈরি করার জন্য ধাপে ধাপে প্রক্রিয়ার মধ্য দিয়ে যাব। ডিবাগার ধারণা লুকানো ইনপুট দৃশ্যমান করার সবচেয়ে সহজ উপায় হল স্ক্রিনে এটি আঁকা। এই ডিবাগার এটি কি করে। বোতাম, ট্রিগার এবং জয়স্টিক সবই একটি ভিজ্যুয়াল পায়।

A টিপুন: একটি বৃত্ত আলোকিত হয়। লাঠি নাজ: বৃত্তটি চারপাশে স্লাইড করে। একটি ট্রিগার অর্ধেক টানুন: একটি বার অর্ধেক পূর্ণ হয়।

এখন আপনি 0 এবং 1 সেকেন্ডের দিকে তাকাচ্ছেন না, কিন্তু আসলে কন্ট্রোলারের লাইভ প্রতিক্রিয়া দেখছেন। অবশ্যই, একবার আপনি ডিফল্ট, চাপা, ডিবাগ তথ্য, এমনকি একটি রেকর্ডিং মোডের মতো স্টেটগুলিতে পাইলিং শুরু করলে, CSS আরও বড় এবং জটিল হতে শুরু করে। সেখানেই ক্যাসকেড স্তরগুলি কাজে আসে। এখানে একটি স্ট্রাইপ-ডাউন উদাহরণ: @লেয়ার বেস { .বোতাম { পটভূমি: #222; সীমানা-ব্যাসার্ধ: 50%; প্রস্থ: 40px; উচ্চতা: 40px; } }

@লেয়ার সক্রিয় { .button.pressed { পটভূমি: #0f0; /* উজ্জ্বল সবুজ */ } }

@লেয়ার ডিবাগ { বোতাম::পরে { বিষয়বস্তু: attr(ডেটা-মান); ফন্ট-আকার: 12px; রঙ: #fff; } }

লেয়ার অর্ডার গুরুত্বপূর্ণ: বেস → সক্রিয় → ডিবাগ।

বেস নিয়ামক আঁকে। সক্রিয় হ্যান্ডেল চাপা অবস্থা. ওভারলে ডিবাগ নিক্ষেপ.

এটিকে এভাবে ভেঙে ফেলার অর্থ আপনি অদ্ভুত নির্দিষ্টতার যুদ্ধে লড়াই করছেন না। প্রতিটি স্তরের তার জায়গা আছে, এবং আপনি সর্বদা জানেন কি জিতেছে। বিল্ডিং ইট আউট প্রথমে পর্দায় কিছু পাওয়া যাক। এটিকে ভাল দেখাতে হবে না - শুধু বিদ্যমান থাকা দরকার তাই আমাদের সাথে কাজ করার কিছু আছে।

গেমপ্যাড ক্যাসকেড ডিবাগার

A
B
X

ডিবাগার নিষ্ক্রিয়

এটি আক্ষরিকভাবে কেবল বাক্স। এখনও উত্তেজনাপূর্ণ নয়, তবে এটি আমাদেরকে CSS এবং JavaScript এর সাথে পরে দখল করার জন্য হ্যান্ডেল দেয়। ঠিক আছে, আমি এখানে ক্যাসকেড স্তরগুলি ব্যবহার করছি কারণ আপনি আরও রাজ্য যোগ করার পরে এটি জিনিসগুলিকে সংগঠিত রাখে। এখানে একটি মোটামুটি পাস আছে:

/* =================================== ক্যাসকেড স্তর সেটআপ অর্ডার সংক্রান্ত বিষয়: বেস → সক্রিয় → ডিবাগ ======================================*/

/* আপফ্রন্ট লেয়ার অর্ডার সংজ্ঞায়িত করুন */ @লেয়ার বেস, সক্রিয়, ডিবাগ;

/* স্তর 1: বেস শৈলী - ডিফল্ট উপস্থিতি */ @লেয়ার বেস { .বোতাম { পটভূমি: #333; সীমানা-ব্যাসার্ধ: 50%; প্রস্থ: 70px; উচ্চতা: 70px; প্রদর্শন: flex; justify-content: কেন্দ্র; align-items: কেন্দ্র; }

.পজ { প্রস্থ: 20px; উচ্চতা: 70px; পটভূমি: #333; প্রদর্শন: ইনলাইন-ব্লক; } }

/* স্তর 2: সক্রিয় অবস্থা - চাপা বোতামগুলি পরিচালনা করে */ @লেয়ার সক্রিয় { .button.active { পটভূমি: #0f0; /* টিপলে উজ্জ্বল সবুজ */ রূপান্তর: স্কেল (1.1); /* বোতামটি সামান্য বড় করে */ }

.pause.active { পটভূমি: #0f0; রূপান্তর: স্কেলওয়াই(1.1); /* চাপ দিলে উল্লম্বভাবে প্রসারিত হয় */ } }

/* স্তর 3: ডিবাগ ওভারলে - বিকাশকারীর তথ্য */ @লেয়ার ডিবাগ { বোতাম::পরে { বিষয়বস্তু: attr(ডেটা-মান); /* সাংখ্যিক মান দেখায় */ ফন্ট-আকার: 12px; রঙ: #fff; } }

এই পদ্ধতির সৌন্দর্য হল প্রতিটি স্তরের একটি স্পষ্ট উদ্দেশ্য রয়েছে। বেস লেয়ার কখনই সক্রিয়কে ওভাররাইড করতে পারে না, এবং সক্রিয় কখনই ডিবাগকে ওভাররাইড করতে পারে না, নির্দিষ্টতা নির্বিশেষে। এটি সিএসএস নির্দিষ্টতা যুদ্ধগুলিকে দূর করে যা সাধারণত ডিবাগিং সরঞ্জামগুলিকে প্লেগ করে। এখন মনে হচ্ছে কিছু ক্লাস্টার অন্ধকার পটভূমিতে বসে আছে। সত্যি, খুব খারাপ না।

জাভাস্ক্রিপ্ট যোগ করা হচ্ছে জাভাস্ক্রিপ্ট সময়। এই যেখানে নিয়ামক আসলে কিছু করে. আমরা এই ধাপে ধাপে তৈরি করব। ধাপ 1: স্টেট ম্যানেজমেন্ট সেট আপ করুন প্রথমত, ডিবাগারের অবস্থা ট্র্যাক করতে আমাদের ভেরিয়েবলের প্রয়োজন: // ================================== // রাজ্য ব্যবস্থাপনা // ==================================

চলুন = মিথ্যা; // ডিবাগার সক্রিয় কিনা তা ট্র্যাক করে rafId যাক; // বাতিল করার জন্য অনুরোধ অ্যানিমেশনফ্রেম আইডি সংরক্ষণ করে

এই ভেরিয়েবলগুলি অ্যানিমেশন লুপ নিয়ন্ত্রণ করে যা ক্রমাগত গেমপ্যাড ইনপুট পড়ে। ধাপ 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 অবস্থা = document.getElementById("স্থিতি");

এই রেফারেন্সগুলিকে সামনে সংরক্ষণ করা DOM-কে বারবার জিজ্ঞাসা করার চেয়ে বেশি কার্যকর। ধাপ 3: কীবোর্ড ফলব্যাক যোগ করুন শারীরিক কন্ট্রোলার ছাড়া পরীক্ষার জন্য, আমরা বোতামগুলিতে কীবোর্ড কীগুলি ম্যাপ করব: // ================================== // কীবোর্ড ফলব্যাক (কোনও নিয়ামক ছাড়া পরীক্ষার জন্য) // ==================================

const keyMap = { "a": btnA, "b": btnB, "x": btnX, "p": [pause1, pause2] // 'p' কী উভয় পজ বার নিয়ন্ত্রণ করে };

এটি আমাদের একটি কীবোর্ডে কী টিপে UI পরীক্ষা করতে দেয়। ধাপ 4: প্রধান আপডেট লুপ তৈরি করুন এখানে যাদুটি ঘটে। এই ফাংশনটি ক্রমাগত চলে এবং গেমপ্যাডের অবস্থা পড়ে: // ================================== // প্রধান গেমপ্যাড আপডেট লুপ // ==================================

ফাংশন আপডেট গেমপ্যাড() { // সমস্ত সংযুক্ত গেমপ্যাড পান const gamepads = navigator.getGamepads(); যদি (!gamepads) ফিরে আসে;

// প্রথম সংযুক্ত গেমপ্যাড ব্যবহার করুন const gp = gamepads[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("সক্রিয়", বিরতি চাপা);

// অবস্থা প্রদর্শনের জন্য বর্তমানে চাপা বোতামগুলির একটি তালিকা তৈরি করুন let pressed = []; gp.buttons.forEach((btn, i) => { যদি (btn. চাপা)pressed.push("বোতাম" + i); });

// কোনো বোতাম চাপলে স্ট্যাটাস টেক্সট আপডেট করুন যদি (চাপা.দৈর্ঘ্য > 0) { status.textContent = "চাপা: " + pressed.join(", "); } }

// ডিবাগার চলমান থাকলে লুপটি চালিয়ে যান যদি (চলমান) { rafId = অনুরোধ অ্যানিমেশন ফ্রেম(আপডেট গেমপ্যাড); } }

classList.toggle() পদ্ধতিটি বাটন টিপছে কিনা তার উপর ভিত্তি করে সক্রিয় ক্লাস যোগ বা মুছে দেয়, যা আমাদের CSS স্তর শৈলীগুলিকে ট্রিগার করে। ধাপ 5: কীবোর্ড ইভেন্টগুলি পরিচালনা করুন এই ইভেন্ট শ্রোতারা কীবোর্ড ফলব্যাক কাজ করে: // ================================== // কীবোর্ড ইভেন্ট হ্যান্ডলার // ==================================

document.addEventListener("keydown", (e) => { যদি (কীম্যাপ[ই.কী]) { // একক বা একাধিক উপাদান পরিচালনা করুন যদি (Array.isArray(keyMap[e.key])) { keyMap[e.key].forEach(el => el.classList.add("active")); } অন্য { keyMap[e.key].classList.add("active"); } status.textContent = "কী চাপা: " + e.key.toUpperCase(); } });

document.addEventListener("keyup", (e) => { যদি (কীম্যাপ[ই.কী]) { // কী রিলিজ হলে সক্রিয় অবস্থা সরান যদি (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("ক্লিক", () => { চলমান = !চলছে; // চলমান অবস্থায় ফ্লিপ করুন

যদি (চলমান) { status.textContent = "ডিবাগার চলছে..."; আপডেট গেমপ্যাড(); // আপডেট লুপ শুরু করুন } অন্য { status.textContent = "ডিবাগার নিষ্ক্রিয়"; বাতিল অ্যানিমেশন ফ্রেম(রাফিআইডি); // লুপ বন্ধ করুন } });

তাই হ্যাঁ, একটি বোতাম টিপুন এবং এটি জ্বলে ওঠে। লাঠি ধাক্কা এবং এটি সরানো. এটাই। আরও একটি জিনিস: কাঁচা মান। কখনও কখনও আপনি কেবল সংখ্যা দেখতে চান, আলো নয়।

এই পর্যায়ে, আপনি দেখতে হবে:

একটি সাধারণ অন-স্ক্রীন নিয়ামক, আপনি তাদের সাথে ইন্টারঅ্যাক্ট করার সাথে সাথে যে বোতামগুলি প্রতিক্রিয়া দেখায়, এবং একটি ঐচ্ছিক ডিবাগ রিডআউট প্রেস করা বোতাম সূচকগুলি দেখাচ্ছে৷

এটিকে কম বিমূর্ত করতে, এখানে অন-স্ক্রিন কন্ট্রোলারের রিয়েল টাইমে প্রতিক্রিয়া দেখানোর একটি দ্রুত ডেমো রয়েছে:

এখন, স্টার্ট রেকর্ডিং চাপলে সবকিছু লগ হয়ে যায় যতক্ষণ না আপনি রেকর্ডিং বন্ধ করুন। 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); }

এই ফাংশনটি আপনার ডেটা থেকে একটি ব্লব (বাইনারী বড় বস্তু) তৈরি করে, এটির জন্য একটি অস্থায়ী URL তৈরি করে এবং প্রোগ্রাম্যাটিকভাবে একটি ডাউনলোড লিঙ্কে ক্লিক করে কাজ করে। ক্লিনআপ নিশ্চিত করে যে আমরা মেমরি লিক করব না। ধাপ 2: JSON এক্সপোর্ট পরিচালনা করুন JSON সম্পূর্ণ ডেটা কাঠামো সংরক্ষণের জন্য উপযুক্ত:

// ================================== // JSON হিসাবে রপ্তানি করুন // ==================================

document.getElementById("export-json").addEventListener("ক্লিক", () => { // রপ্তানি করার কিছু আছে কিনা তা পরীক্ষা করুন যদি (!frames.length) { console.warn("রপ্তানির জন্য কোনো রেকর্ডিং উপলব্ধ নেই।"); প্রত্যাবর্তন }

// মেটাডেটা এবং ফ্রেম সহ একটি পেলোড তৈরি করুন const payload = { তৈরিকৃত সময়ে: নতুন তারিখ().toISOSstring(), ফ্রেম };

// ফরম্যাট JSON হিসাবে ডাউনলোড করুন ডাউনলোড ফাইল( "gamepad-log.json", JSON.stringify(পেলোড, নাল, 2), "অ্যাপ্লিকেশন/জেসন" ); });

JSON ফরম্যাট সবকিছুকে সুগঠিত এবং সহজে বিশ্লেষণযোগ্য রাখে, এটিকে ডেভ টুলে আবার লোড করা বা সতীর্থদের সাথে শেয়ার করার জন্য আদর্শ করে তোলে। ধাপ 3: CSV এক্সপোর্ট পরিচালনা করুন CSV রপ্তানির জন্য, আমাদের সারি এবং কলামে শ্রেণিবদ্ধ ডেটা সমতল করতে হবে:

//=================================== // CSV হিসাবে রপ্তানি করুন // ==================================

document.getElementById("export-csv").addEventListener("ক্লিক", () => { // রপ্তানি করার কিছু আছে কিনা তা পরীক্ষা করুন যদি (!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 সারি = frames.map(f => { const btnVals = f.buttons.map(b => b.value); ফেরত [f.t, ...btnVals, ...f.axes].join(","); }) যোগ দিন("\n");

// CSV হিসেবে ডাউনলোড করুন ডাউনলোড ফাইল("gamepad-log.csv", হেডার + সারি, "টেক্সট/সিএসভি"); });

CSV ডেটা বিশ্লেষণের জন্য উজ্জ্বল কারণ এটি সরাসরি Excel বা Google Sheets-এ খোলে, যা আপনাকে চার্ট, ফিল্টার ডেটা বা স্পট প্যাটার্ন তৈরি করতে দেয়। এখন যেহেতু রপ্তানি বোতাম রয়েছে, আপনি প্যানেলে দুটি নতুন বিকল্প দেখতে পাবেন: JSON এবং রপ্তানি CSV। আপনি যদি কাঁচা লগটিকে আপনার ডেভ টুলগুলিতে ফেলে দিতে চান বা কাঠামোর চারপাশে খোঁচা দিতে চান তবে JSON চমৎকার। অন্যদিকে, CSV সরাসরি এক্সেল বা গুগল শীটে খোলে যাতে আপনি ইনপুটগুলি চার্ট, ফিল্টার বা তুলনা করতে পারেন। নিম্নলিখিত চিত্রটি সেই অতিরিক্ত নিয়ন্ত্রণগুলির সাথে প্যানেলটি দেখতে কেমন তা দেখায়৷

3. স্ন্যাপশট সিস্টেম কখনও কখনও আপনার একটি সম্পূর্ণ রেকর্ডিং প্রয়োজন হয় না, শুধুমাত্র ইনপুট অবস্থার একটি দ্রুত "স্ক্রিনশট"। সেখানেই একটি টেক স্ন্যাপশট বোতাম সাহায্য করে।

এবং জাভাস্ক্রিপ্ট:

// ================================== // স্ন্যাপশট নিন // ==================================

document.getElementById("snapshot").addEventListener("ক্লিক", () => { // সমস্ত সংযুক্ত গেমপ্যাড পান 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); সতর্কতা(স্ন্যাপশট নেওয়া হয়েছে! ক্যাপচার করা হয়েছে ${activePads.length} কন্ট্রোলার(গুলি)); });

স্ন্যাপশটগুলি এক মুহুর্তে আপনার কন্ট্রোলারের সঠিক অবস্থা হিমায়িত করে। 4. ঘোস্ট ইনপুট রিপ্লে এখন মজার জন্য: ভূত ইনপুট রিপ্লে। এটি একটি লগ নেয় এবং এটিকে দৃশ্যমানভাবে প্লে করে যেন একটি ফ্যান্টম প্লেয়ার কন্ট্রোলার ব্যবহার করছে।

পুনরায় খেলার জন্য জাভাস্ক্রিপ্ট: // ================================== // ভূত রিপ্লে // ==================================

document.getElementById("রিপ্লে")।addEventListener("ক্লিক", () => { // আমাদের রিপ্লে করার জন্য একটি রেকর্ডিং আছে তা নিশ্চিত করুন যদি (!frames.length) { সতর্কতা ("রিপ্লে করার জন্য কোন রেকর্ডিং নেই!"); প্রত্যাবর্তন }

console.log("ভূত রিপ্লে শুরু হচ্ছে...");

// সিঙ্ক করা প্লেব্যাকের জন্য সময় ট্র্যাক করুন যাক startTime = performance.now(); যাক frameIndex = 0;

// রিপ্লে অ্যানিমেশন লুপ ফাংশন ধাপ() { const now = performance.now(); const elapsed = now - starttime;

// এখন পর্যন্ত হওয়া উচিত ছিল এমন সমস্ত ফ্রেম প্রক্রিয়া করুন যখন (frameIndex < frames.length && frames[frameIndex].t <= অতিবাহিত) { const frame = ফ্রেম[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) => { if (btn.pressed) pressed.push("Button" + i); }); যদি (চাপা.দৈর্ঘ্য > 0) { status.textContent = "ভূত: " + pressed.join(", "); }

frameIndex++; }

// আরও ফ্রেম থাকলে লুপ চালিয়ে যান যদি (frameIndex < frames.length) { অনুরোধ অ্যানিমেশন ফ্রেম (ধাপ); } অন্য { console.log("রিপ্লেসমাপ্ত।"); status.textContent = "রিপ্লে সম্পূর্ণ"; } }

// রিপ্লে শুরু করুন পদক্ষেপ(); });

ডিবাগিংকে একটু বেশি হ্যান্ড-অন করতে, আমি একটি ভূত রিপ্লে যোগ করেছি। একবার আপনি একটি সেশন রেকর্ড করার পরে, আপনি রিপ্লে হিট করতে পারেন এবং দেখতে পারেন যে UI এটি কাজ করে, প্রায় কোনও ফ্যান্টম প্লেয়ার প্যাড চালাচ্ছে। এর জন্য প্যানেলে একটি নতুন রিপ্লে ঘোস্ট বোতাম প্রদর্শিত হবে।

রেকর্ড হিট করুন, কন্ট্রোলারের সাথে একটু গোলমাল করুন, থামুন, তারপর রিপ্লে করুন। UI আপনার করা সমস্ত কিছুর প্রতিধ্বনি করে, আপনার ইনপুট অনুসরণ করা ভূতের মতো। কেন এই অতিরিক্ত নিয়ে বিরক্ত?

রেকর্ডিং/রপ্তানি পরীক্ষকদের জন্য ঠিক কী ঘটেছে তা দেখানো সহজ করে তোলে। স্ন্যাপশটগুলি সময়ের মধ্যে একটি মুহূর্ত জমে যায়, যখন আপনি বিজোড় বাগগুলি তাড়া করছেন তখন খুব দরকারী৷ ঘোস্ট রিপ্লে টিউটোরিয়াল, অ্যাক্সেসিবিলিটি চেক, বা পাশাপাশি কন্ট্রোল সেটআপ তুলনা করার জন্য দুর্দান্ত।

এই মুহুর্তে, এটি আর কেবল একটি ঝরঝরে ডেমো নয়, তবে এমন কিছু যা আপনি আসলে কাজ করতে পারেন। বাস্তব-বিশ্ব ব্যবহারের ক্ষেত্রে এখন আমরা এই ডিবাগার পেয়েছি যা অনেক কিছু করতে পারে। এটি লাইভ ইনপুট দেখায়, লগ রেকর্ড করে, রপ্তানি করে এবং এমনকি স্টাফ রিপ্লে করে। কিন্তু আসল প্রশ্ন হল: কে আসলে চিন্তা করে? এটি কার জন্য দরকারী? গেম ডেভেলপার কন্ট্রোলার কাজের অংশ, কিন্তু তাদের ডিবাগিং? সাধারণত একটি ব্যথা। কল্পনা করুন আপনি একটি ফাইটিং গেম কম্বো পরীক্ষা করছেন, যেমন ↓ → + পাঞ্চ। প্রার্থনা করার পরিবর্তে, আপনি এটিকে একইভাবে দুবার চাপলেন, আপনি এটি একবার রেকর্ড করুন এবং এটি পুনরায় চালান। সম্পন্ন অথবা আপনি আপনার মাল্টিপ্লেয়ার কোড তাদের মেশিনে একই প্রতিক্রিয়া দেখায় কিনা তা পরীক্ষা করার জন্য একজন সতীর্থের সাথে JSON লগগুলি অদলবদল করুন৷ এটা বিশাল। অ্যাক্সেসিবিলিটি অনুশীলনকারী এটি আমার হৃদয়ের কাছাকাছি। সবাই একটি "মানক" নিয়ামক দিয়ে খেলে না। অভিযোজিত কন্ট্রোলাররা মাঝে মাঝে অদ্ভুত সংকেত ফেলে দেয়। এই টুল দিয়ে, আপনি ঠিক কি ঘটছে দেখতে পারেন. শিক্ষক, গবেষক, যেই হোক না কেন। তারা লগগুলি ধরতে পারে, তাদের তুলনা করতে পারে বা ইনপুটগুলি পাশাপাশি পুনরায় চালাতে পারে। হঠাৎ, অদৃশ্য জিনিস স্পষ্ট হয়ে ওঠে. গুণমান নিশ্চিতকরণ পরীক্ষা পরীক্ষকরা সাধারণত নোট লেখেন যেমন "আমি এখানে বোতাম ম্যাশ করেছি এবং এটি ভেঙে গেছে।" খুব সহায়ক নয়। এখন? তারা সঠিক প্রেসগুলি ক্যাপচার করতে পারে, লগটি রপ্তানি করতে পারে এবং এটিকে পাঠাতে পারে। কোন অনুমান. শিক্ষাবিদদের আপনি যদি টিউটোরিয়াল বা ইউটিউব ভিডিও তৈরি করেন, ভূতের রিপ্লে সোনার। আপনি আক্ষরিক অর্থে বলতে পারেন, "আমি কন্ট্রোলারের সাথে যা করেছি তা এখানে," যখন UI এটি ঘটছে তা দেখায়। ব্যাখ্যাগুলিকে আরও স্পষ্ট করে তোলে। গেমের বাইরে এবং হ্যাঁ, এটি শুধুমাত্র গেমস সম্পর্কে নয়। লোকেরা রোবট, শিল্প প্রকল্প এবং অ্যাক্সেসিবিলিটি ইন্টারফেসের জন্য কন্ট্রোলার ব্যবহার করেছে। প্রতিবার একই সমস্যা: ব্রাউজার আসলে কী দেখছে? এর সাথে, আপনাকে অনুমান করতে হবে না। উপসংহার একটি কন্ট্রোলার ইনপুট ডিবাগ করা সবসময় অন্ধ উড়ন্ত মত অনুভূত হয়. DOM বা CSS এর বিপরীতে, গেমপ্যাডের জন্য কোনো বিল্ট-ইন ইন্সপেক্টর নেই; এটি কনসোলে শুধুমাত্র কাঁচা সংখ্যা, সহজেই গোলমালে হারিয়ে যায়। এইচটিএমএল, সিএসএস এবং জাভাস্ক্রিপ্টের কয়েকশ লাইনের সাহায্যে আমরা আলাদা কিছু তৈরি করেছি:

একটি ভিজ্যুয়াল ডিবাগার যা অদৃশ্য ইনপুটগুলিকে দৃশ্যমান করে তোলে। একটি স্তরযুক্ত CSS সিস্টেম যা UI কে পরিষ্কার এবং ডিবাগযোগ্য রাখে। উন্নতির একটি সেট (রেকর্ডিং, রপ্তানি, স্ন্যাপশট, ভূত রিপ্লে) যা এটিকে ডেমো থেকে ডেভেলপার টুলে উন্নীত করে।

এই প্রকল্পটি দেখায় যে আপনি CSS ক্যাসকেড স্তরগুলিতে সামান্য সৃজনশীলতার সাথে ওয়েব প্ল্যাটফর্মের শক্তি মিশ্রিত করে কতদূর যেতে পারেন। আমি যে টুলটিকে সম্পূর্ণরূপে ব্যাখ্যা করেছি তা হল ওপেন সোর্স। আপনি 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