تعرَّف على كيفية استخدام Gamepad API للارتقاء بألعاب الويب إلى مستوى أعلى.
تُعدّ المفاجأة المخفية في صفحة عدم الاتصال بالإنترنت في Chrome من أكثر الأسرار التي تم الكشف عنها في التاريخ ([citation needed]،
ولكن تم تقديم هذا الادعاء لإحداث تأثير درامي). إذا ضغطت على مفتاح المسافة أو نقرت على الديناصور على الأجهزة الجوّالة، ستتحوّل الصفحة غير المتصلة بالإنترنت إلى لعبة أركيد قابلة للتشغيل. قد تكون على علم بأنّه ليس عليك قطع الاتصال بالإنترنت عندما تريد اللعب، ففي Chrome، يمكنك الانتقال إلى about://dino، أو إذا كنت من محبي التكنولوجيا، يمكنك الانتقال إلى about://network-error/-106. هل تعلم أنّه يتم لعب 270 مليون لعبة الديناصور في Chrome كل شهر؟
هناك معلومة أخرى قد تكون أكثر فائدة وقد لا تكون على علم بها، وهي أنّه في وضع "ألعاب الآركيد"، يمكنك لعب اللعبة باستخدام جهاز تحكّم في الألعاب. تمت إضافة ميزة التوافق مع أجهزة التحكّم في الألعاب منذ عام تقريبًا من وقت كتابة هذه المقالة في عملية تنفيذ من قِبل رايلي غرانت. كما ترون، اللعبة، مثل بقية مشروع 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. ويتيح نوعَين من تأثيرات الاهتزاز:
- الاهتزاز المزدوج: هو تأثير التجاوب الحسّي الناتج عن مشغّلَين دوّارَين غير مركزيَّين، أحدهما في كل مقبض من جهاز التحكّم في الألعاب.
- 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. لاحظ كيف في المثال التالي
connected الآن false عندما أقوم بفصل وحدة تحكم Xbox 360.
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 أو بلوتوث والضغط على أي من أزراره أو تحريك أي من محاوره.
مكافأة: العب لعبة الديناصور في Chrome على web.dev
يمكنك لعب لعبة الديناصور في Chrome باستخدام جهاز التحكّم في الألعاب على هذا الموقع الإلكتروني. يتوفّر الرمز المصدر على GitHub.
اطّلِع على طريقة تنفيذ استطلاع جهاز التحكّم في الألعاب في
trex-runner.js
ولاحِظ كيف يحاكي الضغط على المفاتيح.
لكي يعمل الإصدار التجريبي من جهاز التحكّم في لعبة الديناصور في Chrome، استخرجتُ لعبة الديناصور في Chrome من مشروع Chromium الأساسي (مع تعديل محاولة سابقة من قِبل أرنيل بالان)، ووضعتها على موقع إلكتروني مستقل، ووسّعتُ تنفيذ واجهة برمجة التطبيقات الحالية لأجهزة التحكّم في الألعاب من خلال إضافة تأثيرات الاهتزاز والانحناء، وأنشأتُ وضع ملء الشاشة، وساهم ميهول ساتارديكار في تنفيذ الوضع الداكن. نتمنى لك تجربة لعب ممتعة.
روابط مفيدة
الإقرارات
تمت مراجعة هذا المستند من قِبل فرانسوا بوفورت وجو ميدلي. تم تعديل مواصفات Gamepad API من قِبل ستيف أغوستون وجيمس هولير ومات رينولدز. محرّرو المواصفات السابقون هم براندون جونز وسكوت غراهام وتيد ميلزاريك. تم تعديل مواصفات إضافات أجهزة التحكّم في الألعاب من قِبل براندون جونز.