إنشاء دحرجة

Roll It هي إحدى تجارب Chrome التي تعيد تصميم لعبة كلاسيكية على المتصفّح باستخدام متصفّح على الهاتف والكمبيوتر فقط. يتيح لك المتصفح على هاتفك التصويب نحو الكرة وتدويرها بتمريرة سريعة من معصمك، بينما يعرض المتصفح على الكمبيوتر رسومات في الوقت الفعلي لمزهق "Roll It" باستخدام WebGL ولوحة الرسم. يتواصل الجهازان عبر Websockets. ليس هناك أي تطبيقات. لم يتم تنزيل أي محتوى. ما مِن رموز مميّزة. كل ما تحتاجه هو متصفح حديث.

وبتوجيه من مختبر Google الإبداعي، طوّرت شركة Legwork تجربة المستخدم والواجهات وبيئة اللعبة، ثم تعاونت مع شريك التطوير، Mode Set، لتطوير Roll It. على مدار مدة المشروع كان هناك عدد من التحديات الفريدة. تستعرض هذه المقالة بعض الأساليب التي استخدمناها، والحيل التي اكتشفناها، والدروس التي تعلّمناها أثناء تحقيق النتائج المرجوّة.

سير عمل ثلاثي الأبعاد

كانت إحدى الصعوبات التي واجهتنا في البداية هي اكتشاف أفضل طريقة لجلب النماذج ثلاثية الأبعاد من برامجنا إلى تنسيق ملف متوافق مع الويب. بعد إنشاء مواد العرض في Cinema 4D، تم تبسيط النماذج وتحويلها إلى شبكات مضلّعة منخفضة. تم تخصيص علامات تحديد مضلع معينة لكل شبكة للتمييز بين أجزاء الكائن للتلوين والزخرفة. وتمكّنا بعد ذلك من تصدير الملفات بتنسيق Collada 1.5 (dae.) واستيرادها إلى برنامج Blender، وهو برنامج مفتوح المصدر ثلاثي الأبعاد، لإنشاء ملفات متوافقة لبرنامج three.js. بعد التأكّد من استيراد النماذج بشكل صحيح، صدّرنا الشبكة المتداخلة كملف JSON وتم تطبيق الإضاءة باستخدام رموز. في ما يلي نظرة أكثر تفصيلاً على الخطوات التي اتخذناها:

ضع نموذجًا للكائن داخل C4D. تأكد من أن شبكات الشبكة المتداخلة باتجاه الخارج.
يجب إعداد نموذج للكائن ضمن تقنية C4D. تأكد من أن شبكات الشبكة المتداخلة باتجاه الخارج.
باستخدام أداة تحديد المضلّع، أنشئ علامات تحديد للمناطق المحددة التي تريد زخرفةها. قم بتطبيق المواد على كل علامة من علامات الاختيار.
باستخدام أداة اختيار المضلّع، يمكنك إنشاء علامات اختيار للمناطق المحدّدة التي تريد زخرفةها. قم بتطبيق المواد على كل علامة من علامات الاختيار.
صدِّر الشبكة المتداخلة كملف COLLADA 1.5 .dae.
يمكنك تصدير الشبكة المتداخلة كملف COLLADA 1.5 .dae.
تأكد من تحديد "تصدير الهندسة ثنائية الأبعاد". عادةً ما يكون تصدير المثلثات مدعومًا على نطاق أوسع عبر البيئات الثلاثية الأبعاد على جانب الرمز، ولكن له الجانب السلبي الذي يتمثل في مضاعفة عدد المضلّعات. كلما زاد عدد المضلّعات، زادت ضرائب النموذج على معالج الكمبيوتر. لذا لا تضع علامة في المربّع إذا لاحظت بطئًا في الأداء.
تأكّد من وضع علامة في المربّع بجانب "التصدير الثنائي الأبعاد". عادةً ما يكون تصدير المثلثات مدعومًا على نطاق أوسع عبر البيئات الثلاثية الأبعاد على جانب الرمز، ولكن له الجانب السلبي الذي يتمثل في مضاعفة عدد المضلّعات. كلما زاد عدد المضلّعات، زادت ضرائب النموذج على معالج الكمبيوتر. لذا، لا تضع علامة في المربّع إذا لاحظت بطئًا في الأداء.
استورد ملف Collada إلى Blender.
يجب استيراد ملف Collada إلى Blender.
بعد استيرادها إلى الخلاط، سترى أنّ المواد وعلامات الاختيار قد تم نقلها أيضًا.
بعد استيرادها إلى الخلاط، سترى أنّ المواد وعلامات الاختيار قد تم نقلها أيضًا.
حدد الكائن، واضبط مواد الجسم على ما تفضّله.
اختَر العنصر الذي تريد استخدامه وضبط مواده على ما تفضّله.
تصدير الملف كملف three.js
تصدير الملف كملف three.js للتوافق مع webGL.

كتابة التعليمات البرمجية

تم تطوير Roll It باستخدام مكتبات مفتوحة المصدر ويتم تشغيلها محليًا في المتصفحات الحديثة. باستخدام تقنيات مثل WebGL وWebSockets، يختص الويب بتجارب الوسائط المتعددة واللعب بجودة وحدة التحكم. لقد حققنا تقدمًا كبيرًا بفضل سهولة إنشاء هذه التجارب للمطوّرين بفضل توفّر أدوات أكثر حداثة لتطوير HTML.

بيئة التطوير

تمت كتابة معظم التعليمات البرمجية لـ Roll It باستخدام CoffeeScript، وهي لغة بسيطة وموجزة يتم تحويلها إلى لغة JavaScript ذات تنسيق جيد ومتوافق. تتألق CoffeeScript في تطوير OOP من خلال نموذج التوريث الرائع ومعالجة النطاق الأكثر وضوحًا. تمت كتابة CSS باستخدام إطار عمل SASS، الذي يوفر للمطوّر عددًا من الأدوات الرائعة لتحسين وإدارة أوراق الأنماط في المشروع. تستغرق إضافة هذه الأنظمة إلى عملية التصميم بعض الوقت قليلاً، ولكن العائد يستحق ذلك بالتأكيد، خاصة بالنسبة لمشروع أكبر مثل Roll It. قمنا بإعداد خادم Ruby on Rails لتجميع أصولنا تلقائيًا أثناء التطوير، لذلك أصبحت جميع خطوات التجميع هذه شفافة.

فضلاً عن إنشاء بيئة ترميز سلسة ومريحة، عملنا على تحسين مواد العرض يدويًا لتقليل الطلبات بهدف تحميل الموقع الإلكتروني بشكل أسرع. شغّلنا كل صورة من خلال برنامجَي ضغط، وهما ImageOptim وImageAlpha. يحسّن كل برنامج الصور بطريقته الخاصة، مع فقدان البيانات وفقدانها، على التوالي. وباستخدام مجموعة الإعدادات الصحيحة، يمكنهم خفض حجم ملف الصورة بشكل كبير. لا يؤدي ذلك إلى توفير معدّل نقل البيانات عند تحميل الصور الخارجية فحسب، بل يؤدي أيضًا إلى تحسينه بعد تحسينه، سيتحول صورك إلى سلاسل بترميز base64 أصغر بكثير للتضمين المضمّن في HTML وCSS وJavaScript. في ما يتعلّق بترميز base64، ضمّننا أيضًا ملفات خطوط Open Sans WOFF وSVG مباشرةً في CSS باستخدام هذا الأسلوب، ما أدّى إلى انخفاض إجمالي عدد الطلبات.

المشهد الثلاثي الأبعاد الذي تدعم الفيزياء

THREE.js هي مكتبة JavaScript ثلاثية الأبعاد واسعة الانتشار على الويب. فهو يقدم ملخصًا للرياضيات ثلاثية الأبعاد منخفضة المستوى وتحسينات WebGL المستندة إلى الأجهزة والتي تمكن البشر العاديين من إنشاء مشاهد ثلاثية الأبعاد تفاعلية ذات إضاءة جيدة وجميلة بسهولة بدون الحاجة إلى كتابة أدوات تظليل مخصصة أو إجراء عمليات تحويل المصفوفة يدويًا. Physijs هو برنامج تضمين خاص بـ THREE.js لمكتبة فيزياء شائعة بلغة C++ تمت ترجمتها إلى JavaScript. ولقد استفدنا من هذه المكتبة لمحاكاة تدحرج الكرة والقفز والارتداد نحو وجهتها في العرض الثلاثي الأبعاد.

منذ البداية، أردنا أن نجعل تجربة رمي الكرة تبدو واقعية، ولكن أيضًا نريد التأكّد من أنّ مقتنيات اللعبة تبدو حقيقية. تطلب هذا الأمر تكرارات عديدة لتعديل الجاذبية العامة لمشهد الفيزياس، وسرعة الكرة أثناء تحركها من رمية اللاعب، ومنحدر قفز الممر، وخصائص الاحتكاك والتعويض (الارتداد) للكرة ومواد الحارة. من خلال مزيج من الجاذبية والسرعة العالية، أصبحت اللعبة أكثر واقعية.

التجانس

ينبغي أن تستفيد معظم المجموعات الحديثة من المتصفحات وبطاقات الفيديو من التشويش على الأجهزة الأصلية في بيئة WebGL، إلا أن بعضها لن يعمل بشكل جيد. في حال لم يعمل تنعيم الحواف بشكل طبيعي، ستكون أي حواف صلبة ومتباينة في المشهد THREE.js مسنّنة وقبيحة (بالنسبة إلى أعيننا المميزة، على الأقل).

لحسن الحظ أن هناك حلًا: من خلال مقتطف من التعليمة البرمجية، يمكننا اكتشاف ما إذا كان النظام الأساسي يدعم في الأصل مكافحة التشويش أم لا. إذا كان الأمر كذلك، فحينئذٍ يمكننا المضي قدمًا. وإذا لم يكن الأمر كذلك، فهناك سلسلة من مظلات ما بعد المعالجة التي تأتي مع THREE.js يمكن أن تساعدنا في ذلك. وبالتحديد، فلتر FXAA لمكافحة التشويش. من خلال إعادة رسم المشهد المعروض كل إطار باستخدام أداة التظليل هذه، يصبح لدينا بشكل عام مظهر أكثر سلاسة لخطوطنا وحوافنا. انظر العرض التوضيحي أدناه:

// Check for native platform antialias support via the THREE renderer
// from: http://codeflow.org/entries/2013/feb/22/how-to-write-portable-webgl/#antialiasing
var nativeAntialiasSupport = (renderer.context.getParameter(renderer.context.SAMPLES) == 0) ? false : true;

عناصر التحكّم في الألعاب المستنِدة إلى مقياس التسارع

تعتمد اللعبة بشكل كبير على إيماءة دحرجة الكرة التي ينفّذها اللاعب باستخدام الهاتف. كان بإمكان الأجهزة المحمولة الوصول إلى مقياس التسارع في المتصفح لبعض الوقت الآن، ولكن كمجال، بدأنا للتو في استكشاف التعرف على الإيماءات القائم على الحركة على الويب. إنّ البيانات التي يوفّرها مقياس تسارع الهاتف محدودة إلى حدٍ ما، ولكن بقليل من الإبداع، يمكننا ابتكار بعض التجارب الجديدة الرائعة.

يتم رصد إيماءة "التشغيل " الرئيسية لـ"اللف" بتتبُّع أحدث 10 تحديثات لمقياس التسارع واردة من حدث deviceorientation على النافذة. من خلال طرح قيمة الإمالة السابقة من قيمة الإمالة الحالية، يتم تخزين دلتا الزاوية بين الأحداث. ثم، من خلال جمع آخر دلتا للزوايا العشرة الأخيرة، يمكننا اكتشاف الدوران المستمر أثناء تحرك الهاتف في الفضاء. عندما يتجاوز الهاتف حدّ التغيُّر في الزاوية الكاسحة، يتم تشغيل لفة. ومن خلال إيجاد أكبر دلتا ميل واحد في هذا التدفق، يمكننا تقدير سرعة الكرة. في ميزة "اللف"، تتم تسوية هذه السرعة باستخدام الطوابع الزمنية التي نرفقها مع كل تحديث لمقياس التسارع. يساعد ذلك في الحفاظ على سرعة متباينة في بث تحديثات مقياس التسارع في المتصفِّح على الأجهزة المختلفة.

اتصال WebSockets

بمجرد أن يلف اللاعب الكرة بهاتفه، يتم إرسال رسالة من الهاتف إلى الكمبيوتر المحمول تطلب منه إطلاق الكرة. يتم إرسال رسالة "التشغيل" هذه عبر كائن بيانات JSON من خلال اتصال WebSocket بين الجهازين. بيانات JSON صغيرة وتتكوّن بشكل أساسي من نوع الرسالة وسرعة العرض واتجاه الهدف.

{
  "type": "device:ball-thrown",
  "speed": 0.5,
  "aim": 0.1
}

تتم جميع الاتصالات بين الكمبيوتر المحمول والهاتف من خلال رسائل JSON صغيرة مثل هذه. ويتم إرسال رسالة WebSocket بين الأجهزة في كل مرة تعدِّل فيها اللعبة حالتها على سطح المكتب، أو يميل المستخدم أو ينقر على زر في الهاتف. وليظل هذا الاتصال بسيطًا وسهل الإدارة، يتم بث رسائل WebSockets باستخدام نقطة خروج واحدة من أي متصفح. وعلى النقيض، هناك نقطة دخول واحدة على متصفح الاستقبال، مع وجود كائن WebSocket واحد يعالج جميع الرسائل الواردة والصادرة من كلا الطرفين. عند تلقّي رسالة WebSocket، تتم إعادة بث بيانات JSON داخل تطبيق JavaScript باستخدام طريقة trigger() في jQuery. في هذه المرحلة، تعمل البيانات الواردة تمامًا مثل أي حدث DOM مخصص آخر، ويمكن الحصول عليها ومعالجتها بواسطة أي عنصر آخر في التطبيق.

var websocket = new WebSocket(serverIPAddress);

// rebroadcast incoming WebSocket messages with a global event via jQuery
websocket.onmessage = function(e) {
  if (e.data) {
    var obj = JSON.parse(e.data);
    $(document).trigger(data.type, obj);
  }
};

// broadcast outgoing WebSocket messages by passing in a native .js object
var broadcast = function(obj) {
  websocket.send(JSON.stringify(obj));
};

يتم إنشاء خوادم Roll It's WebSocket بشكل آني عند مزامنة جهازين مع رمز لعبة. تم إنشاء الواجهة الخلفية لبرنامج Roll It باستخدام النظام الأساسي Google Compute Engine وApp Engine باستخدام Go.

إمالة شاشات القائمة

بخلاف رسائل WebSocket التي تستند إلى الحدث والمستخدمة أثناء اللعب، يمكن التحكم في القوائم في Roll It من خلال إمالة الهاتف والنقر على أحد الأزرار لتأكيد الاختيار. وهذا يتطلب تدفقًا أكثر اتساقًا من بيانات الإمالة التي يتم نقلها من الهاتف إلى الكمبيوتر المحمول. لتقليل معدل نقل البيانات وتجنب إرسال تحديثات غير ضرورية، لا يتم إرسال هذه الرسائل إلا إذا تغيرت درجة إمالة الجهاز بأكثر من درجتين. فليس هناك جدوى من إرسال تدفق من بيانات الإمالة إذا كان الهاتف مستقيمًا على طاولة! ويتم أيضًا تقييد معدل الإرسال - لا يتم إرسال أكثر من 15 رسالة WebSockets في الثانية في Roll It، حتى إذا كان الجهاز مائلاً بشكل نشط.

بعد اختيار قيم الإمالة على الكمبيوتر، يتم إدخالها بمرور الوقت باستخدام requestAnimationFrame للحفاظ على سلاسة النقل. والنتيجة النهائية هي قائمة دوّارة وكرة تتحرك للمساعدة في الإشارة إلى اختيار المستخدم. وأثناء إرسال الهاتف لبيانات الإمالة، يتم تعديل عناصر DOM هذه في الوقت الفعلي من خلال إعادة احتساب عملية تحويل CSS داخل حلقة requestAnimationFrame. تدور حاوية القائمة ببساطة، ولكن يبدو أن الكرة تتحرك على طول الأرض. ولتحقيق هذا التأثير، يتم تنفيذ بعض عمليات حساب المثلثات الأساسية لربط الكرات ذات الإحداثي السيني (x) بدورانها. المعادلة البسيطة هي: الدوران = س / (القطر * باي)

الخاتمة

الدوران هو علامة على الوقت. بين المشاريع المفتوحة المصدر التي تدعم تطويره، وقوة معالجة الأجهزة على مكاتبنا وفي جيوبنا، وحالة الويب كمنصة، يمثل الاتصال بشبكة الويب المفتوحة وقتًا مثيرًا وتحوّلاً حقيقيًا. قبل بضع سنوات فقط، كان الكثير من هذه التكنولوجيات موجودًا فقط في أنظمة مملوكة لها، وغير متاحة للاستخدام والتوزيع مجانًا. وفي الوقت الحالي، يمكن تحقيق التجارب المعقّدة بجهد أقل وأقل خيالًا وخيالاً، وذلك من خلال ابتكار أجزاء جديدة من اللغز ومشاركتها كل يوم. ماذا تنتظر؟ أنشئ شيئًا رائعًا وشاركه مع العالم!

شعار "التدوير"