Advertisement
  1. Game Development
  2. Programming

إنشاء لعبة Asteroids بسيطة باستخدام الكيانات القائمة على المكونات

Scroll to top
Read Time: 10 min

Arabic (العربية/عربي) translation by Adjatay Bashroh Aldad (you can also view the original English article)

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


معاينة النتيجة النهائية


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

كود المصدر الكامل متاح على GitHub.


نظرة عامة على الفصل

هناك ستة فصول:

  • AsteroidsGame ، الذي يوسّع فئة اللعبة الأساسية ويضيف المنطق الخاص بـ space-em-up.
  • السفينة ، وهذا هو الشيء الذي تسيطر عليه.
  • الكويكب ، وهو الشيء الذي تطلق عليه النار.
  • رصاصة ، وهو الشيء الذي قمت بإطلاقه.
  • بندقية ، مما يخلق تلك الرصاصات.
  • EnemyShip ، وهو غريب أجنبي من هناك فقط لإضافة القليل من التنوع للعبة.
  • دعونا نذهب من خلال هذه الأنواع الكيانات واحدا تلو الآخر.


    فئة السفينة

    سنبدأ بسفينة اللاعب:

هناك قدرا كبيرا من تنفيذ التفاصيل هنا، ولكن الشيء الرئيسي لإشعار أننا إنشاء مثيل في المنشئ وتكوين مكونات الجسم، والفيزياء، والصحة وعرض والأسلحة. (إن عنصر السلاح هو في الواقع مثال لـ Gun بدلاً من فئة أساس الأسلحة.)

إنني أستخدم واجهات برمجة تطبيقات رسم الرسومات البيانية لإنشاء سفينتي (الخطوط من 29 إلى 32) ، ولكن يمكننا بسهولة استخدام صورة نقطية. أقوم أيضًا بإنشاء -- مثيل لفئة Gamepad الخاصة بي - هذه مكتبة مفتوحة المصدر كتبت قبل عامين لجعل إدخال لوحة المفاتيح أسهل في Flash.

لقد قمت أيضًا بإلغاء وظيفة التحديث من الفئة الأساسية لإضافة بعض السلوك المخصص: بعد تشغيل كافة السلوك الافتراضي باستخدام super.update () نحن تدوير وتدفع السفينة على أساس إدخال لوحة المفاتيح ، وإطلاق النار إذا تم الضغط على مفتاح النار.

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


فئة البندقية

دعونا نطلق النار في ذلك الفصل

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

الشيء العظيم في هذه الفئة هو أنه يستخدم من قبل كل من اللاعب وسفن العدو.


فئة رصاصة

ينشئ Gun مثالًا على هذه الطبقة Bullet:

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

لن يصلح نظام التصادم هذا لآلاف الرصاصات ، ولكنه جيد بالنسبة لمعظم الألعاب غير الرسمية.

إذا حصلت الطلقة على أكثر من 20 إطارًا ، فسنبدأ في التلاشي ، وإذا أقدمنا ​​على 25 إطارًا ، فإننا ندمرها. كما هو الحال مع بندقية ، يتم استخدام Bullet من قبل كل من اللاعب والعدو - الحالات فقط لديها قائمة أهداف مختلفة.

بالحديث عن هذا الموضوع...


فئة EnemyShip

الآن دعونا ننظر إلى سفينة العدو هذه:

كما ترون ، إنه يشبه إلى حد كبير فئة سفينة اللاعب. الفرق الحقيقي الوحيد هو أنه في وظيفة التحديث () ، بدلاً من التحكم في المشغل عبر لوحة المفاتيح ، لدينا بعض 'الغباء الاصطناعي' لجعل السفينة تجول وتطلق النار عشوائياً.


فئة الكويكب

الكيان الآخر الذي يمكن للاعب أن يطلق عليه هو الكويكب نفسه:

نأمل أن تعتاد على كيفية بحث فئات الكيان هذه الآن.

في المنشئ نقوم بتهيئة مكوناتنا وتعيين الموقع والسرعة بشكل عشوائي.

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


فئة AsteroidsGame

أخيرًا ، لنلق نظرة على فئة AsteroidsGame التي تتحكم في العرض بالكامل:

هذا الفصل طويل جدًا (أكثر من 100 سطر!) لأنه يفعل الكثير من الأشياء.

في startGame () يقوم بإنشاء وتكوين 10 كويكبات ، السفينة وسفينة العدو ، ويقوم أيضًا بإنشاء رسالة 'اضغط على بدء التشغيل'.

تقوم وظيفة start () بإيقاف اللعبة وإزالة الرسالة ، بينما تقوم وظيفة gameOver بإيقاف اللعبة مؤقتًا مرة أخرى واستعادة الرسالة. تستمع الدالة restart () بنقرة ماوس على شاشة Game Over - عندما يحدث ذلك ، توقف اللعبة وتبدأ مرة أخرى.

تقوم وظيفة التحديث () بتكرار جميع الأعداء والاعوجاجات التي انجرفت عن الشاشة ، وكذلك التحقق من حالة الفوز ، وهي عدم وجود أعداء في قائمة الأعداء.


أخذ المزيد

هذا هو محرك عظام جميل ولعبة بسيطة ، لذلك دعونا الآن نفكر في طرق يمكننا توسيعه.

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

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

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

لهذا ، سنفعل شيء مثل:

ثم يقوم أي كيان يحتاج إلى وظيفة 'المنصة' بتنفيذ هذه الواجهة ، مما يمكن الكيانات الأخرى من التفاعل مع مكون PlatformController.


الاستنتاجات

حتى من خلال الجرأة على الكتابة عن بنية اللعبة ، أخشى أن أحرك عشًا في عش الدبابير - ولكن هذا (في الغالب) دائمًا شيء جيد ، وآمل على الأقل جعلتك تفكر في كيفية تنظيم الشفرة.

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

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

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

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Game Development tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.