بازی Chrome dino را با گیم پد خود بازی کنید

بیاموزید که چگونه از Gamepad API استفاده کنید تا بازی های وب خود را به سطح بعدی ارتقا دهید.

صفحه آفلاین کروم easter egg یکی از بدترین اسرار در تاریخ است ( [citation needed] ، اما ادعایی برای اثر چشمگیر آن وجود دارد). اگر کلید فاصله را فشار دهید یا در دستگاه های تلفن همراه روی دایناسور ضربه بزنید، صفحه آفلاین به یک بازی آرکید قابل بازی تبدیل می شود. ممکن است بدانید که وقتی می‌خواهید بازی کنید نیازی نیست آفلاین شوید: در Chrome، فقط می‌توانید به about://dino بروید، یا برای افراد حرفه‌ای، به about://network-error/-106 بگردید. about://network-error/-106 . اما آیا می دانستید که هر ماه 270 میلیون بازی Chrome dino بازی می شود ؟

صفحه آفلاین کروم با بازی Chrome dino.
برای بازی کلید فاصله را فشار دهید!

واقعیت دیگری که شاید دانستن آن مفیدتر است و ممکن است از آن آگاه نباشید این است که در حالت آرکید می توانید بازی را با یک گیم پد بازی کنید. پشتیبانی از گیم‌پد تقریباً یک سال پیش در زمان نگارش این مقاله در یک کامیت توسط Reilly Grant اضافه شد. همانطور که می بینید، بازی، درست مانند بقیه پروژه های Chromium، کاملا متن باز است. در این پست می خواهم نحوه استفاده از Gamepad API را به شما نشان دهم.

از Gamepad API استفاده کنید

تشخیص ویژگی و پشتیبانی مرورگر

Gamepad API دارای پشتیبانی جهانی عالی از مرورگر در هر دو دسکتاپ و موبایل است. با استفاده از قطعه زیر می توانید تشخیص دهید که Gamepad API پشتیبانی می شود:

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

چگونه مرورگر یک گیم پد را نشان می دهد

مرورگر گیم‌پدها را به‌عنوان اشیاء Gamepad نشان می‌دهد. یک Gamepad دارای ویژگی های زیر است:

  • id : یک رشته شناسایی برای گیم پد. این رشته مارک یا سبک دستگاه گیم پد متصل را مشخص می کند.
  • displayId : VRDisplay.displayId یک VRDisplay مرتبط (در صورت لزوم).
  • index : نمایه صفحه بازی در ناوبر.
  • connected : نشان می دهد که آیا گیم پد هنوز به سیستم متصل است یا خیر.
  • hand : عددی که مشخص می کند کنترلر در چه دستی نگه داشته می شود یا به احتمال زیاد در آن نگه داشته می شود.
  • timestamp : آخرین باری که داده‌های این گیم‌پد به‌روزرسانی شد.
  • mapping : دکمه و محورهای نگاشت مورد استفاده برای این دستگاه، "standard" یا "xr-standard" .
  • pose : یک شی GamepadPose که اطلاعات پوز مرتبط با کنترلر WebVR را نشان می دهد.
  • axes : آرایه ای از مقادیر برای همه محورهای گیم پد که به صورت خطی در محدوده -1.0 تا 1.0 نرمال شده است.
  • buttons : آرایه ای از حالت های دکمه برای همه دکمه های گیم پد.

توجه داشته باشید که دکمه ها می توانند دیجیتالی (فشرده یا فشار داده نشده) یا آنالوگ (مثلاً 78٪ فشار داده شده) باشند. به همین دلیل است که دکمه ها به عنوان اشیاء GamepadButton با ویژگی های زیر گزارش می شوند:

  • pressed : حالت فشرده شده دکمه (در صورت فشار دادن دکمه true و اگر فشار داده نشود false .
  • touched : حالت لمس دکمه. اگر دکمه قادر به تشخیص لمس باشد، این ویژگی در صورت لمس دکمه true است و در غیر این صورت false .
  • value : برای دکمه هایی که دارای سنسور آنالوگ هستند، این ویژگی نشان دهنده مقدار فشار دادن دکمه است که به صورت خطی در محدوده 0.0 - 1.0 نرمال شده است.
  • hapticActuators : آرایه ای حاوی اشیاء GamepadHapticActuator ، که هر کدام نشان دهنده سخت افزار بازخورد لمسی موجود در کنترلر است.

یکی از موارد اضافی که ممکن است بسته به مرورگر و گیم پدی که دارید با آن مواجه شوید، ویژگی vibrationActuator است. این اجازه می دهد تا برای دو نوع اثر سر و صدا:

  • Dual-Rumble: اثر بازخورد لمسی ایجاد شده توسط دو محرک جرمی چرخان غیرعادی، یکی در هر دسته از گیم پد.
  • Trigger-Rumble: اثر بازخورد لمسی ایجاد شده توسط دو موتور مستقل، با یک موتور واقع در هر یک از ماشه های گیم پد.

نمای کلی شماتیک زیر که مستقیماً از مشخصات گرفته شده است، نگاشت و چینش دکمه ها و محورها را در یک گیم پد عمومی نشان می دهد.

نمای کلی شماتیک نگاشت دکمه ها و محورهای یک گیم پد معمولی.
نمایش بصری یک طرح استاندارد گیم پد ( منبع ).

اعلان هنگام وصل شدن گیم پد

برای اطلاع از اتصال یک گیم پد، به رویداد gamepadconnected که روی شی window فعال می شود گوش دهید. هنگامی که کاربر یک گیم‌پد را متصل می‌کند، که می‌تواند با استفاده از 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 برمی گرداند. آرایه در کروم همیشه دارای طول ثابت چهار مورد است. اگر صفر یا کمتر از چهار گیم پد وصل شده باشد، ممکن است یک مورد 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.
}

غرش دوگانه

Dual-Rumble یک پیکربندی لمسی را با یک موتور ارتعاشی جرمی چرخان غیرعادی در هر دسته از یک گیم پد استاندارد توصیف می کند. در این پیکربندی، هر یک از موتورها قادر به لرزش کل گیم پد است. این دو جرم نابرابر هستند به طوری که اثرات هر یک را می توان برای ایجاد اثرات لمسی پیچیده تر ترکیب کرد. جلوه‌های دوتایی با چهار پارامتر تعریف می‌شوند:

  • 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,
  });
};

ماشه غرش

Trigger rumble اثر بازخورد لمسی است که توسط دو موتور مستقل ایجاد می شود که یک موتور در هر یک از ماشه های گیم پد قرار دارد.

// 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,
  });
};

ادغام با خط مشی مجوزها

مشخصات API Gamepad یک ویژگی کنترل شده توسط خط مشی مشخص شده توسط رشته "gamepad" را تعریف می کند. allowlist پیش فرض آن "self" است. خط مشی مجوزهای یک سند تعیین می کند که آیا محتوای موجود در آن سند مجاز به دسترسی به navigator.getGamepads() است یا خیر. اگر در هر سندی غیرفعال باشد، هیچ محتوایی در سند مجاز به استفاده از navigator.getGamepads() نخواهد بود، و همچنین رویدادهای gamepadconnected و gamepaddisconnected فعال نمی‌شوند.

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

نسخه ی نمایشی

یک نسخه نمایشی آزمایشگر گیم پد در مثال زیر تعبیه شده است. کد منبع در Glitch موجود است. با اتصال یک گیم پد با استفاده از USB یا بلوتوث و فشار دادن هر یک از دکمه های آن یا حرکت دادن محورهای آن، نسخه آزمایشی را امتحان کنید.

امتیاز: Chrome dino را در web.dev بازی کنید

شما می توانید Chrome dino را با گیم پد خود در همین سایت بازی کنید. کد منبع در GitHub موجود است. اجرای نظرسنجی گیم پد را در trex-runner.js بررسی کنید و توجه داشته باشید که چگونه فشار کلید را تقلید می کند.

برای اینکه نسخه نمایشی گیم‌پد دینو Chrome کار کند، من بازی Chrome dino را از پروژه اصلی Chromium حذف کردم (به‌روزرسانی تلاش قبلی توسط Arnelle Ballane )، آن را در یک سایت مستقل قرار دادم، اجرای API گیم‌پد موجود را با اضافه کردن ducking و لرزش گسترش دادم. افکت‌ها، یک حالت تمام صفحه ایجاد کردند، و Mehul Satardekar به اجرای یک حالت تاریک کمک کرد. بازی مبارک!

قدردانی ها

این سند توسط فرانسوا بوفور و جو مدلی بررسی شد. مشخصات API Gamepad توسط Steve Agoston ، James Hollyer و Matt Reynolds ویرایش شده است. ویراستاران قبلی مشخصات براندون جونز ، اسکات گراهام و تد میلزارک هستند. مشخصات برنامه های افزودنی گیم پد توسط برندون جونز ویرایش شده است. تصویر قهرمان توسط لورا تورنت پویگ.