Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Programming
Gamedevelopment

ترميز مولد تسلسل مخصص لتقديم Starscape

by
Difficulty:IntermediateLength:LongLanguages:

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

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

ملاحظة: على الرغم من أن هذا البرنامج التعليمي مكتوب باستخدام Java ، يجب أن تكون قادرًا على استخدام نفس الأساليب والمفاهيم في أي بيئة تطوير ألعاب.


إنشاء وتهيئة الصورة

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

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


جعل ملف نجمة وحقل نجمة

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

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

  • س تنسيق
  • الإحداثي ص
  • الحجم

سيكون لكل سمة من السمات الثلاث قيم تتراوح من 0 إلى 999 ، مما يعني أن كل سمة ستحتوي على ثلاثة أرقام مخصصة لها. سيتم تخزين كل هذا في فئة ستار.

هناك طريقتان مهمتان في فئة Star هما getSize () و getRadiusPx (). ترجع الدالة getSize () حجم النجم ، مقسومًا إلى رقم عشري بين صفر وواحد ، وترجع طريقة getRadiusPx () إلى مدى أهمية نصف قطر النجمة في الصورة النهائية.

لقد اكتشفت أن 4 بيكسلات تمثل نصف قطر جيد في العرض التوضيحي الخاص بي ، لذا سيعيد getRadiusPx () ببساطة قيمة getSize () مضروبة بأربعة. على سبيل المثال ، إذا قام الأسلوب getSize () بإرجاع نصف قطر قدره 0.4 ، فإن طريقة getRadiusPx () ستعطي نصف قطر 1.6 بكسل.

يجب أيضًا أن نجعل فئة بسيطة للغاية تتمثل مهمتها في تتبع جميع النجوم في كل سلسلة من النجوم. تتكون فئة Starfield فقط من الأساليب التي تضيف أو تزيل أو تسترد النجوم من ArrayList. يجب أن يكون أيضاً قادراً على إرجاع ArrayList.


تخطيط مولد التسلسل

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

أولاً ، نعرف أن عرض الصورة وارتفاعها هو 1000 بكسل. وهذا يعني أنه ، لاستغلال الموارد في متناول اليد ، يجب أن يقع نطاق الإحداثيات x و y في النطاق 0-999. نظرًا لأن اثنين من الأرقام المطلوبة تقعان في نفس النطاق ، يمكننا تطبيق نفس النطاق على حجم النجم للحفاظ على التماثل. سيتم بعد ذلك تقليص الحجم في وقت لاحق عند تفسير سلسلة الأرقام.

سنستخدم عددًا من المتغيرات الطبقية. وتشمل هذه: s_seed ، عدد صحيح واحد يحدد التسلسل الكامل ؛ s_start و s_end ، وهما رقمان صحيحان يتم تكوينهما عن طريق تقسيم البذور إلى قسمين ؛ و s_current ، عدد صحيح يحتوي على أحدث عدد تم إنشاؤه في التسلسل.

Creating a sequence
شاهد هذه الصورة من مقالتي السابقة. 1234 هي البذور ، و 12 و 34 هي القيم الأولية ل s_start و s_end.
نصيحة: لاحظ أن كل رقم تم إنشاؤه ينشأ من البذور ؛ لا يوجد دعوة لعشوائية (). وهذا يعني أن نفس البذرة ستولد دائما نفس النجوم.

سنستخدم أيضًا s_sequence ، وهي سلسلة ستحمل التسلسل العام. آخر متغيرين للفئة هما s_image (من النوع Image - فئة سوف ننشئها لاحقًا) و s_starfield (من النوع Starfield ، الفئة التي أنشأناها للتو). أول واحد يخزن الصورة ، في حين أن الثاني يحتوي على ستارفيلد.

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


ترميز مولد التسلسل

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

لذلك:

  • seed = 1234 تعني s_start = 12 و s_end = 34
  • seed = 7 تعني s_start = 00 و s_end = 07
  • seed = 303 تعني s_start = 03 و s_end = 03

التالي في السطر: إنشاء طريقة أخرى ، والتي تعطي الرقم التالي في التسلسل ، نظرا للرقمين.

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

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

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

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

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


ضع كل شيء معا

بعد الانتهاء من ذلك ، يمكننا تجميع المولد. يجب أن يقبل عدد النجوم التي يجب أن يولدها.

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

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

نصيحة: يجب ألا ننسى استبدال s_start و s_end وإلا فإننا سنستمر في توليد نفس الرقم مرارًا وتكرارًا!

رسم النجوم

والآن بعد أن انتهى الجزء الصعب ، فقد حان الوقت للانتقال إلى فئة الصورة ، والبدء في رسم النجوم.

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

لرسم النجم ، سنستخدم تدرجًا نصف قطريًا.

An example of a radial gradient
مثال على التدرج الشعاعي

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

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

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

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

The resulting image with a seed 1234
الصورة الناتجة مع بذرة من 1234

تحسينات

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

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

إن تشغيل البرنامج للمرة الأخيرة يجب أن يمنحك نتيجة مرضية.

The final result – a whole starscape procedurally generated by our Sequence Generator!
والنتيجة النهائية - نجوم كاملة من الناحية الإجرائية ولدت من قبل مولد تسلسلنا!

الاستنتاج

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

Advertisement
Advertisement
Advertisement
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.