مدونة سلوان الهلالي

تطوير ألعاب - برمجة - علم نفس

محرك ألعاب إنكيدو 2

السلام عليكم،   لقد سألني أمس أحد الأصدقاء في الجامعة ماذا أفعل بالضبط؟ لأنه يسمع دائماً أني مشغول ولدي عمل كثير، لم استطع أن أجيبه بشكل مباشر، ولم أعرف كيف أجيب، ماذا كنت أفعل بالضبط خلال السنة الماضية وحتى الآن؟   قبل ما يقارب 8 أشهر، قررت الدخول في مجال تطوير الألعاب المستقلة والألعاب الخفيفة (casual) التجارية، وقد بدأت منذ تلك اللحظة وحتى الآن سباقاً مع الزمن للوصول لأنسب تقنية أستطيع استخدامها لبناء الألعاب مع الاحتفاظ بالمرونة الكافية لتنفيذ الأفكار الغير تقليدية، وقد اعطيت نفسي مهلة تنتهي بعد سنة تقريباً لكي أصدر أول لعبة لي، وهي أعتقد مهلة كافية. في الشهور الأولى، بحثت ونقبت في الانترنت عن محرك ألعاب كامل مجاني يتيح المنتجات التجارية استطيع استخدامه لعمل ألعابي ولكني لم أعثر على ضالتي، جميع المحركات المعروفة إما تكون محركات رسوميات فقط وذلك ليس ما أبحث عنه، أو تكون محركات لا تصل للمستوى المطلوب.   ولكن في نفس الوقت، بدأت ببناء المحرك الذي أبحث عنه ولم اعثر عليه، وقد اسميته إطار عمل إنكيدو، وهو محرك موجه لصناعة الألعاب ثنائية الأبعاد، يستند إنكيدو على مكتبة مفتوحة المصدر تسمى ClanLib وهي مكتبة نظام متكاملة موجهة للألعاب ومتعددة المنصات، تتضمن نظام GUI كامل، مكتبة شبكات موجهة للألعاب، مكتبة صوتية، نظام Signal/Slot لتوزيع الأحداث،... وأشياء كثيرة أخرى، وقد شاركني في العمل الصديق العزيز أحمد عز. عندما بدأت العمل كانت مكتبة ClanLib في الإصدارة 0.8 وكان هنالك الإصدارة 0.9 أيضاً ولكنها كانت تجريبية وغير كاملة في وقتها. بعد شهرين من العمل وصل محرك إنكيدو لشكل إعتقدته جيد، أضفت له مزايا مثل إمكانية تحميل الملفات -خاصة ملفات الإكساء- في الخلفية (secondary thread) لكي لا تقاطع سلاسة اللعبة، وهي الميزة التي شكلت أكبر تحدّي لي في تلك الفترة. بعد ذلك وبشكل مفاجئ غير متوقع تم اصدار النسخة 2.0 من مكتبة ClanLib، وقد احتوت على مزايا جميلة مثل الدخول لقواعد البيانات ونظام عرض ثلاثي الأبعاد متكامل مستند على OpenGL ويستخدم مظللات GLSL، وهذه مزايا كنت أخطط إضافتها مستقبلاً، لذلك لم يكن لدي خيار إلا التحويل لـ ClanLib2، وجدت لسوء الحظ إن جزءاً كبيراً من إنكيدو يجب إعادة كتابته، لأن ClanLib2 يختلف كثيراً، كذلك فوجئت عندما اكتشفت أنهم قرروا إلغاء نظام الموارد (Resource System) الذي كان موجوداً في النسخة الأولى والذي يستند عليه نظام إدارة الموارد في إنكيدو، وبالتالي إضطررت لإلغاء نظام إدارة إنكيدو بالكامل أيضاً. بسبب الإعتمادية الكبيرة على ClanLib القديم أصبح إنكيدو فجأة لا يصلح لشيء، في النهاية شطبته بالكامل وقررت إعادة كتابته بطريقة أفضل، احتفظت بالنسخة القديمة واسميت النسخة الجديدة Enkido2.   بعد ذلك توقفت عن العمل لما يقارب 4 شهور بسبب الامتحانات وبسبب إنضمامي لشركة TimeLine Interactive كمبرمج ألعاب متدرب في فترة الصيف. عندما إنتهت فترة التدريب، عدت للعمل بقوة على Enkido2، حتى وصلت بحمد الله إلى الإصدارة التجريبية 0.2، المزايا الموجودة الآن في المحرك يمكن تلخيصها كالآتي: تتألف الألعاب في Enkido2 من عالم اللعبة (World) وهو يدير كل شيء، عدد من المشاهد (Scenes)، وعدد كبير من عناصر اللعبة (Entities) سواء كانت مرئية أو غير مرئية، والتي تشكّل المشاهد. إمكانية تبادل المعلومات بين جميع الأجزاء عن طريق الرسائل. دعم العمق (Z-index) أثناء الرسم ويقوم جزء خاص من المحرك بعملية ترتيب العناصر حسب عمقها لكي ترسم بشكل صحيح، إحدى المحدوديات التي لم أستطع تلافيها أن كل عنصر يستطيع الرسم لعمق واحد فقط، لا يمكن مثلاً رسم الجسم وظله كل في عمق مختلف من قبل عنصر لعبة واحد. بنك المعلومات (InfoBank) ويمكن استخدامه لحفظ أي بيانات يجب أن تتوفر بشكل Global لجميع الأجزاء. نظام لقياس الأداء التفصيلي (Profiler) مدمج ضمن المحرك. يستخدم المحرك ملفات إعدادات (configurations) تعتمد XML. نظام لتسجيل وتوزيع أحداث الإدخال (Input Events) حالياً يقدم دعم للوحة المفاتيح فقط، يتم تسجيل الأحداث فيه عن طريق ملفات XML الخاصة بالإدخال. نظام مؤقت للتعرف على التصادم بين أجزاء اللعبة يدعم التصادم باستخدام الصندوق المحيطي وتعريف مجموعات تصادم مختلفة. نظام بسيط لآلات الحالة State Machines يمكن إضافتها لأي عنصر.   المشكلة التي أعتقد أنها تواجه جميع المطوّرين الذين يعملون لفترة طويلة على مشروع كهذا أنهم يكتشفون بعد عدة شهور طرق أفضل لكتابة بعض الأجزاء التي تمت كتابتها في البداية، وقد واجهت عدة مرات هذه المشكلة وفي احدى المرات أعدت كتابة المحرك بكامله، وانا لا زلت اواجهها الآن، لا أعرف كيف أتعامل مع هذه الرغبة التي تدفعني لإعادة كتابة جزء ما بطريقة أفضل خاصة وأن ذلك يعني إعادة كتابة عدة أجزاء تعتمد عليه أو حتى إلغاء أجزاء بالكامل، هكذا لن أنتهي من هذا المحرك للأبد، وانا فعلاً في حيرة، ماذا كنتم لتفعلوا إن كنتم مكاني؟ نصائحكم؟   بالنسبة لـ Enkido2، قررت بناء المحرك عن طريق التطبيق، كيف ذلك؟ ما أقوم به هو عمل فكرة للعبة بسيطة جداً تستخدم مكونات محددة من المحرك هي قيد التطوير حالياً، وأمشي في تطوير المحرك بموازاة تطوير اللعبة، بحيث أكتشف أحياناً مشاكل عملية في تصميم أجزاء المحرك من المستحيل التعرّف عليها لو تم بناء المحرك بشكل مستقل، وجدت أن هذه الفكرة ممتازة، وأنصح بها شخصياً لمن يطور محركه الخاص لأهداف عملية لأول مرة، المشكلة الوحيدة التي لم أحلها هي أن بعد عدة ألعاب سوف تكون هنالك أجزاء كثيرة تغيرت من المحرك ويكون هنالك احتمال كبير أن الألعاب التي تم عملها في السابق لن تعمل الآن إلا بإعادة كتابتها، وإعادة الكتابة قد تأخذ وقتاً طويلاً.   بالنسبة للإصدار 0.2 من المحرك، كان التركيز على أساسيات المحرك نفسه، وقد انشأت لعبة صغيرة أسميتها TopDown Shooter (ليس أفضل إسم جئت به بالتأكيد )، يمكنكم تجربة اللعبة (وإعلامي بأي مشاكل تلاحظوها إن لم يكن في ذلك مانع): TopDown Shooter (الحجم: 3 MB) موسيقى البداية هي أحد مقاطع موسيقى Metal Gear والمسماة "Old Snake"، وقد أضفتها لتجربة تش��يل الموسيقى بطريقة Streaming، تشغيل الصوت يتم في مسار تنفيذ ثانوي (secondary thread).   الإدخال: مفاتيح الأسهم لتحريك الدبابة. مفتاح المسافة أو مفتاح الإدخال لبدء اللعبة أو تجاوز الشاشات مثل المقدمة. مفتاح المسافة لإطلاق النار. مفتاح `p` لعمل pause للعبة. مفتاح Escape في أي وقت للخروج من اللعبة.   للحصول على نقاط إضافية ثمينة يمكنك محاولة إسقاط الصواريخ باستخدام المدفع. صورة من اللعبة:     بالمناسبة لعلكم لاحظتم الاسم (RedHawk Interactive) في البداية وهو فقط اسم مؤقت، لدي اسم أفضل بدأت باعتماده مؤخراً.   ماذا بعد؟ سؤال محيّر دائماً. هدفي الآن الوصول للإصدارة 0.3 من المحرك وأثناء ذلك تطوير لعبة صغيرة جديدة سأطرحها أيضاً للتجربة عندما تكتمل، الإصدارة الجديدة سوف تشهد إضافة ما يلي للمحرك: استبدال نظام التصادم البسيط الموجود حالياً بمحرك فيزياء ثنائية الأبعاد كامل، سوف استخدم Box2D لهذا الهدف. هنالك مشكلة في ClanLib2 وهي أنه يقدم نظام إحداثيات يعتمد على إحداثيات النافذة، أي إن كانت النافذة 800x600 سوف تكون إحداثيات ClanLib للرسم 800x600 أيضاً، ما أود الوصول إليه هو تثبيت الإحداثيات بغض النظر عن إحداثيات النافذة، كما أن محرك الفيزياء يحتاج إحداثياته الخاصة والتي يجب أن لا تتجاوز 100 وحدة للطول او العرض (للحصول على أفضل دقة لـ Box2D في التعرّف على التصادم والحسابات الفيزيائية يجب ان تكون أبعاد الأجسام من 10 وحدات إلى 0.1 وحدة)، لذلك سوف استخدم نظام احداثيات موحّد غريب قليلاً، مثلاً 100x100 مشترك بين إنكيدو و Box2D، لا زلت أفكر بطريقة لحل هذه المشكلة وأرحب بأي اقتراحات. إنشاء نظام الكاميرا والتي تستطيع الحركة بأربعة اتجاهات إضافة إلى عمل zoom in/out، ترتبط الكاميرا إرتباطاً كبيراً بما أتوصل إليه في ما يخص محرك الفيزياء والإحداثيات الموحدة. تحسين قابلية الاتصال بين عناصر اللعبة المختلفة عن طريق إضافة إمكانية امتلاك عناصر اللعبة لأسماء وسم (tags)، ويمكن كذلك إعطاء العنصر إسماً يشير لطبيعته (names)، مثلاً العنصر الذي يمثل اللاعب سوف يحمل الاسم "Player". أيضاً إضافة إمكانية الاستعلام عن العناصر بالاسم أو الوسم عن طريق المشهد الحالي. أحد المتطلبات التي اكتشفتها خلال تطوير TopDown Shooter الحاجة للربط بين عنصري لعبة بحيث يعتمد أحدهما على الآخر، إن تم تدمير عنصر معين يتم تدمير جميع العناصر التي تعتمد عليه، ينطبق هذا الكلام على الطائرة وظلها مثلاً، الظل يعتمد على وجود الطائرة ويجب تدميره عند تدمير الطائرة، في TopDown Shooter الطائرة وظلها يرسمهما عنصر واحد (أي في نفس العمق) ولكن ذلك لم يسبب أي مشاكل مرئية ملحوظة بسبب بساطة اللعبة. نظام إدارة اصوات للعبة: هنالك مشكلة عملية أيضاً وهي عند تشغيل المؤثرات الصوتية مرة واحدة (fire and forget) واثناء ذلك قام اللاعب بعمل pause، يجب عمل pause لجميع المؤثرات الصوتية التي تعمل في تلك اللحظة، لا يحصل هذا الآن، نظام إدارة (أو قل تشغيل) الأصوات يقدم مقابس للمؤثرات الصوتية بعدد محدود (sound banks) ويتولى عملية أيقاف وتشغيل المؤثرات الصوتية والموسيقى عند عمل pause للمشاهد.   بالطبع لدي فكرة للعبة الصغيرة التالية، وقد قام صديقي الفنان عاصف برسم بعض الشخصيات التي ستدخل في اللعبة التالية:     شكراً عاصف   ما مستقبل إنكيدو 2؟ لم أتكلم حتى الآن عن إمكانية إصدار المحرك في يوم ما للعامّة، هنالك إمكانية بالطبع ولكن ليس الآن وهو لا زال في المراحل الأولى ويتغير باستمرار. من المزايا التي انا عازم على إضافتها: نظام موارد متكامل يستطيع التحميل من ملفات مضغوطة (قد تكون مشفّرة) مع تقديم طريقة لتحميل موارد المشاهد قبل تشغيل المشهد مع إظهار progress bar وما إلى ذلك، قد يستخدم نظام الموارد قاعدة بيانات فعلية لمتابعة كل شيء. برنامج Project Editor: يستطيع تعديل وإنشاء أجزاء كثيرة من اللعبة مثل إنشاء الأشباح (sprites) ومعلوماتها الفيزيائية، الخطوط، رزم الموارد، كتابة نصوص إعداد اللعبة، عمل build لكل شيء، كتابة وتعديل النصوص البرمجية للعبة، ...الخ أود أن أنقل كتابة اللعبة نفسها من كود ++C إلى نصوص برمجية ينفذها المحرك لتسريع وتسهيل عملية تطوير الألعاب، سوف استخدم مكتبة Mono الرائعة لإنشاء نظام النصوص البرمجية وتنفيذها بطريقة JIT للترجمة، بسبب ذلك فالأداء سيكون مقارب من أداء ++C ويمكن كذلك كتابة النصوص بأي لغة برمجية تدعم CLI، مثل #C، فجوال بيسك، أو Python، لقد شغلت هذه الميزة فعلاً للتجربة خارج إنكيدو حالياً، وانا عازم على إعتماد لغة Boo (وهي نكهة من Python مع دعم لـ static typing و generators ومزايا أخرى لطيفة). دعم لأنظمة الجزيئات (particle systems) وامكانية كتابة نصوص XML لتعريف تلك الأنظمة باستخدام Project Editor. نظامان للإظهار. القياسي يستخدم المظللات (shader driven)، اما في حالة عدم إمكانية العتاد التعامل مع المظللات، يمكن استخدام نظام الإظهار الثانوي والذي يعتمد ممر الرسوميات الثابت (Fixed Function Pipeline). النظامان يستخدمان OpenGL.   كما ترون المشروع ضخم رغم كونه محرك ألعاب ثنائية الأبعاد فقط، الهدف منه الوصول لمحرك يمكن استخدامه لإنشاء ألعاب 2D ذات جودة عالية بأقصر وأسهل طريقة ممكنة، عندما استطيع تطوير لعبة كاملة من البداية للنهاية خلال شهر أو إثنين، أكون قد حققت الهدف المراد من تطوير المحرك. ... وها انا بدلاً من العمل على إضافة محرك الفيزياء لإنكيدو 2، أكتب قصة حياتي، عد إلى العمل! *يصفع نفسه عدة مرات عقاباً*