كيفية بناء لعبة عداء لا نهاية لها في الواقع الافتراضي (الجزء الثاني)

نشرت: 2022-03-10
ملخص سريع ↬ إذا تساءلت يومًا عن كيفية إنشاء الألعاب التي تدعم سماعات رأس الواقع الافتراضي بدون لوحة مفاتيح ، فإن هذا البرنامج التعليمي يشرح فقط ما تبحث عنه. إليك كيف يمكنك أيضًا إحياء لعبة VR الأساسية والفعالة.

في الجزء الأول من هذه السلسلة ، رأينا كيف يمكن إنشاء نموذج واقع افتراضي مع تأثيرات الإضاءة والرسوم المتحركة. في هذا الجزء ، سنقوم بتنفيذ منطق اللعبة الأساسي واستخدام معالجات بيئة A-Frame أكثر تقدمًا لبناء جزء "اللعبة" من هذا التطبيق. في النهاية ، سيكون لديك لعبة واقع افتراضي فعالة مع تحدٍ حقيقي.

يتضمن هذا البرنامج التعليمي عددًا من الخطوات ، بما في ذلك (على سبيل المثال لا الحصر) اكتشاف التصادم والمزيد من مفاهيم الإطار A مثل الخلطات.

  • عرض المنتج النهائي

المتطلبات الأساسية

تمامًا كما في البرنامج التعليمي السابق ، ستحتاج إلى ما يلي:

  • الوصول إلى الإنترنت (على وجه التحديد لموقع glitch.com) ؛
  • مشروع خلل مكتمل من الجزء 1. (يمكنك المتابعة من المنتج النهائي بالانتقال إلى https://glitch.com/edit/#!/ergo-1 والنقر على "ريمكس للتحرير" ؛
  • سماعة رأس للواقع الافتراضي (اختيارية ، موصى بها). (أستخدم Google Cardboard ، والذي يتم تقديمه بسعر 15 دولارًا للقطعة.)
المزيد بعد القفز! أكمل القراءة أدناه ↓

الخطوة الأولى: تصميم العوائق

في هذه الخطوة ، تصمم الأشجار التي سنستخدمها كعقبات. بعد ذلك ، ستقوم بإضافة رسم متحرك بسيط يحرك الأشجار باتجاه المشغل ، مثل ما يلي:

أشجار القالب تتحرك نحو اللاعب
أشجار القوالب تتحرك نحو المشغل (معاينة كبيرة)

ستعمل هذه الأشجار كقوالب للعقبات التي تولدها أثناء اللعبة. في الجزء الأخير من هذه الخطوة ، سنزيل "أشجار القوالب" هذه.

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

ملاحظة : في البرنامج التعليمي الخاص بنا ، ستكون أصولك الوحيدة هي mixins. قم بزيارة صفحة A-Frame Mixins لمعرفة المزيد.

في المحرر الخاص بك ، انتقل إلى index.html . بعد سمائك مباشرةً وقبل الأضواء ، أضف كيان A-Frame جديدًا للاحتفاظ بأصولك:

 <a-sky...></a-sky> <!-- Mixins --> <a-assets> </a-assets> <!-- Lights --> ...

في كيان a-assets الجديد الخاص بك ، ابدأ بإضافة مزيج لأوراقك. تحدد هذه الخلطات الخصائص المشتركة لأوراق الشجرة النموذجية. باختصار ، إنه هرم أبيض مظلل بشكل مسطح ، لتأثير بولي منخفض.

 <a-assets> <a-mixin geometry=" primitive: cone; segments-height: 1; segments-radial:4; radius-bottom:0.3;" material="color:white;flat-shading: true;"></a-mixin> </a-assets>

أضف خليطًا للجذع أسفل خليط أوراق الشجر. سيكون هذا الصندوق عبارة عن منشور صغير مستطيل أبيض اللون.

 <a-assets> ... <a-mixin geometry=" primitive: box; height:0.5; width:0.1; depth:0.1;" material="color:white;"></a-mixin> </a-assets>

بعد ذلك ، أضف كائنات شجرة القوالب التي ستستخدم هذه الخلطات. لا يزال في index.html ، قم بالتمرير لأسفل إلى قسم الأنظمة الأساسية. قبل قسم المشغل مباشرةً ، أضف قسمًا جديدًا للشجرة ، مع ثلاثة كيانات شجرة فارغة:

 <a-entity ...> <!-- Trees --> <a-entity></a-entity> <a-entity></a-entity> <a-entity></a-entity> <!-- Player --> ...

بعد ذلك ، قم بتغيير موضع ، وإعادة قياس ، وإضافة الظلال إلى كيانات الشجرة.

 <!-- Trees --> <a-entity shadow scale="0.3 0.3 0.3" position="0 0.6 0"></a-entity> <a-entity shadow scale="0.3 0.3 0.3" position="0 0.6 0"></a-entity> <a-entity shadow scale="0.3 0.3 0.3" position="0 0.6 0"></a-entity>

الآن ، قم بتعبئة كيانات الشجرة بجذع وأوراق ، باستخدام الخلطات التي حددناها مسبقًا.

 <!-- Trees --> <a-entity ...> <a-entity mixin="foliage"></a-entity> <a-entity mixin="trunk" position="0 -0.5 0"></a-entity> </a-entity> <a-entity ...> <a-entity mixin="foliage"></a-entity> <a-entity mixin="trunk" position="0 -0.5 0"></a-entity> </a-entity> <a-entity ...> <a-entity mixin="foliage"></a-entity> <a-entity mixin="trunk" position="0 -0.5 0"></a-entity> </a-entity>

انتقل إلى المعاينة ، وسترى الآن أشجار القوالب التالية.

قالب الأشجار للعقبات
أشجار القوالب للعقبات (معاينة كبيرة)

الآن ، قم بتحريك الأشجار من مكان بعيد على المنصة تجاه المستخدم. كما في السابق ، استخدم علامة a-animation :

 <!-- Trees --> <a-entity ...> ... <a-animation attribute="position" ease="linear" from="0 0.6 -7" to="0 0.6 1.5" dur="5000"></a-animation> </a-entity> <a-entity ...> ... <a-animation attribute="position" ease="linear" from="-0.5 0.55 -7" to="-0.5 0.55 1.5" dur="5000"></a-animation> </a-entity> <a-entity ...> ... <a-animation attribute="position" ease="linear" from="0.5 0.55 -7" to="0.5 0.55 1.5" dur="5000"></a-animation> </a-entity>

تأكد من أن التعليمات البرمجية الخاصة بك تطابق ما يلي.

 <a-entity...> <!-- Trees --> <a-entity shadow scale="0.3 0.3 0.3" position="0 0.6 0"> <a-entity mixin="foliage"></a-entity> <a-entity mixin="trunk" position="0 -0.5 0"></a-entity> <a-animation attribute="position" ease="linear" from="0 0.6 -7" to="0 0.6 1.5" dur="5000"></a-animation> </a-entity> <a-entity shadow scale="0.3 0.3 0.3" position="-0.5 0.55 0"> <a-entity mixin="foliage"></a-entity> <a-entity mixin="trunk" position="0 -0.5 0"></a-entity> <a-animation attribute="position" ease="linear" from="-0.5 0.55 -7" to="-0.5 0.55 1.5" dur="5000"></a-animation> </a-entity> <a-entity shadow scale="0.3 0.3 0.3" position="0.5 0.55 0"> <a-entity mixin="foliage"></a-entity> <a-entity mixin="trunk" position="0 -0.5 0"></a-entity> <a-animation attribute="position" ease="linear" from="0.5 0.55 -7" to="0.5 0.55 1.5" dur="5000"></a-animation> </a-entity> <!-- Player --> ...

انتقل إلى المعاينة الخاصة بك ، وسترى الآن الأشجار تتحرك نحوك.

أشجار القالب تتحرك نحو اللاعب
أشجار القوالب تتحرك نحو المشغل أشجار القوالب تتحرك نحو المشغل (معاينة كبيرة)

انتقل مرة أخرى إلى المحرر الخاص بك. هذه المرة ، حدد الأصول / ergo.js. في قسم اللعبة ، قم بإعداد الأشجار بعد تحميل النافذة.

 /******** * GAME * ********/ ... window.onload = function() { setupTrees(); }

أسفل عناصر التحكم ولكن قبل قسم اللعبة ، أضف قسم TREES جديدًا. في هذا القسم ، حدد وظيفة setupTrees جديدة.

 /************ * CONTROLS * ************/ ... /********* * TREES * *********/ function setupTrees() { } /******** * GAME * ********/ ...

في وظيفة setupTrees الجديدة ، احصل على مراجع لكائنات DOM لشجرة القوالب ، واجعل المراجع متاحة عالميًا.

 /********* * TREES * *********/ var templateTreeLeft; var templateTreeCenter; var templateTreeRight; function setupTrees() { templateTreeLeft = document.getElementById('template-tree-left'); templateTreeCenter = document.getElementById('template-tree-center'); templateTreeRight = document.getElementById('template-tree-right'); }

بعد ذلك ، حدد أداة removeTree جديدة. باستخدام هذه الأداة ، يمكنك بعد ذلك إزالة أشجار القوالب من المشهد. تحت وظيفة setupTrees ، حدد الأداة المساعدة الجديدة.

 function setupTrees() { ... } function removeTree(tree) { tree.parentNode.removeChild(tree); }

مرة أخرى في setupTrees ، استخدم الأداة المساعدة الجديدة لإزالة أشجار القوالب.

 function setupTrees() { ... removeTree(templateTreeLeft); removeTree(templateTreeRight); removeTree(templateTreeCenter); }

تأكد من تطابق أقسام الشجرة والألعاب مع ما يلي:

 /********* * TREES * *********/ var templateTreeLeft; var templateTreeCenter; var templateTreeRight; function setupTrees() { templateTreeLeft = document.getElementById('template-tree-left'); templateTreeCenter = document.getElementById('template-tree-center'); templateTreeRight = document.getElementById('template-tree-right'); removeTree(templateTreeLeft); removeTree(templateTreeRight); removeTree(templateTreeCenter); } function removeTree(tree) { tree.parentNode.removeChild(tree); } /******** * GAME * ********/ setupControls(); // TODO: AFRAME.registerComponent has to occur before window.onload? window.onload = function() { setupTrees(); }

أعد فتح المعاينة ، ويجب أن تكون أشجارك الآن غائبة. يجب أن تتطابق المعاينة مع لعبتنا في بداية هذا البرنامج التعليمي.

الجزء 1 المنتج النهائي
المنتج النهائي الجزء 1 (معاينة كبيرة)

هذا يختتم تصميم شجرة القالب.

في هذه الخطوة ، قمنا بتغطية واستخدام مزيج A-Frame ، والذي يسمح لنا بتبسيط الكود عن طريق تحديد الخصائص المشتركة. علاوة على ذلك ، استفدنا من تكامل الإطار A مع DOM لإزالة الكائنات من مشهد الواقع الافتراضي بإطار A.

في الخطوة التالية ، سننشئ عوائق متعددة ونصمم خوارزمية بسيطة لتوزيع الأشجار بين الممرات المختلفة.

الخطوة الثانية: تفريخ العوائق

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

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

في هذه الخطوة ، سيتم إجراء جميع تعديلات التعليمات البرمجية الخاصة بنا في الأصول / ergo.js. سيبقى ملف HTML كما هو. انتقل إلى قسم TREES من الأصول / ergo.js.

للبدء ، سنضيف أدوات مساعدة لتفرخ الأشجار. ستحتاج كل شجرة إلى معرّف فريد ، والذي سنحدده بسذاجة ليكون عدد الأشجار الموجودة عند تكاثر الشجرة. ابدأ بتتبع عدد الأشجار في متغير عام.

 /********* * TREES * *********/ ... var numberOfTrees = 0; function setupTrees() { ...

بعد ذلك ، سنهيئ مرجعًا لعنصر DOM لحاوية الشجرة ، والذي ستضيف إليه وظيفة التفرخ الأشجار. لا يزال في قسم TREES ، أضف متغيرًا عامًا ثم قم بعمل المرجع.

 ... var treeContainer; var numberOfTrees ... function setupTrees() { ... templateTreeRight = ... treeContainer = document.getElementById('tree-container'); removeTree(...); ... }

باستخدام كل من عدد الأشجار وحاوية الشجرة ، اكتب وظيفة جديدة تفرز الأشجار.

 function removeTree(tree) { ... } function addTree(el) { numberOfTrees += 1; el.id = 'tree-' + numberOfTrees; treeContainer.appendChild(el); } ...

لتسهيل الاستخدام لاحقًا ، ستقوم بإنشاء وظيفة ثانية تضيف الشجرة الصحيحة إلى المسار الصحيح. للبدء ، حدد مجموعة templates جديدة في قسم TREES .

 var templates; var treeContainer; ... function setupTrees() { ... templates = [templateTreeLeft, templateTreeCenter, templateTreeRight]; removeTree(...); ... }

باستخدام مصفوفة القوالب هذه ، أضف الأداة المساعدة التي تولد الأشجار في حارة معينة ، مع إعطاء معرف يمثل اليسار أو الوسط أو اليمين.

 function function addTree(el) { ... } function addTreeTo(position_index) { var template = templates[position_index]; addTree(template.cloneNode(true)); }

انتقل إلى المعاينة وافتح وحدة تحكم المطور الخاصة بك. في وحدة تحكم المطور الخاصة بك ، قم باستدعاء وظيفة addTreeTo العالمية.

 > addTreeTo(0); # spawns tree in left lane 
استدعاء addTreeTo يدويًا
استدعاء addTreeTo يدويًا (معاينة كبيرة)

الآن ، ستكتب خوارزمية تولد الأشجار بشكل عشوائي:

  1. اختر مسارًا عشوائيًا (لم يتم اختياره بعد لهذه الخطوة الزمنية) ؛
  2. تفرخ شجرة مع بعض الاحتمالات ؛
  3. إذا تم إنتاج الحد الأقصى من الأشجار لهذه الخطوة الزمنية ، فتوقف. خلاف ذلك ، كرر الخطوة 1.

لتفعيل هذه الخوارزمية ، سنعمل بدلاً من ذلك على تبديل قائمة القوالب عشوائيًا ومعالجة واحدة تلو الأخرى. ابدأ بتحديد وظيفة جديدة ، addTreesRandomly بشكل عشوائي يقبل عددًا من وسيطات الكلمات الأساسية المختلفة.

 function addTreeTo(position_index) { ... } /** * Add any number of trees across different lanes, randomly. **/ function addTreesRandomly( { probTreeLeft = 0.5, probTreeCenter = 0.5, probTreeRight = 0.5, maxNumberTrees = 2 } = {}) { }

في وظيفة addTreesRandomly الجديدة الخاصة بك ، حدد قائمة بأشجار القوالب ، وقم بتبديل القائمة عشوائيًا.

 function addTreesRandomly( ... ) { var trees = [ {probability: probTreeLeft, position_index: 0}, {probability: probTreeCenter, position_index: 1}, {probability: probTreeRight, position_index: 2}, ] shuffle(trees); }

قم بالتمرير لأسفل إلى الجزء السفلي من الملف ، وأنشئ قسمًا جديدًا لأدوات المساعدة ، جنبًا إلى جنب مع أداة shuffle الجديدة. ستعمل هذه الأداة على تبديل المصفوفة عشوائيًا في مكانها.

 /******** * GAME * ********/ ... /************* * UTILITIES * *************/ /** * Shuffles array in place. * @param {Array} a items An array containing the items. */ function shuffle(a) { var j, x, i; for (i = a.length - 1; i > 0; i--) { j = Math.floor(Math.random() * (i + 1)); x = a[i]; a[i] = a[j]; a[j] = x; } return a; }

انتقل مرة أخرى إلى وظيفة addTreesRandomly في قسم الأشجار. أضف متغيرًا جديدًا numberOfTreesAdded وقم بالتكرار خلال قائمة الأشجار المحددة أعلاه.

 function addTreesRandomly( ... ) { ... var numberOfTreesAdded = 0; trees.forEach(function (tree) { }); }

في التكرار فوق الأشجار ، تفرخ شجرة فقط مع بعض الاحتمالات وفقط إذا كان عدد الأشجار المضافة لا يتجاوز 2 . قم بتحديث حلقة for على النحو التالي.

 function addTreesRandomly( ... ) { ... trees.forEach(function (tree) { if (Math.random() < tree.probability && numberOfTreesAdded < maxNumberTrees) { addTreeTo(tree.position_index); numberOfTreesAdded += 1; } }); }

لإنهاء الوظيفة ، قم بإرجاع عدد الأشجار المضافة.

 function addTreesRandomly( ... ) { ... return numberOfTreesAdded; }

تحقق جيدًا من أن وظيفة addTreesRandomly تطابق ما يلي.

 /** * Add any number of trees across different lanes, randomly. **/ function addTreesRandomly( { probTreeLeft = 0.5, probTreeCenter = 0.5, probTreeRight = 0.5, maxNumberTrees = 2 } = {}) { var trees = [ {probability: probTreeLeft, position_index: 0}, {probability: probTreeCenter, position_index: 1}, {probability: probTreeRight, position_index: 2}, ] shuffle(trees); var numberOfTreesAdded = 0; trees.forEach(function (tree) { if (Math.random() < tree.probability && numberOfTreesAdded < maxNumberTrees) { addTreeTo(tree.position_index); numberOfTreesAdded += 1; } }); return numberOfTreesAdded; }

أخيرًا ، لتوليد الأشجار تلقائيًا ، قم بإعداد مؤقت يعمل على تشغيل تفرخ الأشجار على فترات منتظمة. حدد المؤقت عالميًا ، وأضف وظيفة تفكيك جديدة لهذا المؤقت.

 /********* * TREES * *********/ ... var treeTimer; function setupTrees() { ... } function teardownTrees() { clearInterval(treeTimer); }

بعد ذلك ، حدد وظيفة جديدة تقوم بتهيئة المؤقت وحفظ المؤقت في المتغير العام المحدد مسبقًا. يتم تشغيل المؤقت أدناه كل نصف ثانية.

 function addTreesRandomlyLoop({intervalLength = 500} = {}) { treeTimer = setInterval(addTreesRandomly, intervalLength); }

أخيرًا ، ابدأ المؤقت بعد تحميل النافذة ، من قسم اللعبة.

 /******** * GAME * ********/ ... window.onload = function() { ... addTreesRandomlyLoop(); }

انتقل إلى المعاينة الخاصة بك ، وسترى الأشجار تتكاثر بشكل عشوائي. لاحظ أنه لا توجد ثلاث شجرات في نفس الوقت.

تفرخ الشجرة بشكل عشوائي
تفرخ الشجرة عشوائيًا (معاينة كبيرة)

هذا يخلص خطوة العقبات. لقد نجحنا في أخذ عدد من أشجار القوالب وإنشاء عدد لا حصر له من العوائق من القوالب. تحترم خوارزمية التفريخ أيضًا القيود الطبيعية في اللعبة لجعلها قابلة للعب.

في الخطوة التالية ، دعنا نضيف اختبار الاصطدام.

الخطوة الثالثة: اختبار الاصطدام

في هذا القسم ، سنقوم بتنفيذ اختبارات التصادم بين العوائق واللاعبين. تعتبر اختبارات الاصطدام هذه أبسط من اختبارات التصادم في معظم الألعاب الأخرى ؛ ومع ذلك ، يتحرك اللاعب فقط على طول المحور السيني ، لذلك عندما تتقاطع الشجرة مع المحور السيني ، تحقق مما إذا كان ممر الشجرة هو نفسه حارة اللاعب. سنقوم بتنفيذ هذا الفحص البسيط لهذه اللعبة.

انتقل إلى index.html ، وصولاً إلى قسم TREES . هنا ، سنضيف معلومات الممر إلى كل شجرة. لكل شجرة ، قم بإضافة data-tree-position-index= ، على النحو التالي. بالإضافة إلى ذلك ، أضف class="tree" ، حتى نتمكن بسهولة من تحديد جميع الأشجار أسفل السطر:

 <a-entity data-tree-position-index="1" class="tree" ...> </a-entity> <a-entity data-tree-position-index="0" class="tree" ...> </a-entity> <a-entity data-tree-position-index="2" class="tree" ...> </a-entity>

انتقل إلى الأصول / ergo.js واستدع وظيفة setupCollisions الجديدة في قسم GAME . بالإضافة إلى ذلك ، حدد متغيرًا عالميًا جديدًا isGameRunning يشير إلى ما إذا كانت هناك لعبة موجودة قيد التشغيل بالفعل أم لا.

 /******** * GAME * ********/ var isGameRunning = false; setupControls(); setupCollision(); window.onload = function() { ...

حدد قسم COLLISIONS جديدًا بعد قسم TREES مباشرةً ولكن قبل قسم اللعبة. في هذا القسم ، حدد وظيفة setupCollisions.

 /********* * TREES * *********/ ... /************** * COLLISIONS * **************/ const POSITION_Z_OUT_OF_SIGHT = 1; const POSITION_Z_LINE_START = 0.6; const POSITION_Z_LINE_END = 0.7; function setupCollision() { } /******** * GAME * ********/

كما كان من قبل ، سنقوم بتسجيل مكون AFRAME ونستخدم مستمع حدث tick لتشغيل الكود في كل خطوة. في هذه الحالة ، سوف نسجل مكونًا مع player ونجري عمليات تحقق ضد جميع الأشجار في ذلك المستمع:

 function setupCollisions() { AFRAME.registerComponent('player', { tick: function() { document.querySelectorAll('.tree').forEach(function(tree) { } } } }

في حلقة for ، ابدأ بالحصول على معلومات الشجرة ذات الصلة:

 document.querySelectorAll('.tree').forEach(function(tree) { position = tree.getAttribute('position'); tree_position_index = tree.getAttribute('data-tree-position-index'); tree_id = tree.getAttribute('id'); }

بعد ذلك ، لا تزال داخل حلقة for ، قم بإزالة الشجرة إذا كانت بعيدة عن الأنظار ، مباشرة بعد استخراج خصائص الشجرة:

 document.querySelectorAll('.tree').forEach(function(tree) { ... if (position.z > POSITION_Z_OUT_OF_SIGHT) { removeTree(tree); } }

بعد ذلك ، إذا لم تكن هناك لعبة قيد التشغيل ، فلا تتحقق مما إذا كان هناك تصادم.

 document.querySelectorAll('.tree').forEach(function(tree) { if (!isGameRunning) return; }

أخيرًا (لا تزال في حلقة for ) ، تحقق مما إذا كانت الشجرة تشترك في نفس الموضع مع اللاعب في نفس الوقت. إذا كان الأمر كذلك ، فقم باستدعاء وظيفة gameOver التي لم يتم تحديدها بعد:

 document.querySelectorAll('.tree').forEach(function(tree) { ... if (POSITION_Z_LINE_START < position.z && position.z < POSITION_Z_LINE_END && tree_position_index == player_position_index) { gameOver(); } }

تحقق من أن وظيفة setupCollisions الخاصة بك تتطابق مع ما يلي:

 function setupCollisions() { AFRAME.registerComponent('player', { tick: function() { document.querySelectorAll('.tree').forEach(function(tree) { position = tree.getAttribute('position'); tree_position_index = tree.getAttribute('data-tree-position-index'); tree_id = tree.getAttribute('id'); if (position.z > POSITION_Z_OUT_OF_SIGHT) { removeTree(tree); } if (!isGameRunning) return; if (POSITION_Z_LINE_START < position.z && position.z < POSITION_Z_LINE_END && tree_position_index == player_position_index) { gameOver(); } }) } }) }

هذا ينهي إعداد التصادم. الآن ، سنضيف بعض التفاصيل الدقيقة لاستخراج تسلسل gameOver و startGame بعيدًا. انتقل إلى قسم GAME . قم بتحديث كتلة window.onload لتتطابق مع ما يلي ، مع استبدال addTreesRandomlyLoop التي لم يتم تحديدها startGame .

 window.onload = function() { setupTrees(); startGame(); }

أسفل استدعاءات وظيفة الإعداد ، قم بإنشاء وظيفة startGame جديدة. ستعمل هذه الوظيفة على تهيئة المتغير isGameRunning وفقًا لذلك ، وتمنع المكالمات المتكررة.

 window.onload = function() { ... } function startGame() { if (isGameRunning) return; isGameRunning = true; addTreesRandomlyLoop(); }

أخيرًا ، حدد gameOver ، والتي ستنبه رسالة "انتهت اللعبة!" رسالة الآن.

 function startGame() { ... } function gameOver() { isGameRunning = false; alert('Game Over!'); teardownTrees(); }

هذا يختتم قسم اختبار الاصطدام في لعبة الركض اللانهائي.

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

خاتمة

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

فيما يلي موارد إضافية لعناصر تحكم وسماعات رأس VR مختلفة:

  • إطار لسماعات رأس VR
    مسح للمتصفحات وسماعات الرأس التي يدعمها A-Frame VR.
  • A- إطار لوحدات تحكم الواقع الافتراضي
    كيف لا يدعم A-Frame أي وحدات تحكم وأجهزة تحكم 3DoF ووحدات تحكم 6DoF ، بالإضافة إلى بدائل أخرى للتفاعل.

في الجزء التالي ، سنضيف بعض اللمسات النهائية ونقوم بمزامنة حالات اللعبة ، والتي تقربنا خطوة واحدة من الألعاب متعددة اللاعبين.