قررت إصدار إصدار جديد من لعبة المتصفح القديمة ، والتي كانت ناجحة على مدار عامين كتطبيق على الشبكات الاجتماعية. هذه المرة شرعت في تصميمه أيضًا كتطبيق لنظام Windows (7-8-10) ووضعه في متاجر متعددة. بالطبع ، في المستقبل يمكنك إنشاء مجموعات لنظامي MacOS و Linux.
هو مكتوب رمز اللعبة تماما في جافا سكريبت النقي. لعرض الرسومات ثلاثية الأبعاد ، يتم استخدام مكتبة three.js كحلقة وصل بين البرنامج النصي و WebGL. ومع ذلك ، كان هذا هو الحال في إصدار المتصفح القديم. كان أهم شيء في هذا المشروع بالنسبة لي هو السبب ، بالتوازي مع اللعبة ، في إضافة مكتبتي الخاصة المصممة لتكملة three.js بالأدوات اللازمة للعمل المريح مع كائنات المشهد ورسومها المتحركة والعديد من الميزات الأخرى. ثم تخلت عنها لفترة طويلة. لقد حان الوقت للعودة إليها.
تحتوي مكتبتي على أدوات ملائمة لإضافة كائنات وإزالتها من المشهد ، وتغيير خصائص الأجزاء الفردية من الكائنات (تنسجم) ، والرسوم المتحركة المستقلة عن الإطار للكائنات ثلاثية الأبعاد ، وتظليل السماء مع نسيج سماء نجمية ليلاً ، وأكثر من ذلك بكثير. سوف أخبركم عن بعضهم. فيما يتعلق بالسماء ، قمت بتنفيذ إنشائها مع وظيفة واحدة تأخذ عددًا من معلمات الإدخال ، وتهيئة التظليل ، وتحميل نسيج السحابة (إذا لزم الأمر) ، وتبدأ في تحديث السماء بتكرار معين.
ومع ذلك ، يكون كل شيء أكثر تعقيدًا قليلاً - بالنسبة للوظائف الدورية ، ولكن نادراً ما تسمى ، هناك بنية أخرى تعمل فعليًا ، وذلك باستخدام setInterval () ، حيث يمكن طرح الأحداث على فواصل زمنية مختلفة ، وستقلل كل ذلك إلى قاسم مشترك وتعمل بها إلى اليمين الوقت اللازم الأحداث في القائمة. هناك يمكنك أيضًا رمي الفاصل الزمني لتحديث السماء. لكن حركة كائنات الألعاب ثلاثية الأبعاد لمزيد من النعومة تم تنفيذها بالفعل من خلال requestAnimationFrame () ...
بما أننا نتحدث عن السماء ، سنبدأ بها.
السماء
إضافة الثابت إلى المشهد كما يلي.
تحتاج أولاً إلى إضافة الضوء القياسي three.js إلى المشهد بقيمه السطحية (الأولية) القصوى. سيتم تخزين المشهد بأكمله بأجسامه وضوءه وسماته الأخرى ، حتى لا يتم تجميع المساحة العالمية ، في مساحة اسم apscene.
بعد ذلك ، يمكنك بالفعل تشغيل الرسوم المتحركة في السماء مع تظليل ، والقوام (لعبة ورق و ... حسنا ، حسنا) من خلال واحدة من وظائفي:
m3d.graph.skydom.initWorld(
ونتيجة لذلك ، تظهر سماء ديناميكية على الساحة مع تغيير سلس في ارتفاع الشمس ، وبالتالي ، تغير في وقت اليوم.
ليس من الضروري استخدام جميع أنواع الإضاءة على المسرح. وليس من الضروري تغيير جميع المعلمات اعتمادا على الوقت من اليوم. ولكن ، مع اللعب وسطوعها ، يمكنك مع ذلك إنشاء صورة واقعية إلى حد ما لتغير النهار والليل. يمكنك تسمية المعلمات كما تريد ، الشيء الرئيسي هو مراقبة مفاتيح الأشياء بداخلها كما هي محددة في three.js.
كيف يبدو ، يمكنك مشاهدة الفيديو من المشهد التجريبي:
هذه هي لعبة مختلفة. إنه مجرد عدم تشوش الأفق بالعديد من الكائنات ، وبالتالي فإن عمل هذا البرنامج النصي هو الأكثر وضوحًا. ولكن في اللعبة التي تناقش القصة حولها ، يتم استخدام نفس الأسلوب بالضبط. يتم تعيين السرعة العالية لمرور الوقت هنا فقط لغرض العرض التوضيحي ، وبالتالي يتدفق الوقت ، بطبيعة الحال ، ببطء أكثر ، مع نفس الخطوة من التكرار بتحديث الشركة. في هذا العرض التوضيحي ، بالمناسبة ، هناك تظليل مائي ، مع وجود معلمات متغيرة ، اعتمادًا على ارتفاع الشمس ... لكنني لم أنهيها بعد.
إنتاجية
كل هذا يتطلب الكثير من الحديد. تعمل في متصفح Chrome ، حيث تقوم بتحميل Xeon E5440 تحت LGA775 (وبأربعة أجهزة من ذاكرة الوصول العشوائي) بنسبة 20٪ ، وجوهر بطاقة الرسومات GT730 بنسبة 45٪. ولكن هذا يرجع فقط إلى الرسوم المتحركة للمياه. إذا تحدثنا عن لعبة لا يوجد فيها ماء ، ولكن توجد مدينة ، فهذه واحدة:
ثم في الوقت الذي تتحرك فيه السيارة حول المدينة - 45 بالمائة ، بطاقة الفيديو 50٪. من حيث المبدأ ، مع خفض عدد إطارات في الثانية (ما يصل إلى حوالي 30 إطارًا في الثانية) ، يعمل بشكل جيد حتى على Pentium4 3GHz (1GB RAM) وعلى جهاز لوحي على Intel Atom 1.3GHz (ذاكرة وصول عشوائي 2 جيجا بايت).
كل هذه الأجهزة ضعيفة للغاية والألعاب المماثلة الأخرى على WebGL وعلى HTML5 ، وحتى في بعض الأبعاد 2D ، فهي تبطئ مني دون إلهام ، إلى الحد الذي يصبح من المستحيل تشغيلها. كما يقولون ، اكتب اللعبة بنفسك ، كما تريد ، واللعب.
مشهد
يعد المشهد ثلاثي الأبعاد في three.js كائنًا للمشهد ، بينما في الواقع ، يتم تحميل جميع النماذج ثلاثية الأبعاد في المشهد. لكي لا أسجل استدعاء محمل الإقلاع لكل نموذج ، قررت أن يتم تعيين مشهد اللعبة بالكامل في شكل تكوين معين ، مع مجموعة صفيف كبيرة مشتركة واحدة: {} (مثل بيانات الموقع) ، والتي ستحتوي على جميع الإعدادات - الأضواء ، ومسارات المواد التي تم تحميلها مسبقًا وصور للواجهة ، مسارات لجميع الطرز التي ينبغي تحميلها على المسرح ، وأكثر من ذلك. بشكل عام ، هذا هو التكوين الكامل للمشهد. يتم تعيينه مرة واحدة في ملف js للعبة ويتم تغذيته إلى أداة تحميل المشهد الخاصة بي.
وهذا locd: {} الكائن ، على وجه الخصوص ، يحتوي على مسارات النماذج ثلاثية الأبعاد الفردية التي تحتاج إلى تحميل. المسار صفر هو المسار المشترك ، ثم المسارات النسبية لكل كائن ، مثل:
['path/myObj', scale, y, x,z, r*Math.PI, 1, '', '', '', 1, ['','','',''], 'scene']
من المفهوم أن جميع الطرز يتم تصديرها من المحرر ثلاثي الأبعاد إلى تنسيق json ، أي أنها تحتوي على مسارات مثل path / myObj.json. يتبع ذلك المقياس (حيث يمكن حفظ المحرر بمقياس غير مناسب للعبة) ، وموضع الكائن في الارتفاع (ص) ، على طول المحورين (x) و (z) ، ثم زاوية الدوران للنموذج في (ص) ، وعدد من المعلمات الاختيارية و اسم المشهد حيث يتم تحميل النموذج - على المشهد الرئيسي (المشهد) أو على الخلفية (sceneb).
نعم ، كان من الضروري تنفيذ هذا ليس في شكل بسيط ، ولكن في شكل مجموعة نقابية. لذا فإن ترتيب المعلمات غير مفهوم حتى بدون الوثائق ، أو على الأقل بدون نوع الوظيفة التي تأخذ هذه المعلمات ، فلن تفهمها. أعتقد في المستقبل أنني سأعيد صياغة هذه الخطوط في المصفوفات الترابطية. في غضون ذلك ، يبدو مثل هذا:
landobj: [ ['gamePath/'], [ ['landscape/ground', 9.455, 0, 0,0, 0*Math.PI, 1, '', '', '', 1, ['','','',''], 'scene'], ['landscape/plants', 9.455, 0, 0,0, 0*Math.PI,1, '', '', '', 1, ['','','',''], 'scene'], ['landscape/buildings/house01', 2, 0, -420,420, -0.75*Math.PI, 1, '', '', '', 1, ['','','',''], 'scene'], ... ] ],
يتم تحميل هذه النماذج على المسرح وتوضع في الإحداثيات الواردة هنا في الفضاء. من حيث المبدأ ، يمكن تحميل جميع الطرز ككائن واحد ، أي يتم تصديرها من المحرر كمشهد لعبة بالكامل وتحميلها في إحداثيات (0 ؛ 0 ؛ 0). ثم سيكون هناك سطر واحد فقط: المناظر الطبيعية / الأرض - لدي ground.json - هذا هو الجزء الرئيسي من عالم اللعبة. ولكن في هذه الحالة ، سيكون من الصعب التعامل مع الكائنات الفردية للمشهد ، حيث ستحتاج إلى البحث أولاً في وحدة التحكم في المتصفح وتذكر أي من هذه الأرض الضخمة. ثم اتصل بهم بالأرقام. لذلك ، من الأفضل تحميل نماذج ألعاب التجوال بكائنات منفصلة. ثم يمكن الوصول إليهم بالاسم من المصفوفة الترابطية ، والتي سيتم إنشاؤها تلقائيًا لهذا الغرض.
قد يبدو التكوين الكامل للعبة ، على سبيل المثال ، كما يلي:
locd:{
نعم ، من الأفضل إعادة كل هذه الصفائف الفرعية إلى صفائف ترابطية ، وإلا فإن ترتيب المعلمات فيها غير واضح ...
نماذج ثلاثية الأبعاد
شيء آخر مثير للاهتمام. تحميل النماذج. تقبل مكتبتي النماذج ثلاثية الأبعاد ذات القوام وتقوم تلقائيًا بتعيين بعض المعلمات لعناصرها الفردية (الشبكات) ، اعتمادًا على الأسماء. والحقيقة هي أنه ، على سبيل المثال ، إذا تم ضبط النموذج بحيث يلقي بظلاله ، فسيتم إلقاؤه بواسطة كل شبكة مدرجة في تكوينه. ليس من الضروري دائمًا أن يلقي النموذج بالكامل ظلًا كاملاً أو يكتسب أي خصائص أخرى تؤثر بشدة على الأداء. لذلك ، إذا قمت بتشغيل إشارة معينة تشير إلى أنه من الضروري مراعاة كل شبكة على حدة ، فعند التحميل ، يكون من الممكن تحديد أي شبكة سيكون لها هذه الخاصية أو تلك وأيها لا. حسنًا ، على سبيل المثال ، ليست هناك حاجة مطلقًا لأن يتم إلقاء الظل على السقف الأفقي المسطح للمنزل أو من خلال بعض التفاصيل البسيطة غير الملائمة للنموذج على خلفية كبيرة. ومع ذلك ، لن يتمكن المشغل من رؤية هذه الظلال ، وسيتم استخدام طاقة معالج الفيديو لمعالجتها.
للقيام بذلك ، في محرر الرسومات (Blender ، Max ، إلخ) ، يمكنك على الفور تحديد أسماء الشبكات (في حقل اسم الكائن) وفقًا لقاعدة معينة. يجب أن يكون هناك تسطير سفلي (_). يجب أن تنتقل أحرف التحكم الشرطية على الجانب الأيسر ، على سبيل المثال: d - doubleside (الشبكة ثنائية الاتجاه ، وإلا - أحادية الاتجاه) ، c (ظل الظل) - تلقي ظلال ، r (تلقي الظل) - تأخذ الظلال. هذا هو ، على سبيل المثال ، قد يكون اسم شبكة الأنابيب في المنزل cr_tube. وتستخدم العديد من الرسائل الأخرى أيضا. على سبيل المثال ، "l" هو مصادم ، أي أن جدار المنزل ، الذي يحمل الاسم crl_wall01 ، لن يسمح للاعب بالمرور عبر نفسه ، وسوف يلقي ويأخذ الظل أيضًا. ليست هناك حاجة لعمل تصادم ، مثل السقف أو مقبض الباب ، وبالتالي تقليل الأداء. كما فهمت بالفعل ، عند تحميل نموذج ، تقوم مكتبتي بتوزيع أسماء الشبكات وتعطيهم الخصائص المقابلة في المشهد. ولكن لهذا من الضروري تسمية جميع الشبكات بشكل صحيح قبل تصدير النموذج من المحرر ثلاثي الأبعاد. هذا سيوفر بشكل كبير الأداء.
كل إشارات التحكم للشبكات داخل كائن:
col_ ... هو المصادم. سيتم عرض مثل هذه الشبكة ببساطة كمصادم شفاف وغير مرئي. في المحرر ، يمكنه أن يبدو مثل أي شيء ، فقط شكله مهم. على سبيل المثال ، يمكن أن يكون متوازيًا حول النموذج بأكمله ، إذا كان ضروريًا ألا يتمكن اللاعب من الانتقال إلى هذا النموذج (بناء ، حجر كبير ، وما إلى ذلك).
l_ ... هو كائن قابل للتصادم. إعطاء أي شبكة خاصية المصادم.
I_ ... - التقاطعات. ستتم إضافة الشبكة إلى قائمة التقاطعات ، والتي يمكن استخدامها ، على سبيل المثال ، للنقر عليها ، أي لإعطاء تفاعلية للعبة.
j_ ... أيضا التقاطعات. كما هو مذكور أعلاه ، فقط إصدار أحدث - مع خوارزمية محسنة للعثور على التقاطعات في اللعبة واستهلاك أقل للموارد.
ه _ ... - تقاطعات أبواب المنازل (المدخل / الخروج). يستثني التقاطع على شبكات الأجسام الأخرى. يتم استخدامه إذا كان ضروريًا في المنازل في وقت ما لجعل الأبواب فقط تفاعلية ، باستثناء جميع العناصر التفاعلية الأخرى. مع الخيال ، يمكنك التوصل إلى هذا مع الكثير من الاستخدامات الأخرى.
ج_ ... - يلقي الظلال. شبكة يلقي الظل.
r_ ... - تلقي الظلال. شبكة تقبل الظلال من جميع الشبكات الأخرى التي يلقي بهم.
d_ ... - الثنائية (مزدوجة من جانب). مرئي على كلا الجانبين ، يتم تثبيت النسيج على كلا الجانبين.
t_ ... - شفاف (شفاف) ، إذا تم تعيين الكائن بالكامل إلى alphatest في three.js.
u_ ... - شفاف (شفاف) ، بكثافة ثابتة (0.4) ، إذا لم يحدد الكائن بالكامل أبجديًا في three.js.
g_ ... - الزجاج. تم تعيين الشفافية الثابتة (0.2).
h_ ... - غير مرئية (مخفية). بالنسبة إلى أجزاء الكائن (الشبكات) التي يجب إخفاؤها عند إضافة الكائن إلى المشهد. دخلت في قائمة مخفية.
v_ ... مرئية. جميع الكائنات باستثناء تلك التي تحمل علامة "h" مرئية بالفعل ، لكن مع العلم "v" يتم إدخالها في قائمة منفصلة مرئية لمزيد من الإخفاء أو التلاعب الأخرى.
نتيجة لذلك ، قد يكون اسم الشبكة مثل هذا: crltj_box1 (القوالب ، تقبل الظل ، المصادم ، الشفافة ، التفاعلية). وشبكة أخرى كجزء من نفس النموذج: cr_box2 (فقط يلقي ويأخذ الظلال) ، وبطبيعة الحال ، يمكن تعيين أحرف التحكم في أي ترتيب. وبالتالي ، من المحرر يمكنك التحكم في العرض المستقبلي لأجزاء من الكائن في اللعبة ، أو بالأحرى ، بعض خصائصها ، مع توفير ، في نفس الوقت ، قوة الحوسبة.
جوهر اللعبة
إن المعنى ، في الواقع ، للعبة التي تدور حولها القصة ، هو التحرك في محيط الحقل المربع وشراء الشركات. يتكون الحقل في شكل شوارع ثلاثية الأبعاد. النموذج الاقتصادي للعبة يختلف اختلافًا كبيرًا عن النموذج من نوعه. في لعبتي ، عندما يبدأ شخص ما نشاطًا تجاريًا ، تنخفض أرباحك المتوقعة. والعكس بالعكس ، عندما تكتشف شيئًا ما ، تزداد. يتم إجراء جميع حسابات الأرباح والخسائر في مصلحة الضرائب في حقل البداية. يمكنك أيضًا الحصول على قرض من أحد البنوك ، والتداول في الأوراق المالية والقيام بعدد من الأشياء الأخرى. لقد قمت بتحسين سلوك الذكاء الاصطناعى مقارنة بالنسخة القديمة. أعد تصميم جميع النماذج والملمس ثلاثية الأبعاد تقريبًا والأداء الأمثل. قدمت المزيد من الإعدادات وأكثر من ذلك بكثير.
حيوية
لتحريك حركة كائنات اللعبة ، يتم استخدام محرك أبسط ، والذي مع معدل إطار معين (يقتصر على 60) يغير أي معلمات رقمية لفترة زمنية معينة ، ويمرر القيم الوسيطة إلى المعالج. وفي المعالج ، على سبيل المثال ، يتم عرض النموذج.
على سبيل المثال نحن بحاجة إلى تحريك الكائن في الفضاء من الموضع (10 ؛ 10 ؛ 50) إلى النقطة (100 ؛ 300 ؛ 60). وضعنا 3 معلمات من خلال الإشارة إلى قيمها الأولية والنهائية. ستختلف إحداثي x من 10 إلى 100 ، y - من 10 إلى 300 و z - من 50 إلى 60. وكل هذا يجب أن يحدث ، في 4 ثوانٍ.
m3d.lib.anim.add( 'moveobj', 1, 4000, 'and', {userpar1:111, obj:my3DObject}, [ {lim1:10, lim2:100, sstart:10, sfin:100, t:0}, {lim1:10, lim2:300, sstart:10, sfin:300, t:0}, {lim1:50, lim2:60, sstart:50, sfin:60, t:0} ], function(){ myPeriodicFun(this); }, function(){ myFinishFun(this); } ); m3d.lib.anim.play();
السطر الأول من 5 معلمات: moveobj - اسم الرسوم المتحركة (أي) ، رقم الدفق (يمكنك تحريك الكائنات بشكل متوازٍ في عدد غير محدود من التدفقات) ، 4000 - وقت الرسوم المتحركة 4 ثوان ، - وحتى معلمة غير مستخدمة ، والتي ستكون مسؤولة في المستقبل عن منطق الانتقال بين الرسوم المتحركة داخل نفس الدفق ، userpar هو أي صفيف ترابطي سيتم تمريره إلى المعالج كمعلمة ، على سبيل المثال ، بنصف قطر محسوب ، جيب ، جيب التمام ، وأي قيم يتم حسابها لهذه الرسوم المتحركة بشكل عام ، حتى لا يتم حسابها في عن وقت كل التكرار. أو بالإشارة إلى كائن ثلاثي الأبعاد ، والذي ، في الواقع ، سوف ينشط.
التالي هو مجموعة مع معلمات قابلة للتغيير. نجد أن المعلمة الأولى هي التغيير في إحداثي x ، والثاني هو y ، والثالث هو z. نكتب لكل في lim1 و lim2 ، من وإلى أي حجم سيتغير. في sstart و sfin نحدد نفس القيم. هنا يمكنك تحديد بداية ، على سبيل المثال ، من قيمة أخرى ، ثم "ستنتقل" المعلمة في دائرة منها إلى ، لتجاوز lim2 وبدء "ثورة" جديدة بـ lim1. حسنًا ، على سبيل المثال ، يعد هذا ضروريًا إذا تم تحريك رسومنا المتحركة بين بعض القيم (lim1 و lim2) ، لكننا نحتاج إلى بدءها ليس من البداية (أي ليس من lim1) ، ولكن من قيمة متوسطة.
يحدد t: 0 أنه يتم تنفيذ الرسوم المتحركة لهذه المعلمة مرة واحدة ، وفقًا للوقت الإجمالي (4000) ، كما لو كانت ممتدة إليها. إذا قمنا بتعيين رقم آخر ، أقل من الوقت الرئيسي ، فسيتم تكرار هذه المعلمة وسيتم تكرارها حتى وقت الحركة الرئيسية (4000). هذا مناسب ، على سبيل المثال ، لتعيين دوران الكائن عندما يجب أن تعبر الزاوية مرارًا وتكرارًا خط 360 درجة وإعادة التعيين إلى 0.
يأتي بعد ذلك ردان للاستدعاء - واحد سيتم تنفيذه مع كل تكرار والآخر سيتم تنفيذه بمجرد الانتهاء من الرسوم المتحركة بالكامل (نقطة الخروج).
رد الاتصال الأول myPeriodicFun (هذا) ، على سبيل المثال ، يمكن أن يكون مثل هذا:
myPeriodicFun:function(self) { var state=self.par[0].state, state_old=self.par[0].state_old; var state2=self.par[1].state, state_old2=self.par[1].state_old; var state3=self.par[2].state, state_old3=self.par[2].state_old; if ((state!=state_old)||(state2!=state_old2)||(state3!=state_old3)) { var obj=self.userpar.obj; obj.position.x=state; obj.position.y=state2; obj.position.z=state3; ap.cameraFollowObj(obj); }; },
أي عند كل تكرار للحركة ، يتم طرح المعلمة (self) في هذه الوظيفة التي تحتوي على القيم الوسيطة المحسوبة لجميع معلمات الحركة المعينة: self.par [0] .state ، self.par [1] .state ، self.par [2] .state. هذا هو x و y و z في الوقت الحالي. على سبيل المثال ، إذا استمرت الرسوم المتحركة لمدة 4 ثوانٍ ، فسوف تساوي بعد ثانيتين x (100-10) / 2 = 45. وهكذا بالنسبة لجميع الإحداثيات. وفقا لذلك ، في myPeriodicFun نعرض ببساطة كائننا في هذه الإحداثيات. , : , -.
f ((state!=state_old)..., , ( state_old ), , , , , - , , . state state_old , , , , . 1 , , .
بشكل عام ، يتم فهم الرسوم المتحركة كتغيير بسيط في أي عدد من المعلمات في وقت معين مع تسليم قيمها الوسيطة إلى وظيفة رد الاتصال. على سبيل المثال ، يمكنك إضافة معلمة رابعة أخرى ، والتي ستكون مسؤولة عن زاوية دوران الكائن. ويمكنك بشكل عام حشر معالم العديد من الكائنات في رسم متحرك واحد إذا كانت تتحرك بشكل موحد. يمكنك وضع الرسوم المتحركة في تدفقات مختلفة ، ثم سيتم معالجتها بالتوازي. يمكنك إضافة (m3d.lib.anim.add ()) إلى سلسلة واحدة من سلسلة كاملة من الرسوم المتحركة ، وسيتم تنفيذها واحدة تلو الأخرى. علاوة على ذلك ، سيكون لكل موضوع تسلسل مستقل خاص به. الشيء الرئيسي هو أن النظام لديه طاقة كافية وأن كل شيء لا يتحول إلى عرض شرائح.ملاحظة: التدفقات هنا تتحقق ببساطة عن طريق التعداد المتتالي في كل تكرار لجميع الرسوم المتحركة المتوازية وحساب لكل منهم من القيم المتوسطة لجميع المعلمات الخاصة بهم. وهذا هو ، لا يوجد تعدد حقيقي في جافا سكريبت.يمكن أيضًا استخدام نفس "المحرك" لتحريك عناصر الواجهة عن طريق تعيينها لتغيير إحداثيتين على مستوى الشاشة وعرض هذه العناصر في وظائف رد الاتصال وفقًا للقيم الوسيطة التي تم الحصول عليها. الذي ، في الواقع ، يتم في لعبتي.الظلال الديناميكية
تبين أن عرض الظلال في جميع أنحاء المشهد كان مضيعة لدرجة أنه عندما تم تشغيلها ، انخفض إطار الصورة في الثانية عدة مرات. هذا ليس جيد. سوف نعرض الظلال من الكائنات في مربع صغير معين حول اللاعب. سأقول على الفور أن مثل هذه التقنية تزيد بشكل كبير من معدل الإطار.لا شيء معقد هنا. يتم إلقاء الظلال Three.js داخل كاميرا ظل معينة محددة بواسطة المربع (shadowCameraLeft ، shadowCameraRight ، shadowCameraTop ، shadowCameraBottom). يمكن تمديده إلى المشهد بأكمله ، أو يمكن صنعه بحيث يتبع الكاميرا الرئيسية ولا يتم الظلال إلا حوله. الشيء الوحيد الذي أضفته إلى هذا النظام هو الخطوة التي سيتم من خلالها تحديث الظلال. ليست هناك حاجة على الإطلاق للقيام بهذا التحديث في كل مرة يقوم فيها اللاعب بالوخز ، حيث يقوم هذا بتحميل النظام بالحسابات. دعه يتغلب على مسافة دنيا معينة على طول أي من المحاور الثلاثة بحيث يتم تحديث الظل.3D contr, . contr.cameraForShadowStep, , .
, , 700x700x700, contr.cameraForShadowStep , , 20. 20 , . 3D , , 3D . , 700x700x700 20, 7000x7000x7000 200. .
بالمناسبة ، عندما تتحرك الشمس في السماء ، يتم تحديث الظلال بشكل مستقل عن هذا النظام ، حيث يجب أن يتغير اتجاه الظلال هناك. أي ، سيتم تحديثها حتى إذا كان اللاعب يقف دون حركة. هناك ، يتم استدعاء وظيفة تحديث الظلال وفقًا لفترة تحديث السماء بصراحة.نظام نقطة الضوء
إن وجود أكثر من عشرة مصادر للضوء على المسرح قوي بالثانية في الثانية مثل الظلال الديناميكية. وحتى يجعل من المستحيل لعب "القنب" القديم. علاوة على ذلك ، لا يهم إذا كانت هذه المصادر في مجال رؤية اللاعب (يمكن تعيين نطاق عرض العالم) أو على مسافة كبيرة. إذا كانوا موجودين بغباء على المسرح ، فإن كل شيء يعمل ببطء. لذلك ، لقد قدمت في قائمة الإعدادات للعبة ، والتي يمكن تسميتها قبل تحميل العالم ثلاثي الأبعاد ، خيارات لعدد هذه المصادر (2 ، 4 أو 8) تسمى "Light of Lanterns".وبالتالي ، في الليل ، لن يعمل تشغيل جميع الأنوار الموضوعة على المسرح في نفس الوقت. أعلاه ، في وصف مخطط التهيئة العالمي ، قدمت صفائف userPointLights و lightsPDynamicAr. في userPointLights ، يتم تعيين إحداثيات جميع مصابيح المصباح على المسرح في صفيف. و lightsPDynamicAr يحتوي على إعدادات الإضاءة لجميع الحالات 8. بناءً على إعداد عدد الأضواء ، ستأخذ المكتبة أولها وتضيفها إلى المشهد في مجال رؤية المشغل.في الواقع ، أثناء تحرك اللاعب ، يتم البحث عن 2-8 فوانيس الأقرب إلى اللاعب من خلال مجموعة من إحداثيات الفوانيس userPointLights. ونقطة مصادر الضوء تتحرك تحتها. بمعنى آخر ، مصابيح الإضاءة من 2-8 تتبع اللاعب المحيط به. علاوة على ذلك ، يتم ذلك أيضًا ليس مع كل إطار من إطارات fps ، ولكن مع خطوة معينة. ليست هناك حاجة مطلقًا لبدء تشغيل وظيفة البحث 60 مرة في الثانية ، خاصة إذا كان اللاعب لا يتحرك - ثم اترك الأضواء الموجودة من حوله تحترق.هكذا يبدو في الحركة (Xeon E5440 ، GeForce GT730):بناء التوزيع
( ), bat-, Google Closure Compiler *.js . nwjc.exe nw.js — js (*.bin). :
java -jar D:\webservers\Closure\compiler.jar --js D:\webservers\proj\m3d\www\game\bus\bus.js --js_output_file D:\webservers\proj\nwProjects\bus\game\bus\bus.js
cd D:\«Program Files»\Web2Exe\down\nwjs-sdk-v0.35.5-win-ia32
D:\«Program Files»\Web2Exe\down\nwjs-sdk-v0.35.5-win-ia32\nwjc.exe D:\webservers\proj\nwProjects\bus\game\bus\bus.js D:\webservers\proj\nwProjects\bus\game\bus\bus.bin
del D:\webservers\proj\nwProjects\bus\game\bus\bus.js
بعد ذلك ، استخدم الأداة المساعدة Web2Executable البسيطة لإنشاء ملف exe مع التجميع تحت Windows. لقد اخترت nw.js الإصدار 0.35.5 ، على الرغم من توفر الإصدارات الأحدث أيضًا. لم ألاحظ أي تأثير منها ، باستثناء زيادة حجم التجمع.الأداة المساعدة قادرة على تنزيل الإصدار المحدد من nw.js إلى المجلد المحدد نفسه. الإخراج هو التجمع. يحتوي الملف القابل للتنفيذ من 35 ميغابايت ، في الواقع ، اللعبة نفسها. كل شيء آخر هو العقدة webkit. يحتوي مجلد الإعدادات المحلية على ملفات ، بوضوح ، مع بعض الموارد بلغات مختلفة. قمت بحذفها وتركت فقط تلك المتعلقة باللغة الإنجليزية. بالمناسبة ، لم يمنع هذا إطلاق إصدار اللغة الروسية من اللعبة (في اللعبة ، تتحول اللغة بين الروسية والإنجليزية). لماذا كل هذه الملفات إذن ، أنا لا أعرف. لكن بدون اللغة الإنجليزية ، لا شيء يبدأ.استغرق التجميع بأكمله في نهاية المطاف 167 ميغابايت.ثم حزمت كل شيء في ملف توزيع واحد قابل للتنفيذ باستخدام إحدى الأدوات المساعدة المجانية المصممة لهذا الغرض ، وكان الإخراج 70.2 ميغابايت Businessman3DSetup.exe.منشور
لقد أرسلت التجميع إلى متاجر تطبيقات مختلفة. معظمهم ما زالوا في طور الإشراف على لعبتي. في الوقت الحالي ، نشرته حكة فقط حتى الآن. أحذرك على الفور ، اللعبة مدفوعة الثمن ، السعر 3 دولارات. لا توجد مشتريات بعد ، لكنني لم أشارك بعد في الترويج لها. رفض GOG للنشر ، مستشهداً بحقيقة أن اللعبة بسيطة للغاية ومتخصصة. أنا ، من حيث المبدأ ، أوافق. Epic Store ، في اعتقادي ، سوف يفعل الشيء نفسه.الإصدار المنشور من اللعبة هو مستخدم واحد ، مع روبوتات مقدارها من 1 إلى 5. اللغة - الروسية والإنجليزية. أنوي الانتهاء من إصدار الشبكة. ولكن أثناء التفكير - لإصداره في شكل نفس التطبيق أو في شكل إصدار مستعرض ويب متاح على الفور في Windows و Linux و iOs و MacOs ، وعمومًا حيثما يدعم المستعرض WebGL. في الواقع ، في الواقع ، webkit هو متصفح واللعبة تعمل بشكل جيد فيه ، في Firefox و Edge و IE11 في Windows ، رغم أنها بطيئة للغاية.النتائج
أعتقد أنني لست مستعدًا بعد لوضع محركي للاستخدام العام ، لأنه لم ينته بعد. سأقوم أولاً بكتابة لعبة أخرى عليها ، فقط تلك من الفيديو التوضيحي عن السفن ، لأنه في تلك اللعبة يمكنك "المرور" في العمل باستخدام تظليل المياه. بالإضافة إلى ذلك ، أخطط لتنفيذ محرك الفيزياء بسيط هناك. نعم ، وما زلت بحاجة إلى الانتهاء من جميع الميزات الأخرى ، وإصلاح جميع العيوب. ومن الأفضل القيام بذلك في لعبتين بدلاً من واحدة ، لأن بعض الفروق الدقيقة ممكنة. في غضون ذلك ، محركي ، في رأيي ، لا يزال شحذًا كبيرًا في لعبة واحدة.بالإضافة إلى ذلك ، لست متأكدًا على الإطلاق من أن أي شخص يحتاج إلى كل هذا. إذا نظرت بوقاحة ، فلن يكتب أحد بألعاب جافا سكريبت خالصة. لكنني أحب ذلك لأن الألعاب سهلة وسريعة بالنسبة للمتصفح. يتم تحميلها بسرعة ، ولا تتطلب الكثير من ذاكرة الوصول العشوائي وتعمل بسرعة كبيرة مقارنةً بالمنافسين في html5 ، حتى عند مقارنتها مع ثنائي الأبعاد. أعتقد أنني سأصدر أكثر من لعبة متصفح (وليس فقط) في كل هذه التطورات.