अपने गेमपैड से Chrome Dino गेम खेलें

अपने वेब गेम को बेहतर बनाने के लिए, Gamepad API का इस्तेमाल करने का तरीका जानें.

Chrome का ऑफ़लाइन पेज, ईस्टर एग, इतिहास के सबसे रोमांचक रहस्यों में से एक है ([citation needed], लेकिन इसमें नाटकीय प्रभाव डालने के लिए दावा किया गया है). space बटन दबाने या मोबाइल डिवाइसों पर, डायनासॉर पर टैप करने पर, ऑफ़लाइन पेज, खेलने लायक आर्केड गेम बन जाता है. आप शायद इस बात से सहमत होंगे कि जब आपको गेम खेलने का मन हो, तो असल में आपको ऑफ़लाइन जाने की ज़रूरत नहीं होती: Chrome में, बस about://dino तक नेविगेट किया जा सकता है या कुछ खास लोगों के लिए about://network-error/-106 को ब्राउज़ किया जा सकता है. क्या आपको पता है कि हर महीने 27 करोड़ Chrome Dino गेम खेले जाते हैं?

Chrome Dino गेम के साथ Chrome का ऑफ़लाइन पेज.
खेलने के लिए, स्पेस बटन दबाएं!

एक और तथ्य जिसके बारे में जानना काफ़ी मददगार है और जिसके बारे में आपको पता नहीं है वह यह है कि आर्केड मोड में गेमपैड से गेम खेला जा सकता है. गेमपैड की सुविधा करीब एक साल पहले रेली ग्रांट ने commit में इसे लिखने के समय जोड़ी थी. जैसा कि आपको दिख रहा है, यह गेम, बाकी 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: इस सूची से पता चलता है कि कंट्रोलर किस हाथ में है या उसे किस हाथ में रखा जा सकता है.
  • timestamp: इस गेमपैड के लिए पिछली बार डेटा अपडेट किए जाने का समय.
  • mapping: इस डिवाइस के लिए, बटन और ऐक्सिस को मैप किया जा रहा है, चाहे "standard" या "xr-standard".
  • pose: GamepadPose ऑब्जेक्ट, जो WebVR कंट्रोलर से जुड़ी पोज़ की जानकारी दिखाता है.
  • axes: गेमपैड के सभी ऐक्सिस के लिए वैल्यू का कलेक्शन, जिसे -1.01.0 की रेंज के लिए लीनियर तौर पर सामान्य रूप से दिखाया जाता है.
  • buttons: गेमपैड के सभी बटन के लिए बटन स्टेटस का कलेक्शन.

ध्यान दें कि बटन डिजिटल (दबाए गए या दबाए नहीं गए) या ऐनालॉग (उदाहरण के लिए, 78% दबाया गया) हो सकते हैं. इसी वजह से, बटन को यहां दिए गए एट्रिब्यूट के साथ GamepadButton ऑब्जेक्ट के तौर पर रिपोर्ट किया जाता है:

  • pressed: बटन को दबाकर रखने की स्थिति (अगर बटन दबाया गया है, तो true. और अगर बटन नहीं दबाया गया है, तो false.
  • touched: बटन को छुए जाने की स्थिति. अगर बटन को छूने से पता चलता है, तो बटन को छूने पर यह प्रॉपर्टी true है और अगर ऐसा नहीं है, तो false है.
  • value: एनालॉग सेंसर वाले बटन के लिए, यह प्रॉपर्टी उस मात्रा को दिखाती है जिससे बटन को दबाया गया था. इस मात्रा को लीनियर तौर पर 0.01.0 की रेंज में सामान्य तरीके से दिखाया जाता है.
  • hapticActuators: एक कलेक्शन, जिसमें GamepadHapticActuator ऑब्जेक्ट मौजूद हैं. हर ऑब्जेक्ट, कंट्रोलर पर उपलब्ध हैप्टिक फ़ीडबैक हार्डवेयर के बारे में बताता है.

आपके ब्राउज़र और गेमपैड के आधार पर आपको vibrationActuator प्रॉपर्टी के साथ दूसरी चीज़ों का भी सामना करना पड़ सकता है. यह दो तरह के रंबल इफ़ेक्ट की अनुमति देता है:

  • ड्यूअल-रंबल: यह हैप्टिक फ़ीडबैक इफ़ेक्ट है, जो गेमपैड की हर ग्रिप में एक के बाद एक रोटेटिंग मास ऐक्ट्युएटर का बना है.
  • ट्रिगर-रंबल: यह हैप्टिक फ़ीडबैक इफ़ेक्ट है, जो दो इंडिपेंडेंट मोटर से जनरेट होता है. इसमें, गेमपैड के हर ट्रिगर में एक मोटर होती है.

खास जानकारी को ध्यान में रखकर, नीचे दी गई स्कीमा की खास जानकारी में, सामान्य गेमपैड पर मैपिंग और बटन और ऐक्सिस को दिखाया गया है.

किसी सामान्य गेमपैड के बटन और ऐक्सिस की मैपिंग की स्कीमा के बारे में खास जानकारी.
स्टैंडर्ड गेमपैड लेआउट का विज़ुअल प्रज़ेंटेशन (सोर्स).

गेमपैड के कनेक्ट होने पर मिलने वाली सूचना

गेमपैड कनेक्ट होने पर, यह जानने के लिए window ऑब्जेक्ट पर ट्रिगर होने वाला gamepadconnected इवेंट सुनें. जब उपयोगकर्ता कोई गेमपैड कनेक्ट करता है, जो यूएसबी या ब्लूटूथ का इस्तेमाल करके कनेक्ट किया जा सकता है, तो 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' है. ड्यूअल-रंबल से हैप्टिक कॉन्फ़िगरेशन की जानकारी मिलती है. इसमें स्टैंडर्ड गेमपैड के हर हैंडल में, एक खास घूमने वाला वाइब्रेशन मोटर होता है. इस कॉन्फ़िगरेशन में, दोनों में से कोई भी मोटर, पूरे गेमपैड को वाइब्रेशन कर सकती है. दोनों द्रव्यमान बराबर नहीं हैं, इसलिए ज़्यादा जटिल हैप्टिक इफ़ेक्ट तैयार करने के लिए, दोनों के असर को मिलाया जा सकता है. ड्यूअल-रंबल इफ़ेक्ट को चार पैरामीटर की मदद से तय किया जाता है:

  • duration: वाइब्रेशन इफ़ेक्ट की अवधि को मिलीसेकंड में सेट करता है.
  • startDelay: वाइब्रेशन शुरू होने तक देरी को सेट करता है.
  • strongMagnitude और weakMagnitude: ज़्यादा और हल्के, घूम रहे मास मोटर के लिए वाइब्रेशन की इंटेंसिटी के लेवल सेट करें. इन्हें 0.01.0 की रेंज में सामान्य रूप से सेट किया गया है.

रंबल इफ़ेक्ट के साथ काम करने की सुविधा

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.
}

ड्यूअल रंबल

// 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>

डेमो

नीचे दिए गए उदाहरण में, गेमपैड की जांच करने वाले टूल का डेमो एम्बेड किया गया है. सोर्स कोड Glitch पर उपलब्ध है. डेमो को आज़माने के लिए, यूएसबी या ब्लूटूथ का इस्तेमाल करके गेमपैड को कनेक्ट करें और उसके किसी भी बटन को दबाएं या उसके किसी भी ऐक्सिस को घुमाएं.

बोनस: web.dev पर Chrome Dino खेलें

इस साइट पर, अपने गेमपैड से Chrome Dino खेला जा सकता है. सोर्स कोड GitHub पर उपलब्ध है. trex-runner.js में जाकर, गेमपैड पोलिंग लागू करने की प्रोसेस देखें और ध्यान दें कि यह बटन दबाए जाने की प्रोसेस को कैसे एम्युलेट कर रहा है.

Chrome Dino गेमपैड डेमो का इस्तेमाल करने के लिए, मैंने मुख्य Chromium प्रोजेक्ट से Chrome Dino गेम को हटाया और इसे अरनेल बैलेन की शुरुआत में अपडेट दिया. साथ ही, इसे स्टैंडअलोन साइट पर रखा. साथ ही, डकिंग और वाइब्रेशन इफ़ेक्ट जोड़कर मौजूदा गेमपैड एपीआई को लागू करने की प्रोसेस को बढ़ाया, फ़ुल स्क्रीन मोड बनाया, और मेहुल सतारदेकर ने डार्क मोड लागू किया. गेमिंग का आनंद लें!

स्वीकार हैं

इस दस्तावेज़ की समीक्षा फ़्रैंसुआ ब्यूफ़ोर्ट और जो मेडली ने की है. Gamepad API की खास जानकारी में स्टीव एगोस्टन, जेम्स हॉलियर, और Matt Reynolds ने बदलाव किए हैं. इस तकनीकी विशेषज्ञ में, ब्रैंडन जोंस, स्कॉट ग्रैहम, और टेड मिल्ज़ारेक शामिल हैं. गेमपैड एक्सटेंशन की खास जानकारी में ब्रैंडन जोन्स ने बदलाव किया है. हीरो इमेज, लॉरा टॉरेंट पुइग की.