আপনার গেমপ্যাড দিয়ে Chrome ডাইনো গেম খেলুন

আপনার ওয়েব গেমকে পরবর্তী লেভেলে নিয়ে যেতে Gamepad API কীভাবে ব্যবহার করবেন তা জানুন।

Chrome-এর অফলাইন পৃষ্ঠার ইস্টার এগ হল ইতিহাসের সবচেয়ে খারাপভাবে রাখা গোপন বিষয়গুলির মধ্যে একটি ([citation needed], তবে নাটকীয় প্রভাবের জন্য দাবি করা হয়েছে)। আপনি স্পেস কী প্রেস করলে অথবা মোবাইল ডিভাইসে ডাইনোসরে ট্যাপ করলে, অফলাইন পৃষ্ঠাটি খেলার উপযোগী আর্কেড গেমে পরিণত হয়। আপনি হয়ত জানেন যে খেলতে ইচ্ছে করলে আপনাকে অফলাইন হতে হবে না: Chrome-এ আপনি শুধু about://dino-এ নেভিগেট করতে পারেন অথবা আপনার মধ্যে থাকা গিকদের জন্য about://network-error/-106-এ ব্রাউজ করতে পারেন। কিন্তু আপনি কি জানেন যে প্রতি মাসে ২৭০ মিলিয়ন Chrome ডাইনো গেম খেলা হয়?

Chrome ডাইনো গেম সহ Chrome-এর অফলাইন পৃষ্ঠা।
খেলতে স্পেস কী প্রেস করুন!

আরেকটি তথ্য যা সম্ভবত জানা আরও বেশি উপযোগী এবং আপনি নাও জানতে পারেন যে আর্কেড মোডে আপনি গেমপ্যাড দিয়ে গেম খেলতে পারবেন। এই লেখাটি লেখার সময় থেকে প্রায় এক বছর আগে Reilly Grant-এর করা কমিট-এ গেমপ্যাড সাপোর্ট যোগ করা হয়েছিল। আপনি দেখতেই পাচ্ছেন, Chromium প্রোজেক্টের বাকি অংশের মতো এই গেমটিও সম্পূর্ণ ওপেন সোর্স। এই পোস্টে, আমি আপনাকে দেখাতে চাই যে কীভাবে Gamepad API ব্যবহার করতে হয়।

Gamepad API ব্যবহার করুন

ফিচার শনাক্তকরণ ও ব্রাউজার সাপোর্ট

ডেস্কটপ ও মোবাইল, দুটিতেই Gamepad API-এর জন্য দারুণ ব্রাউজার সাপোর্ট রয়েছে। Gamepad API কাজ করে কিনা তা আপনি নিম্নলিখিত স্নিপেট ব্যবহার করে শনাক্ত করতে পারবেন:

if ('getGamepads' in navigator) {
  // The API is supported!
}

ব্রাউজার কীভাবে গেমপ্যাডকে দেখায়

ব্রাউজার গেমপ্যাডকে Gamepad অবজেক্ট হিসেবে দেখায়। Gamepad-এর নিম্নলিখিত প্রপার্টি আছে:

  • id: গেমপ্যাডের জন্য একটি শনাক্তকরণ স্ট্রিং। এই স্ট্রিং কানেক্ট করা গেমপ্যাড ডিভাইসের ব্র্যান্ড বা স্টাইল শনাক্ত করে।
  • displayId: সংশ্লিষ্ট VRDisplay-এর VRDisplay.displayId (প্রাসঙ্গিক হলে)।
  • index: নেভিগেটরে গেমপ্যাডের ইন্ডেক্স।
  • connected: গেমপ্যাড এখনও সিস্টেমের সাথে কানেক্ট করা আছে কিনা তা দেখায়।
  • hand: কন্ট্রোলারটি কোন হাতে ধরা আছে বা কোন হাতে ধরা থাকার সম্ভাবনা সবচেয়ে বেশি তা নির্ধারণ করে এমন একটি enum।
  • timestamp: এই গেমপ্যাডের ডেটা শেষবার আপডেট করা হয়েছে।
  • mapping: এই ডিভাইসের জন্য ব্যবহার করা বোতাম ও অক্ষের ম্যাপিং, হয় "standard" অথবা "xr-standard"।
  • pose: একটি GamepadPose অবজেক্ট যা WebVR কন্ট্রোলারের সাথে যুক্ত পোজ সংক্রান্ত তথ্য দেখায়।
  • axes: গেমপ্যাডের সব অক্ষের জন্য ভ্যালুর অ্যারে, যা -1.0–1.0 রেঞ্জে লিনিয়ারলি নরমালাইজ করা হয়েছে।
  • buttons: গেমপ্যাডের সব বোতামের জন্য বোতামের স্ট্যাটাসের অ্যারে।

মনে রাখবেন, বোতাম ডিজিটাল (প্রেস করা বা না করা) বা অ্যানালগ (যেমন, ৭৮% প্রেস করা) হতে পারে। এই কারণে বোতামগুলি GamepadButton অবজেক্ট হিসেবে রিপোর্ট করা হয়, যার নিম্নলিখিত অ্যাট্রিবিউট রয়েছে:

  • pressed: বোতামটি প্রেস করা অবস্থায় আছে কিনা (বোতামটি প্রেস করা থাকলে true এবং প্রেস করা না থাকলে false।
  • touched: বোতামের টাচ করা স্ট্যাটাস। বোতামটি টাচ শনাক্ত করতে পারলে, বোতামটি টাচ করা হলে এই প্রপার্টি true হবে এবং অন্যথায় false হবে।
  • value: অ্যানালগ সেন্সর আছে এমন বোতামের ক্ষেত্রে, এই প্রপার্টি বোতামটি কতটা প্রেস করা হয়েছে তা দেখায়, যা 0.0–1.0 রেঞ্জে লিনিয়ারলি নরমালাইজ করা হয়।
  • hapticActuators: একটি অ্যারে যাতে GamepadHapticActuator অবজেক্ট আছে, যার প্রতিটি কন্ট্রোলারে উপলভ্য হ্যাপটিক ফিডব্যাক হার্ডওয়্যারকে দেখায়।

আপনার ব্রাউজার এবং গেমপ্যাডের উপর নির্ভর করে, আপনি আরও একটি সমস্যার সম্মুখীন হতে পারেন, সেটি হল vibrationActuator প্রপার্টি। এটি দুই ধরনের রাম্বল এফেক্টের অনুমতি দেয়:

  • ডুয়াল-রাম্বল: গেমপ্যাডের প্রতিটি গ্রিপে একটি করে দুটি এক্সেন্ট্রিক রোটেটিং মাস অ্যাকচুয়েটর দ্বারা তৈরি হ্যাপটিক ফিডব্যাক এফেক্ট।
  • ট্রিগার-রাম্বল: দুটি স্বতন্ত্র মোটর দ্বারা তৈরি হ্যাপটিক ফিডব্যাক এফেক্ট, যার মধ্যে একটি মোটর গেমপ্যাডের প্রতিটি ট্রিগারে অবস্থিত।

নিম্নলিখিত স্কিম্যাটিক ওভারভিউ, সরাসরি স্পেক থেকে নেওয়া, একটি জেনেরিক গেমপ্যাডে বোতাম এবং অক্ষের ম্যাপিং এবং বিন্যাস দেখায়।

সাধারণ গেমপ্যাডের বোতাম ও অক্ষের ম্যাপিংয়ের স্কিম্যাটিক ওভারভিউ।
স্ট্যান্ডার্ড গেমপ্যাড লেআউটের ভিজ্যুয়াল উপস্থাপনা (সোর্স)।

গেমপ্যাড কানেক্ট করা হলে বিজ্ঞপ্তি

গেমপ্যাড কখন কানেক্ট করা হয়েছে তা জানতে, window অবজেক্টে ট্রিগার করা gamepadconnected ইভেন্ট শুনুন। ব্যবহারকারী যখন USB বা ব্লুটুথ ব্যবহার করে গেমপ্যাড কানেক্ট করেন, তখন একটি GamepadEvent ফায়ার হয় যার মধ্যে গেমপ্যাডের বিবরণ gamepad প্রপার্টিতে থাকে। নিচে, আপনি Xbox 360 কন্ট্রোলারের একটি উদাহরণ দেখতে পাবেন যা আমার কাছে ছিল (হ্যাঁ, আমি রেট্রো গেমিং পছন্দ করি)।

window.addEventListener('gamepadconnected', (event) => {
  console.log('✅ 🎮 A gamepad was connected:', event.gamepad);
  /*
    gamepad: Gamepad
    axes: (4) [0, 0, 0, 0]
    buttons: (17) [GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton]
    connected: true
    id: "Xbox 360 Controller (STANDARD GAMEPAD Vendor: 045e Product: 028e)"
    index: 0
    mapping: "standard"
    timestamp: 6563054.284999998
    vibrationActuator: GamepadHapticActuator {type: "dual-rumble"}
  */
});

গেমপ্যাড ডিসকানেক্ট হয়ে গেলে বিজ্ঞপ্তি

গেমপ্যাড ডিসকানেক্ট হওয়ার বিজ্ঞপ্তি, কানেকশন শনাক্ত করার মতোই একইভাবে কাজ করে। এই সময় অ্যাপটি gamepaddisconnected ইভেন্ট শোনে। নিম্নলিখিত উদাহরণে লক্ষ্য করুন যে Xbox 360 কন্ট্রোলার আনপ্লাগ করার পরে connected এখন false হয়ে গেছে।

window.addEventListener('gamepaddisconnected', (event) => {
  console.log('❌ 🎮 A gamepad was disconnected:', event.gamepad);
  /*
    gamepad: Gamepad
    axes: (4) [0, 0, 0, 0]
    buttons: (17) [GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton]
    connected: false
    id: "Xbox 360 Controller (STANDARD GAMEPAD Vendor: 045e Product: 028e)"
    index: 0
    mapping: "standard"
    timestamp: 6563054.284999998
    vibrationActuator: null
  */
});

আপনার গেম লুপে গেমপ্যাড

গেমপ্যাড অ্যাক্সেস করার জন্য প্রথমে navigator.getGamepads()-এ কল করতে হয়, যা Gamepadটি আইটেম সহ একটি অ্যারে ফেরত দেয়। Chrome-এ অ্যারেতে সবসময় চারটি আইটেমের নির্দিষ্ট দৈর্ঘ্য থাকে। চারটির কম বা কোনও গেমপ্যাড কানেক্ট করা না থাকলে, আইটেমটি null হতে পারে। অ্যারের সব আইটেম সবসময় চেক করতে ভুলবেন না এবং মনে রাখবেন যে গেমপ্যাড তার স্লট "মনে রাখে" এবং সবসময় প্রথম উপলভ্য স্লটে নাও থাকতে পারে।

// When no gamepads are connected:
navigator.getGamepads();
// (4) [null, null, null, null]

এক বা একাধিক গেমপ্যাড কানেক্ট করা থাকলেও, navigator.getGamepads() এখনও nullটি আইটেম রিপোর্ট করে, আপনাকে প্রতিটি গেমপ্যাডের যেকোনও বোতাম টিপে সেটিকে "ওয়েক" করতে হতে পারে। তারপর আপনি নিচের কোডে দেখানো পদ্ধতিতে গেম লুপে গেমপ্যাড স্ট্যাটাস পোল করতে পারবেন।

const pollGamepads = () => {
  // Always call `navigator.getGamepads()` inside of
  // the game loop, not outside.
  const gamepads = navigator.getGamepads();
  for (const gamepad of gamepads) {
    // Disregard empty slots.
    if (!gamepad) {
      continue;
    }
    // Process the gamepad state.
    console.log(gamepad);
  }
  // Call yourself upon the next animation frame.
  // (Typically this happens every 60 times per second.)
  window.requestAnimationFrame(pollGamepads);
};
// Kick off the initial game loop iteration.
pollGamepads();

ভাইব্রেশন অ্যাকচুয়েটর

vibrationActuator প্রপার্টি GamepadHapticActuator অবজেক্ট রিটার্ন করে, যা মোটর বা অন্যান্য অ্যাকচুয়েটরের কনফিগারেশনের সাথে সম্পর্কিত এবং হ্যাপটিক ফিডব্যাকের উদ্দেশ্যে বল প্রয়োগ করতে পারে। Gamepad.vibrationActuator.playEffect() কল করে হ্যাপটিক এফেক্ট চালানো যেতে পারে। শুধুমাত্র 'dual-rumble' এবং 'trigger-rumble' ধরনের এফেক্টই সঠিক বলে গণ্য হবে।

কাজ করে এমন রাম্বল এফেক্ট

if (gamepad.vibrationActuator.effects.includes('trigger-rumble')) {
  // Trigger rumble supported.
} else if (gamepad.vibrationActuator.effects.includes('dual-rumble')) {
  // Dual rumble supported.
} else {
  // Rumble effects aren't supported.
}

ডুয়াল রাম্বল

ডুয়াল-রাম্বল একটি হ্যাপটিক কনফিগারেশন বর্ণনা করে যার মধ্যে স্ট্যান্ডার্ড গেমপ্যাডের প্রতিটি হ্যান্ডেলে একটি এক্সেন্ট্রিক রোটেটিং মাস ভাইব্রেশন মোটর থাকে। এই কনফিগারেশনে, যেকোনও মোটর পুরো গেমপ্যাড ভাইব্রেট করতে পারে। দুটি ভর অসমান যাতে আরও জটিল হ্যাপটিক এফেক্ট তৈরি করতে প্রতিটির এফেক্ট একত্রিত করা যায়। ডুয়াল-রাম্বল এফেক্ট চারটি প্যারামিটার দ্বারা সংজ্ঞায়িত করা হয়:

  • duration: মিলিসেকেন্ডে ভাইব্রেশন এফেক্টের সময়সীমা সেট করে।
  • startDelay: ভাইব্রেশন শুরু না হওয়া পর্যন্ত বিলম্বের সময়সীমা সেট করে।
  • strongMagnitude এবং weakMagnitude: ভারী এবং হালকা এক্সেন্ট্রিক রোটেটিং মাস মোটরের জন্য ভাইব্রেশন ইনটেনসিটি লেভেল সেট করুন, যা 0.0–1.0 রেঞ্জে নরমালাইজ করা হয়েছে।
// This assumes a `Gamepad` as the value of the `gamepad` variable.
const dualRumble = (gamepad, delay = 0, duration = 100, weak = 1.0, strong = 1.0) => {
  if (!('vibrationActuator' in gamepad)) {
    return;
  }
  gamepad.vibrationActuator.playEffect('dual-rumble', {
    // Start delay in ms.
    startDelay: delay,
    // Duration in ms.
    duration: duration,
    // The magnitude of the weak actuator (between 0 and 1).
    weakMagnitude: weak,
    // The magnitude of the strong actuator (between 0 and 1).
    strongMagnitude: strong,
  });
};

ট্রিগার রাম্বল

ট্রিগার রাম্বল হল হ্যাপটিক ফিডব্যাক এফেক্ট যা দুটি স্বতন্ত্র মোটর দ্বারা তৈরি হয়, যার মধ্যে একটি মোটর গেমপ্যাডের প্রতিটি ট্রিগারে অবস্থিত।

// This assumes a `Gamepad` as the value of the `gamepad` variable.
const triggerRumble = (gamepad, delay = 0, duration = 100, weak = 1.0, strong = 1.0) => {
  if (!('vibrationActuator' in gamepad)) {
    return;
  }
  // Feature detection.
  if (!('effects' in gamepad.vibrationActuator) || !gamepad.vibrationActuator.effects.includes('trigger-rumble')) {
    return;
  }
  gamepad.vibrationActuator.playEffect('trigger-rumble', {
    // Duration in ms.
    duration: duration,
    // The left trigger (between 0 and 1).
    leftTrigger: leftTrigger,
    // The right trigger (between 0 and 1).
    rightTrigger: rightTrigger,
  });
};

অনুমতি সংক্রান্ত নীতির সাথে ইন্টিগ্রেশন

Gamepad API স্পেক "gamepad" স্ট্রিং দ্বারা শনাক্ত করা নীতি-নিয়ন্ত্রিত ফিচার সংজ্ঞায়িত করে। এর ডিফল্ট allowlist হল "self"। কোনও ডকুমেন্টের অনুমতি সংক্রান্ত নীতি নির্ধারণ করে যে সেই ডকুমেন্টের কোনও কন্টেন্ট navigator.getGamepads() অ্যাক্সেস করার অনুমতি পাবে কিনা। কোনও ডকুমেন্টে বন্ধ করা থাকলে, ডকুমেন্টের কোনও কন্টেন্টকে navigator.getGamepads() ব্যবহার করার অনুমতি দেওয়া হবে না, gamepadconnected এবং gamepaddisconnected ইভেন্টও ফায়ার হবে না।

<iframe src="index.html" allow="gamepad"></iframe>

ডেমো

নিচের উদাহরণে একটি গেমপ্যাড টেস্টার ডেমো এম্বেড করা আছে। উৎস কোড GitHub-এ উপলভ্য। USB বা ব্লুটুথ ব্যবহার করে গেমপ্যাড কানেক্ট করে এবং এর যেকোনও বোতাম টিপে বা এর যেকোনও অক্ষ সরিয়ে ডেমোটি ব্যবহার করে দেখুন।

বোনাস: web.dev-এ Chrome ডাইনো গেম খেলুন

আপনি এই সাইটে গেমপ্যাড ব্যবহার করে Chrome dino খেলতে পারবেন। সোর্স কোড GitHub-এ উপলভ্য। trex-runner.js-এ গেমপ্যাড পোলিং প্রয়োগ করার পদ্ধতি দেখুন এবং এটি কীভাবে 'কী' প্রেস করার বিষয়টি এমুলেট করছে তা লক্ষ্য করুন।

Chrome ডাইনো গেমপ্যাড ডেমো যাতে কাজ করে, তার জন্য আমি মূল Chromium প্রোজেক্ট থেকে Chrome ডাইনো গেমটি বের করে নিয়েছি (Arnelle Ballane-এর আগের প্রচেষ্টা আপডেট করে), এটি একটি স্ট্যান্ডঅ্যালোন সাইটে রেখেছি, ডাক করা এবং ভাইব্রেশন এফেক্ট যোগ করে বর্তমান গেমপ্যাড API ইমপ্লিমেন্টেশন আরও বাড়িয়েছি, একটি ফুল স্ক্রিন মোড তৈরি করেছি এবং Mehul Satardekar একটি ডার্ক মোড ইমপ্লিমেন্টেশনে অবদান রেখেছেন। গেমিং উপভোগ করুন!

স্বীকৃতি

এই ডকুমেন্ট François Beaufort এবং Joe Medley পর্যালোচনা করেছেন। Gamepad API স্পেসিফিকেশন এডিট করেছেন Steve Agoston, James Hollyer এবং Matt Reynolds। আগের স্পেক এডিটররা হলেন ব্র্যান্ডন জোনস, স্কট গ্রাহাম এবং টেড মিলজারেক। গেমপ্যাড এক্সটেনশন স্পেসিফিকেশন Brandon Jones এডিট করেছেন।