24 ساعة لعبة الصدأ: تجربة التنمية الشخصية

صورة

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

توصي Skillbox بما يلي: دورة تدريبية لمدة عامين "أنا مطور ويب للمحترفين" .

نذكرك: لجميع قراء "Habr" - خصم بقيمة 10،000 روبل عند التسجيل في أي دورة تدريبية في Skillbox باستخدام الرمز الترويجي "Habr".

لماذا الصدأ؟


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

لماذا بالضبط لعبة ونوع اللعبة؟


جعل الألعاب ممتعة! أرغب في المزيد من الأسباب ، لكن بالنسبة لمشاريع "المنزل" ، اخترت موضوعات لا ترتبط ارتباطًا وثيقًا بعملي المعتاد. أي نوع من اللعبة؟ كنت أرغب في صنع شيء مثل جهاز محاكاة التنس ، والذي يجمع بين مدن سكايلينز ، و Zoo Tycoon ، و Prison Architect و Tennis نفسها. بشكل عام ، تحولت إلى لعبة حول أكاديمية التنس ، حيث يأتي الناس للعب.

التدريب الفني


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

العثور على موارد مفيدة أشاركها معك:


لقد اكتشفت العديد من محركات ألعاب Rust ، وأخيراً اخترت Piston و ggez. صادفتهم عند العمل في مشروع سابق. في النهاية ، اخترت ggez ، لأنه بدا أكثر ملاءمة لتنفيذ لعبة صغيرة ثنائية الأبعاد. البنية المعيارية لـ Piston معقدة للغاية بالنسبة لمطور مبتدئ (أو شخص يعمل مع Rust لأول مرة).

هيكل اللعبة


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

التفكير في كل شيء ، وأنا مجموعة للعمل.

خلق لعبة


البدء: الدوائر والتجريدية

أخذت مثالاً من ggez وحصلت على دائرة على الشاشة. ! مدهش الآن بعض التجريدات. بدا لي أنه من الجيد أن أتجاهل فكرة كائن اللعبة. يجب تقديم كل كائن وتحديثه كما هو موضح هنا:

// the game object trait trait GameObject { fn update(&mut self, _ctx: &mut Context) -> GameResult<()>; fn draw(&mut self, ctx: &mut Context) -> GameResult<()>; } // a specific game object - Circle struct Circle { position: Point2, } impl Circle { fn new(position: Point2) -> Circle { Circle { position } } } impl GameObject for Circle { fn update(&mut self, _ctx: &mut Context) -> GameResult<()> { Ok(()) } fn draw(&mut self, ctx: &mut Context) -> GameResult<()> { let circle = graphics::Mesh::new_circle(ctx, graphics::DrawMode::Fill, self.position, 100.0, 2.0)?; graphics::draw(ctx, &circle, na::Point2::new(0.0, 0.0), 0.0)?; Ok(()) } } 

سمحت لي هذه الشفرة بالحصول على قائمة ممتازة بالكائنات التي يمكنني تحديثها وعرضها في حلقة ممتازة بنفس الدرجة.

 mpl event::EventHandler for MainState { fn update(&mut self, context: &mut Context) -> GameResult<()> { // Update all objects for object in self.objects.iter_mut() { object.update(context)?; } Ok(()) } fn draw(&mut self, context: &mut Context) -> GameResult<()> { graphics::clear(context); // Draw all objects for object in self.objects.iter_mut() { object.draw(context)?; } graphics::present(context); Ok(()) } } 

مطلوب main.rs لأنه يحتوي على جميع أسطر التعليمات البرمجية. قضيت بعض الوقت لفصل الملفات وتحسين بنية الدليل. إليك كيف بدأ كل شيء في الاعتناء بذلك:

الموارد -> هذا هو المكان الذي توجد فيه جميع الأصول (صور)
SRC
- الكيانات
- game_object.rs
- دائرة
- main.rs -> الحلقة الرئيسية

الناس والأرضيات والصور

والخطوة التالية هي إنشاء كائن لعبة الشخص وتحميل الصور. يجب أن يستند كل شيء إلى حجم البلاط 32 * 32.



ملاعب التنس

بعد أن درست كيف تبدو ملاعب التنس ، قررت إخراجها من بلاط 4 * 2. في البداية ، كان من الممكن عمل صورة بهذا الحجم أو تجميع 8 مربعات منفصلة. ولكن بعد ذلك أدركت أن هناك حاجة إلى اثنين فقط من البلاط الفريد ، وهذا هو السبب.

في المجموع ، لدينا اثنين من هذه البلاط: 1 و 2.

يتكون كل قسم من البلاط من البلاط 1 أو البلاط 2. ويمكن ترتيبها كالمعتاد أو قلبها رأسًا على عقب بمقدار 180 درجة.



الوضع الرئيسي للبناء (التجمع)

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

لكن ما زلت بحاجة إلى تذكر ما نعنيه 1 و 2 ، لذلك أضفت إطارًا سلكيًا بحيث يكون من الواضح أي كائن محدد. هنا هو كيف يبدو.


أسئلة عن الهندسة المعمارية وإعادة البناء

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

يبدو لي أنني بحاجة إلى إعادة التفكير في الهندسة المعمارية بحيث تم الكشف عن بعض القيود:

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

قمت ببعض الأبحاث الإضافية واكتشفت بنية ECS - Entity Component System ، والذي يشيع استخدامه في الألعاب. فيما يلي فوائد ECS:

  • يتم فصل البيانات عن المنطق ؛
  • تخطيط بدلا من الميراث.
  • بنية البيانات الموجهة.

تتميز ECS بثلاثة مفاهيم أساسية:

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

بعد الدراسة ، أصبح من الواضح أن ECS يحل هذه المشكلات:

  • استخدام التخطيط بدلاً من الميراث لتنظيم نظام الكيانات ؛
  • التخلص من تجزئة الكود بسبب أنظمة التحكم ؛
  • باستخدام طرق مثل is_build_mode لتخزين منطق الإطار السلكي في نفس المكان - في نظام التقديم.

إليك ما حدث بعد تنفيذ ECS.

الموارد -> هذا هو المكان الذي توجد فيه جميع الأصول (صور)
SRC
- المكونات
المنصب
- شخص
- التنس
- الكلمة
- wireframe.rs
- mouse_tracked.rs
- الموارد
- فأر
- النظم
- التقديم
- الثوابت
- utils.rs
- world_factory.rs -> وظائف المصنع العالم
- main.rs -> الحلقة الرئيسية

كلف الناس بالمحاكم


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

ماذا فعلت:

  • إضافة بيانات حول المحاكم المخصصة للشخص ؛
  • إضافة بيانات عن الأشخاص الموزعين إلى TennisCourt ؛
  • إضافة CourtChoosingSystem ، التي تتيح لك تحليل الأشخاص والمواقع ، والعثور على المحاكم المتاحة وتوزيع اللاعبين عليها ؛
  • إضافة نظام PersonMovementSystem ، الذي يبحث عن الأشخاص المعينين في المحاكم ، وإذا لم يكونوا هناك ، فإنه يرسل الأشخاص عند الضرورة.


لتلخيص


لقد استمتعت حقًا بالعمل على هذه اللعبة البسيطة. علاوة على ذلك ، يسعدني أنني استخدمت Rust في كتابته ، لأنه:

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

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

توصي Skillbox بما يلي:


Source: https://habr.com/ru/post/ar444364/


All Articles