تعرَّف على كيفية استخدام واجهة برمجة التطبيقات Gamepad API للارتقاء بألعاب الويب إلى المستوى التالي.
مفاجأة مخفية في صفحة Chrome بلا اتصال بالإنترنت هي أحد أسوأ الأسرار التي تم الاحتفاظ بها في التاريخ ([citation needed]
، إلا أنّ المطالبة تكمن للتأثير المذهل). عند الضغط على مفتاح المسافة أو النقر على الديناصور على الأجهزة الجوّالة، ستصبح الصفحة المتوفّرة بلا إنترنت لعبة كلاسيكية قابلة للتشغيل. قد تكون على دراية
بأنّك لست مضطرًا إلى قطع الاتصال بالإنترنت عند شعورك بالرغبة في اللعب: في Chrome، يمكنك الانتقال إلى about://dino
أو الانتقال إلى about://network-error/-106
إذا كنت مهووسًا باللعبة. لكن هل تعلم أنّ هناك
270 مليون لعبة ديناصور يتم لعبها في Chrome كل شهر؟
![صفحة Chrome بلا اتصال بالإنترنت التي تحتوي على لعبة الديناصور على Chrome](https://web.dev/static/articles/gamepad/image/chromes-offline-page-th-3d966d4a2f411.png?authuser=6&hl=ar)
هناك حقيقة أخرى من المفيد جدًا معرفتها والتي قد لا تكون على دراية بها، وهي أنّه في وضع الألعاب الكلاسيكية، يمكنك تشغيل اللعبة بلوحة الألعاب. تمت إضافة الدعم إلى وحدة تحكّم الألعاب قبل عام واحد تقريبًا وذلك في وقت كتابة هذا الالتزام من قِبل رايلي غرانت. كما ترى، اللعبة، تمامًا مثل بقية مشروع Chromium، مفتوحة المصدر بالكامل. في هذه المشاركة، أود أن أوضح لك كيفية استخدام واجهة برمجة تطبيقات Gamepad.
استخدام واجهة برمجة تطبيقات Gamepad
رصد الميزات ودعم المتصفِّح
توفّر واجهة برمجة التطبيقات 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
. تسمح هذه الميزة بتأثيرات مدمَجة من نوعين:
- التحكّم المزدوج: تأثير التجاوب الحسّي الذي يصدره مشغّلان لكتلان دوّاران فريدان، أحدهما في كل قبضة من لوحة الألعاب.
- تحفيز الاهتزاز: هو تأثير التجاوب الحسّي الذي يصدره محرّكان مستقلان، مع وضع محرك واحد في كل مُشغِّل في لوحة الألعاب.
توضح النظرة العامة التخطيطية التالية، المأخوذة مباشرةً من المواصفات، عملية التخطيط وترتيب الأزرار والمحاور في لوحة ألعاب عامة.
إشعار عند اتصال لوحة ألعاب
لمعرفة الوقت الذي تكون فيه لوحة الألعاب متصلة، يُرجى رصد حدث 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>
عرض توضيحي
يتم تضمين عرض توضيحي لمختبِري لوحة الألعاب في المثال التالي. رمز المصدر متوفّر على Glitch. جرّب العرض التوضيحي عن طريق توصيل وحدة تحكم في الألعاب باستخدام USB أو بلوتوث والضغط على أي من أزراره أو تحريك أي من محوره.
ميزة إضافية: تشغيل لعبة الديناصور في Chrome على web.dev
يمكنك لعب لعبة الديناصور في Chrome باستخدام جهاز التحكّم في الألعاب على هذا الموقع الإلكتروني تمامًا. يتوفّر رمز المصدر على GitHub.
يمكنك الاطّلاع على طريقة تنفيذ الاستطلاعات في لوحة الألعاب في
trex-runner.js
وملاحظة طريقة محاكاة الضغطات على المفاتيح.
لكي يعمل العرض التوضيحي للعبة الديناصور في Chrome، تم حذف لعبة الديناصور في Chrome من المشروع الأساسي في Chromium (مع تحديث المجهود السابق الذي بذله "أرنيل بالان")، ووضعته في موقع إلكتروني مستقل، ووسّعنا عملية تنفيذ واجهة برمجة التطبيقات الحالية في لوحة الألعاب من خلال إضافة تأثيرات الالتلاعب والاهتزاز، وإنشاء وضع ملء الشاشة وإنشاء وضع تنفيذ بملء الشاشة، ومساهم في الوضع الداكن. نتمنّى لك تجربة ممتعة في اللعب!
روابط مفيدة
- مواصفات واجهة برمجة التطبيقات Gamepad API
- مواصفات إضافات واجهة برمجة التطبيقات Gamepad API
- مستودع جيت هب
شكر وتقدير
تمّت مراجعة هذا المستند من قِبل فرانسوا بوفورت وجو ميدلي. يعدّل كل من ستيف أغوستون وجيمس هوليير ومات رينولدز مواصفات واجهة برمجة تطبيقات Gamepad. محرّرو المواصفات السابقون هم براندون جونز وسكوت غراهام وتيد ميلزاريك. يعدّل براندون جونز مواصفات "إضافات لوحة الألعاب". الصورة الرئيسية من تصوير "لورا تورنت بويغ".