إطار A-Frame هو إطار قائم على الويب يتيح لك إنشاء تطبيقات وألعاب ومشاهد مختلفة في الواقع الافتراضي (VR). كل ما سبق سوف يكون متاحًا مباشرةً من متصفح خوذة VR الخاصة بك. ستكون هذه الأداة مفيدة لأولئك الذين يرغبون في تطوير ألعاب VR في مستعرض ، وعلى سبيل المثال ، يمكن أن تكون مفيدة كمنصة لإنشاء تطبيقات VR على الويب ومواقع الويب والصفحات المقصودة. استخدامات الويب BP محدودة فقط بخيالك. Offhand يمكنني أن أجلب بضعة مجالات من النشاط البشري حيث BP يمكن أن تكون مفيدة: التعليم والطب والرياضة والمبيعات والترفيه.
ما هو في الداخل؟
لا تتم كتابة الإطار A من 0 على WebGL الخالص ، بل يستند إلى مكتبة
Three.js . لذلك ، أوصي بأن تفهم أولاً المفاهيم الأساسية لـ Three.js قبل البدء في العمل باستخدام A-Frame ، على الرغم من أن هذا ليس ضروريًا ، لأن A-Frame مصمم بحيث لا يمكنك التفكير في تقديم الهندسة والتركيز أكثر على منطق التطبيق الخاص بك . لهذا السبب هو ، في الواقع ، والإطار.
لهذا ، يفترض إطار A-ثلاث نقاط رئيسية ، والتي سنتحدث عنها لاحقًا.
A- الإطار يعمل مع HTML
تتم إضافة العديد من عناصر A-Frame الأساسية ، مثل المشهد والكاميرا والمربع والكرة وما إلى ذلك ، إلى المشهد من خلال علامات تحمل الاسم نفسه مع بادئة
a- . يتم تسجيل كل عنصر مماثل كعرف. الإطار A (0.8.0) يستخدم حاليًا مواصفات v0.
<a-scene> <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box> <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere> </a-scene>
سوف ترسم هذه القطعة الصغيرة من الكود مشهد WebGL الذي سيتم إضافة كائنين إليه: مكعب ومجال مع المعلمات المحددة. بالإضافة إلى العنصرين المذكورين أعلاه ، هناك عدد من البدائل الأخرى التي يمكن إضافتها إلى المشهد بنفس الطريقة:
<a-circle> ، <a-cone> ، <a-cylinder> ، <a-dodecahedron> ، <a-icosahedron> ، <a-octahedron> ، <a-plane> ، <a-ring> ، <a-tetrahedron> ، <a-torus-knot> ، <a-torus> ، <a-triangle> . في الإطار A أيضًا ، يوجد عدد من العناصر الأخرى التي تؤدي وظائف معينة:
- <a-camera> - ينشئ كاميرا. الكاميرا المنظورية فقط (PerspectiveCamera) مدعومة حاليًا.
- <a-obj-model> ، <a-collada-model> ، <a-gltf-model> - جميعها تحمّل وتعرض نماذج بالتنسيق المقابل.
- <a-cursor> - عنصر يسمح لك بتنفيذ العديد من الإجراءات: النقر ، التوجيه ، إلخ. المؤشر مرتبط بوسط الكاميرا ، لذلك سيكون دائمًا في مركز ما يراه المستخدم.
- <a-image> - يعرض الصورة المحددة على متن طائرة (<a-plane>).
- <a-link> هي نفسها العلامة ، فقط للمشهد ثلاثي الأبعاد.
- <a-sky> - اسطوانة ضخمة حول المسرح تتيح لك عرض 360 صورة. أو يمكنك ببساطة ملء ذلك مع بعض الألوان.
- <a-sound> - ينشئ مصدرًا صوتيًا في موضع معين.
- <a-text> - يرسم النص المسطح.
- <a-video> - تشغيل الفيديو على متن طائرة.
أود أيضًا أن أشير إلى أننا نعمل مع عناصر DOM ، وبالتالي يمكننا استخدام DOM API القياسي ، بما في ذلك querySelector ، getElementById ، appendChild ، إلخ.
A- الإطار يستخدم ECS
ECS (نظام مكونات الكيان) - نمط تصميم التطبيق واللعبة. كان واسع الانتشار فقط في الجزء الثاني. كما يوحي الاسم ، فإن المفاهيم الأساسية الثلاثة للنمط هي الكيان والمكون والنظام. في النموذج الكلاسيكي ، يتم ربطها على النحو التالي: لدينا بعض الكائنات الحاوية (الكيان) التي يمكننا إضافة مكونات إليها. عادةً ما يكون المكون مسؤولاً عن جزء منفصل من المنطق. على سبيل المثال ، لدينا كائن Player ، يحتوي على مكون Health. سيحتوي هذا المكون على كل المنطق المرتبط بتجديد أو فقد صحة اللاعب (كائن). والنظم ، بدورها ، ضرورية من أجل إدارة مجموعة من الكيانات مجتمعة بواسطة بعض المكونات. عادة ، يمكن للمكون تسجيل كيان داخل النظام الذي يحمل نفس الاسم.
في الإطار A ، يتم تطبيق هذا النمط بكل بساطة وأناقة - بمساعدة السمات. يتم استخدام أي من عناصر A-Frame -
<a-scene> ، <a-box> ، <a-sphere> ، وما إلى ذلك ، ككيانات ، ولكن ، بالطبع ،
عنصر <a-entity> منفصل . اسمه يتحدث عن نفسه. جميع العناصر الأخرى عبارة عن غلاف للمكونات ويتم تصنيعها للراحة ، حيث يمكن أيضًا إنشاء أي عنصر باستخدام
<a-entity> . على سبيل المثال
<a-box> :
<a-entity geometry="primitive: box; width: 1; height: 1; depth: 1"></a-entity>
الشكل
الهندسي - في هذه الحالة ، هو المكون الذي تمت إضافته إلى
الكيان <a-entity> .
ليس لدى <a-entity> نفسه أي منطق (بالمعنى العام) ، ويقوم المكون
الهندسي بتحويله أساسًا إلى مكعب أو أي شيء آخر. عنصر آخر لا يقل أهمية عن
الهندسة المادية . وتضيف المواد إلى الهندسة. المواد هي المسؤولة عن ما إذا كان مكعبنا سوف يلمع مثل المعدن ، وما إذا كان سيكون له أي مواد ، إلخ. في
Three.js الخالص
، سيتعين علينا إنشاء هندسة منفصلة ، مادة منفصلة ، ومن ثم يجب دمج كل هذا في ذاكرة التخزين المؤقت. بشكل عام ، هذا النهج يوفر الوقت.
يجب تسجيل أي مكون في الإطار A على المستوى العالمي من خلال تصميم خاص:
AFRAME.registerComponent('hello-world', { init: function () { console.log('Hello, World!'); } });
ثم يمكن إضافة هذا المكون إلى المشهد ، أو أي عنصر آخر.
<a-entity hello-world></a-entity>
نظرًا لأننا قمنا بإضافة رد الاتصال
الأولي لمكوننا ، بمجرد إضافة العنصر إلى DOM ، فإن رد الاتصال سيعمل وسنرى رسالتنا في وحدة التحكم. هناك عمليات الاسترجاعات دورة حياة أخرى في مكونات A-Frame. دعونا نتناولها بمزيد من التفاصيل:
- تحديث - يسمى كلاهما أثناء التهيئة كـ init ، وعند تحديث أي خاصية لهذا المكون.
- إزالة - يسمى بعد إزالة مكون أو كيان يحتوي عليه. وهذا هو ، إذا قمت بإزالة <a-entity> من DOM ، فسوف تستدعي جميع مكوناته إزالة رد الاتصال.
- القراد - يسمى في كل مرة قبل تقديم المشهد. داخل تجسيد حلقة يستخدم requestAnimaitonFrame
- توك - يسمى في كل مرة بعد تقديم مشهد.
- اللعب - يتم استدعاء كل منها عند استئناف تقديم المشهد. أساسا بعد scene.play () ؛
- توقف مؤقت - يتم الاتصال به في كل مرة يتم فيها إيقاف عرض المشهد. أساسا بعد scene.pause () ؛
- updateSchema - يسمى في كل مرة بعد تحديث المخطط.
مفهوم آخر مهم مكون في A- الإطار هو الدوائر. يصف المخطط خصائص المكون. يتم تعريفها على النحو التالي:
AFRAME.registerComponent('my-component', { schema: { arrayProperty: {type: 'array', default: []}, integerProperty: {type: 'int', default: 5} } }
في هذه الحالة ، سيحتوي
المكون الخاص بي على خاصيتين ،
arrayProperty و
integerProperty . لتمريرها إلى المكون ، تحتاج إلى تعيين قيمة السمة المقابلة.
<a-entity my-component="arrayProperty: 1,2,3; integerProperty: 7"></a-entity>
يمكنك الحصول على هذه الخصائص داخل المكون من خلال خاصية
البيانات .
AFRAME.registerComponent('my-component', { schema: { arrayProperty: {type: 'array', default: []}, integerProperty: {type: 'int', default: 5} }, init: function () { console.log(this.data); } }
للحصول على خصائص مكون من الكيان الذي تمت إضافته إليه ، يمكنك استخدام دالة
getAttribute المعدلة قليلاً. عند الوصول إلى كيان A-Frame ، فإنه لن يُرجع فقط قيمة سلسلة السمة ، ولكن كائن
البيانات المذكور أعلاه.
console.log(this.el.getAttribute('my-component'));
بنفس الطريقة تقريبًا ، يمكنك تغيير خصائص أحد المكونات:
this.el.setAttribute('my-component',{arrayProperty: [], integerProperty: 5})
الآن دعونا نتحدث عن النظم. يتم تسجيل الأنظمة في الإطار A بنفس طريقة تسجيل المكونات:
AFRAME.registerSystem('my-system', { schema: {}, init: function () { console.log('Hello, System!'); }, });
بالإضافة إلى المكون ، يحتوي النظام على دائرة وعمليات معاودة الاتصال. يحتوي النظام فقط على 5 منهم فقط:
init ، play ، pause ، tick ، tock . لا يحتاج النظام إلى إضافته كمكون إلى الكيان. سيتم إضافته تلقائيًا إلى مكان الحادث.
this.el.sceneEl.systems['my-system'];
إذا كان المكون له نفس اسم النظام ، فسيكون النظام متاحًا على هذا
النظام .
AFRAME.registerSystem('enemy', { schema: {}, init: function () {}, }); AFRAME.registerComponent('enemy', { schema: {}, init: function () { const enemySystem = this.system; }, });
عادة ، هناك حاجة إلى أنظمة لتجميع وإدارة الكيانات مع المكونات ذات الصلة. هنا ، من الناحية النظرية ، يجب أن يكون هناك منطق يتعلق بمجموعة من الكيانات. على سبيل المثال ، تحكم في ظهور الأعداء في اللعبة.
يحدث التواصل في الإطار A من خلال وسائل أحداث المتصفح
في الواقع ، لماذا تعيد اختراع العجلة ، إذا كان هناك في الوقت الحالي تطبيق ناشر ومشترك مدمج رائع لعناصر DOM. تسمح لك أحداث DOM بالاستماع إلى كلا أحداث المستعرض ، مثل ضغط المفاتيح ، والنقر بالماوس ، وأحداث المستخدم الأخرى. يوفر لنا A-Frame وسيلة مريحة وسهلة للتواصل بين الكيانات والمكونات والأنظمة ، من خلال أحداث المستخدم. لذلك ، يتم تصحيح كل عنصر من عناصر A-Frame بواسطة دالة
emit ، ويستغرق ذلك ثلاثة معلمات:
الأول هو اسم الحدث ،
والثاني هو البيانات المراد إرسالها ،
والثالث هو ما إذا كان يجب أن يطفو على السطح الحدث.
this.el.emit('start-game', {level: 1}, false);
يمكنك الاشتراك في هذا الحدث بالطريقة المعتادة لنا جميعًا ، وذلك باستخدام
addEventListener: const someEntity = document.getElementById('someEntity'); someEntity.addEventListener('start-game', () => {...});
تمثل فقاعات الأحداث هنا نقطة مهمة للغاية ، لأنه في بعض الأحيان يكون كيانان يجب أن يتواصلا مع بعضهما البعض على نفس المستوى ، وفي هذه الحالة يمكنك إضافة مستمع حدث إلى عنصر المشهد. كما ترى سابقًا ، يتوفر داخل كل عنصر عبر رابط
sceneEl .
this.el.sceneEl.addEventListener('start-game', () => {...});
في الختام
ربما هذا هو كل ما أردت التحدث عنه في هذا المقال. يحتوي A-Frame على الكثير من الموضوعات المختلفة التي يمكن تغطيتها ، لكن هذه المقالة عبارة عن مراجعة وأردت التركيز على القارئ فقط على النقاط الرئيسية.
في المقالة التالية ، سنحاول إنشاء مشهد أساسي لاختبار كل المعرفة المكتسبة في الممارسة. شكرا لكم جميعا!