
في
المقالة السابقة ، حاولنا إنشاء مشهد أساسي في A-Frame لتجربة المفاهيم الأساسية للإطار في الممارسة العملية. في هذه المقالة ، أود أن أشارك تجربتي في إنشاء لعبة على A-Frame - Recycle! VR مستودع المشروع متاح على
الرابط التالي .
إعادة التدوير!
جاءت فكرة إنشاء لعبة فورًا تقريبًا بمجرد أن علمت عن Web VR. على الرغم من أنه بشكل عام ، أعتقد أن الألعاب على الويب في أي حال ستكون أدنى من المشاريع الجيدة حتى بالنسبة للأجهزة المحمولة ، ناهيك عن أجهزة الكمبيوتر الشخصية وأجهزة التحكم. ولكن يبدو لي أن اللعبة هي أصعب اختبار. بدأت أفكر في ما يمكنني فعله بالضبط. شاهدت مشاريع أخرى ، وقد أدهشني على الفور فرصة أخذ شيء باستخدام وحدة التحكم. ونظرًا لأنني متصلاً بمؤسسة تعمل في مجموعة منفصلة من البيانات المهملة لبعض الوقت ، فإن الإجابة جاءت بحد ذاتها. إعادة التدوير. نأخذ القمامة ورميها في سلة المهملات. ما يمكن أن يكون أسهل. ولكن تبين أن كل شيء ليس بهذه البساطة ، وهذا في الواقع سوف تتم مناقشته أكثر.
اختيار الإطار
في وقت بدء العمل في اللعبة ، لم أكن أعرف سوى إطارين أكثر أو أقل خطورة: React 360 ، A-Frame. من الواضح ، كان الإطار A الأكثر ملاءمة لإنشاء اللعبة. نعم ، الآن أعلم أنه لا يزال هناك محرك ألعاب PlayCanvas يدعم أيضًا VR ، لكنه فات الأوان. علاوة على ذلك ، اتضح أن الإطار A ليس سيئًا أيضًا في إنشاء الألعاب.
من أين تبدأ؟
بدأت بدراسة أمثلة الألعاب الرسمية من مطوري A-Frame. صالح هذه ليست كافية. انفجار ، رسام ، متحف ، سوبر كرافت والآن Gunters of Oasis. من بين جميع المشاريع المقدمة ، أحببت A-Blast أكثر - مطلق النار الذي يجب أن تقاتل فيه مع أفضل المخلوقات في الكون. لذلك ، أردت أن أغتنم هذه اللعبة كقالب لي. لكنها لم تنجح. والسبب في ذلك هو بنية اللعبة. يبدو لي أنها كانت تشوش للغاية وليس التفكير بها. ربما ليس هناك ما هو أكثر من ذلك ، لكنني أردت القيام بشيء أكثر ملاءمة وأسهل للفهم.
هيكل
تمثل بنية
A-Blast نقطة دخول واحدة فقط - ملف index.html ، الذي يحتوي على مشهد واحد مع جميع الأصول ، والكيانات الأساسية للعبة ، وعناصر التحكم ، وكل شيء بشكل عام.

كما ترون في لقطة الشاشة ، بالإضافة إلى المكونات والأنظمة اللازمة (يستخدم A-Frame نمط نظام مكونات العنصر) ، هناك أيضًا عيارات نارية وأعداء - نفس الأنظمة بشكل أساسي ، ولكن يوجد لسبب ما غلاف خاص بهم. عموما أقول أن هذا الرمز ليس من السهل فهمه. لذلك قررت التفكير في كيفية تنظيم هذا الرمز. الفكرة الأولى هي تقسيم المشهد إلى أجزائه المكونة. لماذا يكون جهاز التوجيه والقوالب مفيدًا ، مما يجعل هذا الجزء أو ذاك من المشهد. بعد البحث عن الأول والثاني (لا ، ليس خمس دقائق) ، لم أجد أي شيء. على الرغم من أنني من مؤيدي القاعدة ، لا تكتب الدراجات ، لكن هذه المرة كان علي أن أكتب قراري. رغم أنني ، في مكان ما خلال 2-3 أسابيع ، صادفت قوالب من كيفن نغو. ولكن بعد فوات الأوان.
جهاز التوجيه والأنماط

وهكذا ، تدخل
قوالب إطار التوجيه إلى المشهد. ماذا يمكن أن يفعل؟ كما ذكر أعلاه ، تتمثل مهمتها الرئيسية في تقديم الأجزاء الضرورية من اللعبة ، على سبيل المثال ، شاشة العنوان ، ساحة اللعب ، الشاشة النهائية للعبة ، إلخ. كيف نفعل ذلك؟ من حيث المبدأ ، يمكنك أن تجد كل ما تحتاجه في وثائق الوحدة النمطية على جيثب ، ولكن باختصار ، لدينا ما يلي:
<a-scene router> ... <a-route id="start-screen" template="start-screen"></a-route> <a-route id="game-field" template="game-field"></a-route> <a-route id="game-over" template="game-over"></a-route> <a-route id="how-to-play" template="how-to-play"></a-route> ... <a-template name="controls"></a-template> ... </a-scene>
- نحن نضيف مكون جهاز التوجيه إلى مكان الحادث.
- أضف مسارًا لكل جزء من التطبيق (إطارات المشهد). مسار واحد للشاشة الرئيسية ، ومسار آخر لملعب ، إلخ.
- تقديم القوالب مباشرة من خلال القوالب
- إذا لزم الأمر ، نغير الطرق من خلال
this.el.systems.router.changeRoute('game-field');
ملاحظة : يشير هذا المثال إلى رمز المشهد ، حتى نتمكن من الاتصال بنظام التوجيه مباشرة. - نقوم بتعيين القوالب وتوصيلها ، شيء مثل هذا:
AFRAME.registerTemplate('game-field', ` <a-sub-assets> <a-asset-item id="glass" src="/assets/models/glass_bottle.gltf"></a-asset-item> ... <audio id="fail" src="/assets/sounds/fail.wav" preload></audio> </a-sub-assets> <a-template name="button" options="text: EXIT; position: 0 1 4; rotation: 0 180 0; event: stop-game"></a-template> <a-entity id="indicator" indicator visible="false" position="0 1 -2" text="align: center; width: 4; color: #00A105; value: -1" ></a-entity> <a-entity game-field-manager></a-entity> `);
ملاحظة: تتيح لك الأصول الفرعية تحميل الأصول بالإضافة إلى الأصول ، ولكن فقط مع وجود اختلاف في الاختيار افتراضيًا وإذا تمت إضافة الأصل بالفعل ، فلن تتم إضافته مرة أخرى عند تغيير المسار.
ملاحظة 2: عادةً لا يمكنك استخدام القوالب إلا مع سلسلة قوالب ES6. خلاف ذلك ، يمكن أن تتحول إلى "سلسلة" + فار + "سلسلة" ، وليس بارد. Kevin ، على سبيل المثال ، لديه دعم لمحركات القوالب. ولكن لماذا تعقيدها ، أليس كذلك؟
وبالتالي ، يمكنك إنشاء بنية تطبيق مريحة تحتوي على ما يلي:
المكونات والأنظمة والقوالب والحالات و libs . لا شيء أكثر وكل شيء على الرفوف.
معالجة الأشياء

المهمة الأولى التي كان يجب حلها كانت التلاعب بالأشياء. كنت بحاجة إلى وظيفية مثل الاستيلاء على رمي. في البداية ، بدأت أفكر في كيفية إنشاء مثل هذا المكون من البداية. على المستوى الفلسفي بحت ، مثل هذا الانعكاس مسموح به: لدينا وحدة تحكم (في حالة سطح المكتب ، يكون المؤشر) ، وله موقع. لدينا أيضًا أشياء معينة ، على سبيل المثال مكعبات ، لديهم أيضًا موقع. عن طريق تغيير موضع وحدة التحكم ، يجب علينا تغيير موضع الكائن. هل هو بسيط؟ نعم ، نعم ، لكنها لن تنجح. سأذكر بضع نقاط من قائمة طويلة جدًا لإقناعك بهذا:
- المؤشر الموجود في الإطار A هو سليل الكاميرا وله إحداثيات نسبية ؛
- موقف وحدة التحكم لا يكفي ، لا تزال بحاجة إلى النظر في الاتجاه ، المسافة إلى الكائن ، موقف الكاميرا (لاعب) ؛
- بالنسبة للكائنات ذات الجسم المادي ، لن يعمل هذا على الإطلاق ، لأن إحداثيات الهندسة مرتبطة بإحداثيات الجسم.
من الجيد أن السيد ويل مورفي الصالح وأصدقائه قاموا
بعمل رائع. في جوهرها ، تحتوي هذه المكتبة على جميع المكونات الضرورية:
- تحوم . التوجيه. قم بتوجيه وحدة التحكم أو المؤشر فوق منطقة التصادم للكائن (عادةً ما يكون الكائن بالكامل)
- grabbable : التقاط. أمسك كائنًا باستخدام الزر المناسب واسحبه
- لمط : الاستيلاء بكلتا يديه وتمتد \ الضغط
- draggable \ dropable : ضروري بشكل أساسي لتحديد الحدث "تم طرح العنصر في موقع محدد"
يمكنك العثور على كل ما تحتاجه حول إعداد وتوصيل الأيدي الفائقة في المستودع المذكور أعلاه. أريد فقط أن ألفت الانتباه إلى عدد من الفروق الدقيقة:
- إنشاء مزج منفصلة لليد اليمنى واليسرى. افصل المكونات حسب نوع الأجهزة المدعومة. على سبيل المثال ، اليد اليمنى ، بالإضافة إلى oculus-touch ، و vive-controls ، و windows-motion-controls ، قد يكون هناك أيضًا oculus-go-controls-gear-vr-controls. يجب إخفاء اليد اليسرى لخوذات BP المحمولة. يجب أن تحتوي كل وحدة تحكم على أيدي mixin ومكون super-hands. مثال
- إذا حددت كائنات: .clsname الخاص بإعادة التدوير ، لا تنسَ إضافته إلى كل عنصر يمكن أخذه باستخدام وحدة التحكم ، وإلا فلن يفشل حدث واحد للأيدي الفائقة. بالطبع ، إذا colliderEvent: raycaster-تقاطع ؛
- السحب باستخدام الإحداثيات الثنائية الأبعاد لمشاريع الماوس في العالم ثلاثي الأبعاد ، لذلك من الأفضل استخدام المؤشر لسطح المكتب.
أضف الفيزياء
إن إضافة الفيزياء إلى الإطار أمر بسيط للغاية. هناك
نظام خاص لهذا الغرض. يضاف إلى المشهد وفويلا ، والفيزياء هي بالفعل في جيبك.
<a-scene physics="debug: false"> <a-box dynamic-body position="0 1 -2"></a-box> <a-box id="floor" static-body></a-box> </a-scene>
علامة :
تصحيح: صحيح يتيح القدرة على عرض الهيئات المادية المرتبطة الهندسة. أنها مريحة عندما تحتاج إلى "مخطط" كائن.
في الواقع ، هذا ملف
مُثبَّت لـ
cannon.js يقوم بكل العمل القذر لمقارنة الهندسة والأجسام المادية لك. مرة أخرى ، حول كيفية عمل هذا النظام ، يمكنك العثور عليه في وصف المستودع. وأود أن أتناول النقطة الوحيدة المهمة في لعبتي.
كنت بحاجة للتأكد من أنه من خلال الضغط على الزر إلى سلة المهملات ، تم تعيين قوة معينة (كلما ضغطت على الزر ، زادت القوة). كما اتضح ، هذه المهمة ليست بهذه البساطة كما تبدو للوهلة الأولى. حسنا ، ما هو معقد جدا؟ - أنت تقول ، نحن
نطبق أو
نفهم . ليس حقًا ... إنه يحدد دوران كائن على طول ناقل يطبق على مركز الجسم. باستخدام هذه الطريقة ، لا يمكننا محاكاة سوى يول. على الرغم من ذلك ، إذا قمت بتعيين متجه بالزاوية الصحيحة للمستوى ، فقد تحصل على شيء مشابه للدفع. ولكن هذا ليس ما احتاجه.
كما اتضح ، كنت بحاجة إلى السرعة عند ضبط هذه المعلمة ، يبدأ الكائن في حركته في اتجاه معين. يتم تحديد هذا الاتجاه بواسطة المتجه. وهنا تبدأ المتعة. كيف تجد هذا المتجه؟ لقد وجدت خيارين:
- احصل على رباعي وحدة التحكم (أو الكاميرا لسطح المكتب) ، الذي يصف اتجاهه في الفضاء. أنشئ متجهًا V1 = <1،1،1> ، اضربه بقوة الرمي وطبق الاتجاه على كل هذا.
const velocityVector = new THREE.Vector3(1,1,1); velocityVector.multiplyScalar(this.force); velocityVector.applyQuaternion(controllerQuaternion); this.grabbed.body.velocity.set(velocityVector.x, velocityVector.y, velocityVector.z);
- ابحث عن موضع وحدة التحكم (المؤشر) وموضع الكائن الذي يتم طرحه. حساب الاتجاه الاتجاه لنقطتين. تطبيع ناقلات. وضربها بالقوة.
const directionX = (trashPosition.x - zeroPosition.x); const directionZ = (trashPosition.z - zeroPosition.z); const vectorsLength = Math.sqrt(Math.pow(directionX, 2) + Math.pow(directionZ, 2)); const x = (directionX / vectorsLength) * this.force; const y = this.force; const z = (directionZ / vectorsLength) * this.force; this.grabbed.body.velocity.set(x , y, z );
اخترت الخيار الثاني لأنه فيه يمكنني حساب x و z فقط. وضبط نفسك ، لأنني كنت في حاجة إلى رمي على طول القوس بحيث تسقط القمامة الملقاة في السلة ، على الرغم من أن المستخدم يحمل وحدة التحكم.
بضع كلمات عن النموذج

منذ البداية ، قررت صنع لعبة ذات نمط
بولي منخفض . على الرغم من أن WebGL قادرة على عرض المشاهد المعقدة نسبيًا اليوم ، إلا أن أدائها لا يزال أدنى من المكتبات المتقدمة مثل DirectX و Vulkan و Mantle ، وما إلى ذلك. يعتمد هذا أيضًا على أداء جهاز المستخدم. نظرًا لأنني أرغب في التركيز على خوذات BP المحمولة ذات الأسعار المعقولة (Oculus Go، Gear VR) ، أعتقد أن انخفاض بولي هو أحد الحلول القليلة لإنشاء تطبيق أو لعبة VR. على الرغم من ، بالطبع ، كل هذا يتوقف على حجم.
حسنًا ، بولي منخفض منخفض بولي ، لكن كيف نفعل كل شيء؟ كل شيء بسيط للغاية ، هناك أداة مفتوحة المصدر جيدة -
Blender . صدقني ، هو قادر على الكثير ، لكن بالنسبة للمهام البسيطة فهو غير مناسب تمامًا. هناك الكثير من المواد التدريبية على عرض الأزياء في Blender ولن يكون من الصعب العثور عليها. أردت فقط التركيز على عدد من النقاط المتعلقة بتطوير الويب:
- ثلاثة شبيبة المصدر هو عفا عليها الزمن. بحاجة الى ايجاد وتوريد GLTF المصدر . GLTF هو تنسيق خاص مصمم للويب. ونعم ، هذا هو JSON.
- GLTF لا يدعم Cycles Renderer ، لذلك يجب عليك استخدام Blender Renderer. وهذا يعني أنه لن يكون هناك عقدة باردة ، وتحولات اللون ، ويسلط الضوء على المعادن (يمكن القيام به بشكل مختلف).
- تحتاج إلى تصدير العنصر المحدد فقط. لا تحتاج إلى كاميرات وأضواء إضافية؟ ملف> تصدير> gltf 2.0. في القائمة اليمنى ، حدد تصدير GLTF 2.0> تصدير فقط.
- نبدأ في التصدير من الموضع <0 ، 0 ، 0> في Blender. من الأفضل القياس في نفس المكان حتى لا تستخدم مكون المقياس في إطار لاحق.
- إذا قمت برسم مساحة مفتوحة كما في Recycle! VR ، تحتاج إلى إضافة كائنات فقط إلى حيث يمكن للاعب أن ينظر نظريا. وراء ، وراء المنازل ، في سلة! هناك بضعة أشجار وفقط في المكان الذي يمكن للمستخدم رؤيته فيه. ليس من الضروري زيادة التحميل على المشهد.
- إذا كنت بحاجة إلى تغيير مادة الطراز ، فيجب عليك الانتظار حتى يتم التحميل ، والحصول على النموذج نفسه ، وسحب جميع العقد منه (يحتوي GLTF على معلومات ليس فقط حول الشبكات)
e.detail.model.traverse((node) => { if (node.isMesh) { node.material.color = new THREE.Color(someColor); } });
في الختام
شكرا لكم جميعا على اهتمامكم! أذكرك مرة أخرى أن مستودع المشروع متاح على
الرابط التالي . أي شخص يريد أن يجلب شيئا جديدا لهذه اللعبة - مرحبا بكم.