ما الذي تحتاج إلى معرفته عند تحويل لعبة فلاش إلى HTML5؟
نشرت: 2022-03-10مع تزايد استخدام HTML5 ، بدأت العديد من الشركات في إعادة عناوينها الأكثر شيوعًا للتخلص من الفلاش القديم ومطابقة منتجاتها مع أحدث معايير الصناعة. هذا التغيير مرئي بشكل خاص في صناعات القمار / الكازينو والترفيه وقد حدث منذ عدة سنوات حتى الآن ، لذلك تم بالفعل تحويل مجموعة مختارة مناسبة من العناوين.
لسوء الحظ ، عند تصفح الإنترنت ، يمكنك في كثير من الأحيان العثور على أمثلة لوظيفة تبدو متسرعة ، مما يؤدي إلى جودة المنتج النهائي. هذا هو السبب في أنها فكرة جيدة لمطوري الألعاب أن يكرسوا بعضًا من وقتهم للتعرف على موضوع تحويل Flash إلى HTML5 وتعلم الأخطاء التي يجب تجنبها قبل الشروع في العمل.
من بين أسباب اختيار JavaScript بدلاً من Flash ، بصرف النظر عن المشكلات التقنية الواضحة ، حقيقة أن تغيير تصميم لعبتك من SWF إلى JavaScript يمكن أن ينتج عنه تجربة مستخدم أفضل ، والتي بدورها تمنحها مظهرًا عصريًا. ولكن كيف نفعل ذلك؟ هل تحتاج إلى محول ألعاب JavaScript مخصص للتخلص من هذه التكنولوجيا القديمة؟ حسنًا ، يمكن أن يكون تحويل Flash إلى HTML5 أمرًا رائعًا - وإليك كيفية العناية به.
يوصى بالقراءة : مبادئ تصميم ألعاب HTML5
كيفية تحسين تجربة لعبة HTML5
يعد تحويل لعبة إلى منصة أخرى فرصة ممتازة لتحسينها وإصلاح مشكلاتها وزيادة الجمهور. فيما يلي بعض الأشياء التي يمكن القيام بها بسهولة وتستحق التفكير فيها:
دعم الأجهزة المحمولة
يسمح التحويل من Flash إلى JavaScript بالوصول إلى جمهور أوسع (مستخدمي الأجهزة المحمولة) ؛ عادةً ما يلزم تطبيق دعم عناصر التحكم في الشاشة التي تعمل باللمس في اللعبة أيضًا. لحسن الحظ ، تدعم كل من أجهزة Android و iOS الآن WebGL ، لذلك يمكن عادةً تحقيق عرض 30 أو 60 إطارًا في الثانية بسهولة. في كثير من الحالات ، لن يتسبب 60 إطارًا في الثانية في حدوث أي مشكلات ، والتي ستتحسن بمرور الوقت فقط ، حيث تصبح الأجهزة المحمولة أكثر أداءً.- تحسين الأداء
عندما يتعلق الأمر بمقارنة ActionScript و JavaScript ، فإن الأخير أسرع من الأول. بخلاف ذلك ، يعد تحويل اللعبة مناسبة جيدة لإعادة النظر في الخوارزميات المستخدمة في كود اللعبة. مع تطوير لعبة JavaScript ، يمكنك تحسينها أو إزالة الكود غير المستخدم تمامًا الذي تركه المطورون الأصليون. - إصلاح الخلل وإدخال تحسينات على طريقة اللعب
يمكن أن يساعد وجود مطورين جدد يبحثون في التعليمات البرمجية المصدر للعبة في إصلاح الأخطاء المعروفة أو اكتشاف أخطاء جديدة ونادرة جدًا. سيؤدي ذلك إلى جعل ممارسة اللعبة أقل إزعاجًا للاعبين ، مما يجعلهم يقضون وقتًا أطول على موقعك ويشجعهم على تجربة ألعابك الأخرى. - إضافة تحليلات الويب
بالإضافة إلى تتبع حركة المرور ، يمكن أيضًا استخدام تحليلات الويب لجمع المعرفة حول كيفية تصرف اللاعبين في اللعبة ومكان توقفهم أثناء اللعب. - مضيفا الترجمة
سيؤدي هذا إلى زيادة الجمهور وهو مهم للأطفال من البلدان الأخرى الذين يلعبون لعبتك. أو ربما لعبتك ليست باللغة الإنجليزية وتريد دعم هذه اللغة؟
لماذا سيؤدي تخطي HTML و CSS لواجهة المستخدم داخل اللعبة إلى تحسين أداء اللعبة
عندما يتعلق الأمر بتطوير ألعاب JavaScript ، فقد يكون من المغري الاستفادة من HTML و CSS للأزرار داخل اللعبة والأدوات وعناصر واجهة المستخدم الرسومية الأخرى. نصيحتي هي توخي الحذر هنا. إنه أمر غير بديهي ، ولكن الاستفادة من عناصر DOM أقل أداءً في الألعاب المعقدة وهذا يكتسب أهمية أكبر على الهاتف المحمول. إذا كنت ترغب في تحقيق 60 إطارًا في الثانية ثابتًا على جميع الأنظمة الأساسية ، فقد يلزم الاستقالة من HTML و CSS.
يمكن تنفيذ عناصر واجهة المستخدم الرسومية غير التفاعلية ، مثل أشرطة الصحة ، أو أشرطة الذخيرة ، أو عدادات النقاط بسهولة في Phaser باستخدام الصور العادية (فئة Phaser.Image
) ، والاستفادة من خاصية .crop
Phaser.Text
تسميات النص.
يمكن تنفيذ عناصر تفاعلية مثل الأزرار ومربعات الاختيار باستخدام فئة Phaser.Button
. يمكن أن تتكون العناصر الأخرى الأكثر تعقيدًا من أنواع بسيطة مختلفة ، مثل المجموعات والصور والأزرار والتسميات النصية.
ملاحظة: في كل مرة تقوم فيها بإنشاء مثيل Phaser.Text أو كائن PIXI.Text ، يتم إنشاء مادة جديدة لعرض النص عليها. يكسر هذا النسيج الإضافي تجميعات الرأس ، لذا احرص على عدم وجود الكثير منها .
كيفية التأكد من تحميل الخطوط المخصصة
إذا كنت تريد عرض نص بخط متجه مخصص (مثل TTF أو OTF) ، فأنت بحاجة إلى التأكد من أن المتصفح قد تم تحميله بالفعل قبل عرض أي نص. لا يوفر Phaser v2 حلاً لهذا الغرض ، ولكن يمكن استخدام مكتبة أخرى: Web Font Loader.
بافتراض أن لديك ملف خط وتضمين Web Font Loader في صفحتك ، فيما يلي مثال بسيط على كيفية تحميل خط:
قم بإنشاء ملف CSS بسيط سيتم تحميله بواسطة Web Font Loader (لست بحاجة إلى تضمينه في HTML الخاص بك):
@font-face { // This name you will use in JS font-family: 'Gunplay'; // URL to the font file, can be relative or absolute src: url('../fonts/gunplay.ttf') format('truetype'); font-weight: 400; }
حدد الآن متغيرًا عامًا باسم WebFontConfig
. عادة ما يكفي شيء بسيط مثل هذا:
var WebFontConfig = { 'classes': false, 'timeout': 0, 'active': function() { // The font has successfully loaded... }, 'custom': { 'families': ['Gunplay'], // URL to the previously mentioned CSS 'urls': ['styles/fonts.css'] } };
في النهاية ، تذكر أن تضع الكود الخاص بك في رد الاتصال "النشط" الموضح أعلاه. وهذا كل شيء!
كيفية تسهيل حفظ اللعبة على المستخدمين
لتخزين البيانات المحلية باستمرار في ActionScript ، يمكنك استخدام فئة SharedObject. في JavaScript ، البديل البسيط هو localStorage API ، والذي يسمح بتخزين السلاسل لاسترجاعها لاحقًا ، وبقاء عمليات إعادة تحميل الصفحة.
حفظ البيانات بسيط للغاية:
var progress = 15; localStorage.setItem('myGame.progress', progress);
لاحظ أنه في المثال أعلاه ، سيتم تحويل متغير progress
، وهو رقم ، إلى سلسلة.
التحميل بسيط أيضًا ، ولكن تذكر أن القيم المستردة ستكون سلاسل أو null
إذا لم تكن موجودة.
var progress = parseInt(localStorage.getItem('myGame.progress')) || 0;
نحن هنا نضمن أن القيمة المعادة هي رقم. إذا لم يكن موجودًا ، فسيتم تخصيص 0 لمتغير progress
.
يمكنك أيضًا تخزين واسترداد هياكل أكثر تعقيدًا ، على سبيل المثال ، JSON:
var stats = {'goals': 13, 'wins': 7, 'losses': 3, 'draws': 1}; localStorage.setItem('myGame.stats', JSON.stringify(stats)); … var stats = JSON.parse(localStorage.getItem('myGame.stats')) || {};
هناك بعض الحالات التي لا يتوفر فيها كائن localStorage. على سبيل المثال ، عند استخدام file://
protocol أو عند تحميل صفحة في نافذة خاصة. يمكنك استخدام عبارة try and catch للتأكد من أن الكود الخاص بك سيستمر في العمل ويستخدم القيم الافتراضية ، كما هو موضح في المثال أدناه:
try { var progress = localStorage.getItem('myGame.progress'); } catch (exception) { // localStorage not available, use default values }
شيء آخر يجب تذكره هو أن البيانات المخزنة يتم حفظها لكل مجال وليس لكل عنوان URL. لذلك إذا كان هناك خطر يتمثل في استضافة العديد من الألعاب على مجال واحد ، فمن الأفضل استخدام بادئة (مساحة الاسم) عند الحفظ. في المثال أعلاه 'myGame.'
هي مثل هذه البادئة وتريد عادةً استبدالها باسم اللعبة.
ملاحظة : إذا كانت لعبتك مضمنة في إطار iframe ، فلن يستمر تطبيق localStorage في نظام التشغيل iOS. في هذه الحالة ، ستحتاج إلى تخزين البيانات في إطار iframe الأصلي بدلاً من ذلك .
كيفية الاستفادة من استبدال شادر جزء الافتراضي
عندما يعرض Phaser و PixiJS النقوش المتحركة الخاصة بك ، فإنهم يستخدمون تظليل شظي داخلي بسيط. لا يحتوي على العديد من الميزات لأنه مصمم خصيصًا للسرعة. ومع ذلك ، يمكنك استبدال هذا التظليل لأغراضك. على سبيل المثال ، يمكنك الاستفادة منه لفحص السحب الزائد أو دعم المزيد من الميزات للعرض.
فيما يلي مثال على كيفية توفير تظليل الأجزاء الافتراضي الخاص بك إلى Phaser v2:
function preload() { this.load.shader('filename.frag', 'shaders/filename.frag'); } function create() { var renderer = this.renderer; var batch = renderer.spriteBatch; batch.defaultShader = new PIXI.AbstractFilter(this.cache.getShader('filename.frag')); batch.setContext(renderer.gl); }
ملاحظة: من المهم أن تتذكر أنه يتم استخدام التظليل الافتراضي لجميع النقوش المتحركة وكذلك عند التقديم إلى مادة. أيضًا ، ضع في اعتبارك أن استخدام تظليلات معقدة لجميع الكائنات المتحركة داخل اللعبة سيقلل بشكل كبير من أداء العرض .
كيفية تغيير طريقة الصبغ باستخدام تظليل افتراضي
يمكن استخدام تظليل افتراضي مخصص لاستبدال طريقة التلوين الافتراضية في Phaser و PixiJS.
يعمل التلوين في Phaser و PixiJS بضرب بكسلات النسيج في لون معين. يؤدي الضرب دائمًا إلى تغميق الألوان ، ومن الواضح أنه لا يمثل مشكلة ؛ إنه يختلف ببساطة عن تلوين الفلاش. بالنسبة لإحدى ألعابنا ، احتجنا إلى تطبيق صبغ مشابه لـ Flash وقررنا أنه يمكن استخدام تظليل افتراضي مخصص. فيما يلي مثال على هذا التظليل الجزئي:
// Specific tint variant, similar to the Flash tinting that adds // to the color and does not multiply. A negative of a color // must be supplied for this shader to work properly, ie set // sprite.tint to 0 to turn whole sprite to white. precision lowp float; varying vec2 vTextureCoord; varying vec4 vColor; uniform sampler2D uSampler; void main(void) { vec4 f = texture2D(uSampler, vTextureCoord); float a = clamp(vColor.a, 0.00001, 1.0); gl_FragColor.rgb = f.rgb * vColor.a + clamp(1.0 - vColor.rgb/a, 0.0, 1.0) * vColor.a * fa; gl_FragColor.a = fa * vColor.a; }
يعمل هذا التظليل على تفتيح البكسل عن طريق إضافة لون أساسي إلى اللون الخفيف. لكي يعمل هذا ، تحتاج إلى توفير اللون السلبي الذي تريده. لذلك ، من أجل الحصول على اللون الأبيض ، تحتاج إلى ضبط:
sprite.tint = 0x000000; // This colors the sprite to white Sprite.tint = 0x00ffff; // This gives red
تبدو النتيجة في لعبتنا على النحو التالي (لاحظ كيف تومض الدبابات باللون الأبيض عند ضربها):
كيفية فحص السحب الزائد لاكتشاف مشاكل معدل التعبئة
يمكن أيضًا الاستفادة من استبدال التظليل الافتراضي للمساعدة في تصحيح الأخطاء. لقد أوضحت أدناه كيف يمكن اكتشاف السحب الزائد باستخدام مثل هذا التظليل.
يحدث الرسم الزائد عندما يتم عرض العديد من وحدات البكسل أو جميعها على الشاشة عدة مرات. على سبيل المثال ، تأخذ العديد من الكائنات نفس المكان ويتم عرضها على بعضها البعض. يتم وصف عدد وحدات البكسل التي يمكن أن تعرضها وحدة معالجة الرسومات في الثانية على أنها معدل التعبئة. تتميز وحدات معالجة الرسومات الحديثة لسطح المكتب بمعدل تعبئة مفرط للأغراض ثنائية الأبعاد المعتادة ، ولكن الأجهزة المحمولة أبطأ كثيرًا.
هناك طريقة بسيطة لمعرفة عدد المرات التي تتم فيها كتابة كل بكسل على الشاشة عن طريق استبدال تظليل الأجزاء العام الافتراضي في PixiJS و Phaser بهذا:
void main(void) { gl_FragColor.rgb += 1.0 / 7.0; }
يعمل هذا التظليل على تفتيح وحدات البكسل التي تتم معالجتها. يشير الرقم 7.0 إلى عدد عمليات الكتابة المطلوبة لتحويل البكسل إلى اللون الأبيض ؛ يمكنك ضبط هذا الرقم حسب رغبتك. بمعنى آخر ، تمت كتابة وحدات البكسل الأفتح على الشاشة عدة مرات ، وكُتبت وحدات البكسل البيضاء 7 مرات على الأقل.
يساعد هذا التظليل أيضًا في العثور على كل من الكائنات "غير المرئية" التي لا تزال تُعرض لسبب ما والعفاريت التي تحتوي على مناطق شفافة مفرطة حولها بحاجة إلى التجريد (لا تزال وحدة معالجة الرسومات بحاجة إلى معالجة وحدات البكسل الشفافة في الأنسجة الخاصة بك).
تُظهر الصورة الموجودة على اليسار كيف يرى اللاعب اللعبة ، بينما تعرض الصورة الموجودة على اليمين تأثير تطبيق تظليل overdraw على نفس المشهد.
لماذا محركات الفيزياء هم أصدقاؤك
محرك الفيزياء هو برنامج وسيط مسؤول عن محاكاة الأجسام الفيزيائية (عادة ديناميكيات الجسم الجامدة) واصطداماتها. تحاكي محركات الفيزياء مسافات ثنائية أو ثلاثية الأبعاد ، ولكن ليس كلاهما. سيوفر محرك الفيزياء النموذجي:
- حركة الجسم عن طريق ضبط السرعات والتسارع والمفاصل والمحركات ؛
- كشف الاصطدامات بين أنواع الأشكال المختلفة ؛
- حساب استجابات الاصطدام ، أي كيف يجب أن يتفاعل جسمان عندما يصطدمان.
في Merixstudio ، نحن من أشد المعجبين بمحرك الفيزياء Box2D واستخدمناه في مناسبات قليلة. هناك مكون إضافي Phaser يعمل بشكل جيد لهذا الغرض. يستخدم Box2D أيضًا في محرك لعبة Unity و GameMaker Studio 2.
بينما يعمل محرك الفيزياء على تسريع عملية التطوير الخاصة بك ، هناك ثمن يتعين عليك دفعه: انخفاض أداء وقت التشغيل. يعد اكتشاف التصادمات وحساب الاستجابات مهمة تتطلب الكثير من وحدة المعالجة المركزية. قد تكون مقيدًا بالعشرات من الكائنات الديناميكية في مشهد على الهواتف المحمولة أو تواجه أداءً متدهورًا ، بالإضافة إلى معدل إطارات مخفض بعمق أقل من 60 إطارًا في الثانية.
الجزء الأيسر من الصورة عبارة عن مشهد من لعبة ، بينما يُظهر الجانب الأيمن نفس المشهد مع عرض تراكب تصحيح فيزياء Phaser في الأعلى.
كيفية تصدير الأصوات من ملف .fla
إذا كان لديك مؤثرات صوتية لألعاب Flash داخل ملف .fla ، فلن يكون من الممكن تصديرها من واجهة المستخدم الرسومية (على الأقل ليس في Adobe Animate CC 2017) نظرًا لعدم وجود خيار قائمة يخدم هذا الغرض. ولكن هناك حل آخر - نص مخصص يفعل ذلك بالضبط:
function normalizeFilename(name) { // Converts a camelCase name to snake_case name return name.replace(/([AZ])/g, '_$1').replace(/^_/, '').toLowerCase(); } function displayPath(path) { // Makes the file path more readable return unescape(path).replace('file:///', '').replace('|', ':'); } fl.outputPanel.clear(); if (fl.getDocumentDOM().library.getSelectedItems().length > 0) // Get only selected items var library = fl.getDocumentDOM().library.getSelectedItems(); else // Get all items var library = fl.getDocumentDOM().library.items; // Ask user for the export destination directory var root = fl.browseForFolderURL('Select a folder.'); var errors = 0; for (var i = 0; i < library.length; i++) { var item = library[i]; if (item.itemType !== 'sound') continue; var path = root + '/'; if (item.originalCompressionType === 'RAW') path += normalizeFilename(item.name.split('.')[0]) + '.wav'; else path += normalizeFilename(item.name); var success = item.exportToFile(path); if (!success) errors += 1; fl.trace(displayPath(path) + ': ' + (success ? 'OK' : 'Error')); } fl.trace(errors + ' error(s)');
كيفية استخدام البرنامج النصي لتصدير ملفات الصوت:
- احفظ الكود أعلاه كملف .jsfl على جهاز الكمبيوتر الخاص بك ؛
- افتح ملف .fla باستخدام Adobe Animate ؛
- حدد "الأوامر" ← "تشغيل الأمر" من القائمة العلوية وحدد البرنامج النصي في الحوار الذي يفتح ؛
- يظهر الآن ملف حوار آخر لتحديد دليل وجهة التصدير.
وفعلت! يجب أن يكون لديك الآن ملفات WAV في الدليل المحدد. ما تبقى فعله هو تحويلها ، على سبيل المثال ، إلى MP3 أو OGG أو AAC.
كيفية استخدام ملفات MP3 في فلاش لتحويلات HTML5
عاد تنسيق MP3 القديم الجيد ، حيث انتهت صلاحية بعض براءات الاختراع وأصبح بإمكان كل متصفح الآن فك تشفير ملفات MP3 وتشغيلها. هذا يجعل التطوير أسهل قليلاً لأنه في النهاية ليست هناك حاجة لإعداد تنسيقين صوتيين منفصلين. في السابق كنت بحاجة ، على سبيل المثال ، إلى ملفات OGG و AAC ، بينما الآن سيكفي تنسيق MP3.
ومع ذلك ، هناك شيئان مهمان عليك تذكرهما حول MP3:
- تحتاج ملفات MP3 إلى فك تشفيرها بعد التحميل ، وهو ما يمكن أن يستغرق وقتًا طويلاً ، خاصة على الأجهزة المحمولة. إذا رأيت توقفًا مؤقتًا بعد تحميل جميع أصولك ، فربما يعني ذلك أنه تم فك تشفير MP3 ؛
- يعد تشغيل ملفات MP3 ذات حلقات بدون فجوات مشكلة بعض الشيء. الحل هو استخدام mp3loop ، والذي يمكنك أن تقرأ عنه في المقال المنشور بواسطة Compu Phase.
لذا ، لماذا يجب عليك تحويل Flash إلى JavaScript؟
كما ترى ، فإن تحويل Flash إلى JavaScript ليس مستحيلًا إذا كنت تعرف ما يجب القيام به. بالمعرفة والمهارة ، يمكنك التوقف عن المعاناة مع Flash والاستمتاع بالألعاب السلسة والمسلية التي تم إنشاؤها في JavaScript. لا تحاول إصلاح Flash - تخلص منه قبل أن يضطر الجميع إلى القيام بذلك!
تريد معرفة المزيد؟
في هذه المقالة ، كنت أركز بشكل أساسي على Phaser v2. ومع ذلك ، يتوفر الآن إصدار أحدث من Phaser ، وأنا أشجعك بشدة على التحقق من ذلك ، حيث قدم عددًا كبيرًا من الميزات الجديدة والرائعة ، مثل الكاميرات المتعددة أو المشاهد أو خرائط التيلمب أو محرك الفيزياء Matter.js.
إذا كنت شجاعًا بما يكفي وترغب في إنشاء أشياء رائعة حقًا في المتصفحات ، فإن WebGL هو الشيء الصحيح للتعلم من الألف إلى الياء. إنه مستوى تجريد أقل من أطر أو أدوات بناء الألعاب المختلفة ولكنه يسمح بتحقيق أداء وجودة أفضل حتى إذا كنت تعمل على ألعاب ثنائية الأبعاد أو عروض توضيحية. من بين العديد من مواقع الويب التي قد تجدها مفيدة عند تعلم أساسيات WebGL هي WebGL Fundamentals (تستخدم العروض التوضيحية التفاعلية). بالإضافة إلى ذلك ، لمعرفة المزيد حول معدلات اعتماد ميزة WebGL ، تحقق من إحصائيات WebGL.
تذكر دائمًا أنه لا يوجد شيء مثل المعرفة الزائدة - خاصة عندما يتعلق الأمر بتطوير اللعبة!