تعرَّف على كيفية استخدام واجهة برمجة التطبيقات Gamepad API لتحسين ألعاب الويب.
إنّ مفاجأة Chrome المخفية في الصفحة بلا اتصال بالإنترنت هي من أسوأ الأسرار التي تم الاحتفاظ بها في التاريخ ([citation needed]
،
ولكن تم تقديم هذا الادعاء لتأثيره الدرامي). إذا ضغطت على مفتاح المسافة أو نقرت على الديناصور على
الأجهزة الجوّالة، ستصبح الصفحة بلا إنترنت لعبة أركيد قابلة للتشغيل. قد تكون على دراية بأنّه
ليس عليك إيقاف الاتصال بالإنترنت عندما تريد اللعب: في Chrome، يمكنك الانتقال
إلى about://dino
، أو الانتقال إلى about://network-error/-106
إذا كنت من عشاق الألعاب. هل لديك فكرة عن عدد مستخدمي لعبة الديناصور في Chrome؟ يتم تشغيل لعبة الديناصور في Chrome 270 مليون مرة كل شهر.
هناك حقيقة أخرى قد لا تكون على دراية بها، وهي أنّه في وضع "ألعاب الأركيد"، يمكنك تشغيل اللعبة باستخدام جهاز تحكّم. تمت إضافة ميزة استخدام وحدة التحكّم في الألعاب قبل عام تقريبًا، ويعود تاريخ كتابة هذه المقالة إلى وقت تنفيذ commit الذي أجراه 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
. يتيح هذا الخيار نوعَين من تأثيرات الارتجاج:
- التأثير المزدوج للاهتزاز: تأثير الملاحظات اللمسية الناتج عن محرّكَين غريبَي الشكل للكتلة الدوّارة، أحدهما في كل مقبض من مقبضَي ذراع التحكّم.
- التأثير في الزناد: تأثير الملاحظات اللمسية الناتج عن محرّكين مستقلّين، مع محرّك واحد في كل من أدوات التنشيط في لوحة الألعاب.
يعرض المخطّط التالي للنظرة العامة، المأخوذ مباشرةً من المواصفات، تعيين الأزرار والمحاور وترتيبها على جهاز تحكم ألعاب عام.
إشعار عند توصيل جهاز تحكّم في الألعاب
لمعرفة متى يتم توصيل جهاز تحكم ألعاب، انتظِر حدث 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
جهاز،
قد تحتاج إلى "تنشيط" كل جهاز تحكم ألعاب من خلال الضغط على أي من أزراره. يمكنك بعد ذلك فحص حالات gamepad
في حلقة اللعبة كما هو موضّح في الرمز التالي.
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 كلّ من Steve Agoston و James Hollyer و Matt Reynolds. محرّرو المواصفات السابقون هم براندون جونز وسكوت غراهام و تيد ميلشاريك. يُعدّل براندون جونز مواصفات إضافات لوحات الألعاب. الصورة الرئيسية من تصميم "لورا تورنت بويج".