اذهب إلى المحتوى

البحث في الموقع

المحتوى عن 'godot'.

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المحتوى


التصنيفات

  • الإدارة والقيادة
  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • السلوك التنظيمي في المؤسسات
  • عالم الأعمال
  • التجارة والتجارة الإلكترونية
  • نصائح وإرشادات
  • مقالات ريادة أعمال عامة

التصنيفات

  • مقالات برمجة عامة
  • مقالات برمجة متقدمة
  • PHP
    • Laravel
    • ووردبريس
  • جافاسكربت
    • لغة TypeScript
    • Node.js
    • React
    • Vue.js
    • Angular
    • jQuery
    • Cordova
  • HTML
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • لغة C#‎
    • ‎.NET
    • منصة Xamarin
  • لغة C++‎
  • لغة C
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • لغة Rust
  • برمجة أندرويد
  • لغة R
  • الذكاء الاصطناعي
  • صناعة الألعاب
  • سير العمل
    • Git
  • الأنظمة والأنظمة المدمجة

التصنيفات

  • تصميم تجربة المستخدم UX
  • تصميم واجهة المستخدم UI
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب GIMP
    • كريتا Krita
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • مقالات DevOps عامة
  • خوادم
    • الويب HTTP
    • البريد الإلكتروني
    • قواعد البيانات
    • DNS
    • Samba
  • الحوسبة السحابية
    • Docker
  • إدارة الإعدادات والنشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
    • ريدهات (Red Hat)
  • خواديم ويندوز
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • شبكات
    • سيسكو (Cisco)

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح
  • مبادئ علم التسويق

التصنيفات

  • مقالات عمل حر عامة
  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • العمل الحر المهني
    • العمل بالترجمة
    • العمل كمساعد افتراضي
    • العمل بكتابة المحتوى

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
    • بريستاشوب
    • أوبن كارت
    • دروبال
  • الترجمة بمساعدة الحاسوب
    • omegaT
    • memoQ
    • Trados
    • Memsource
  • برامج تخطيط موارد المؤسسات ERP
    • تطبيقات أودو odoo
  • أنظمة تشغيل الحواسيب والهواتف
    • ويندوز
    • لينكس
  • مقالات عامة

التصنيفات

  • آخر التحديثات

أسئلة وأجوبة

  • الأقسام
    • أسئلة البرمجة
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات

التصنيفات

  • كتب ريادة الأعمال
  • كتب العمل الحر
  • كتب تسويق ومبيعات
  • كتب برمجة
  • كتب تصميم
  • كتب DevOps

ابحث في

ابحث عن


تاريخ الإنشاء

  • بداية

    نهاية


آخر تحديث

  • بداية

    نهاية


رشح النتائج حسب

تاريخ الانضمام

  • بداية

    نهاية


المجموعة


النبذة الشخصية

تم العثور على 12 نتائج

  1. آخر ما يلزمنا ﻹكمال اللعبة ثنائية الأبعاد "تفادي الزواحف" التي بدأنا العمل عليها في مقال سابق هو بناء واجهة المستخدم user interface المخصصة عرض أشياء مهمة مثل النتيجة أو عبارة "انتهت اللعبة" وزر ﻹعادة اللعب. لهذا سننشىء في مقال اليوم مشهدًا جديدًا ثم نضيف عقدة من النوع CanvasLayer (واجهة مستخدم) باسم HUD وهي اختصار للكلمات "Heads-up display" بمعنى "شاشة المقدمة" والتي تعرض معلومات عن اللعبة وتظهر على شكل طبقة فوق نافذة عرض اللعبة. إنشاء واجهة اللعبة تسمح لك العقدة CanvasLayer في محرك الألعاب جودو GODOT برسم عناصر واجهة المستخدم على طبقة فوق بقية مشاهد اللعبة، وبالتالي لن تغطيها أية عناصر أخرى كاللاعب أو اﻷعداء. في لعبتنا الحالة، نحتاج لأن تعرض الواجهة HUD المعلومات التالية: النتيجة وتغيّرها ScoreTimer. رسالة مثل "انتهت اللعبة" أو "استعد!". زر البداية "ابدأ" لكي تبدأ اللعب. إن الصنف اﻷساسي لهذه العقدة هو Control، وسنحتاج في واجهتنا لنوعين من عناصر التحكم Control هما عنوان Label وزر Button، لهذا عليك إنشاء ثلاث عقد أبناء للعقدة HUD كالتالي: عنوان Label باسم ScoreLabel. عنوان Label باسم Message. زر Button باسم StartButton. مؤقت Timer باسم MessageTimer. انقر على العنوان ScoreLabel ثم اكتب رقمًا في الحقل Text ضمن الفاحص، وكما تلاحظ، فإن الخط المستخدم افتراضيًا للعقدة Control صغير وغير مناسب، لذلك سنستخدم خطًا موجودًا ضمن المجلد "font" يُدعى "Xolonium-Regular.ttf" كالتالي: في نافذة الفاحص وتحت اللوحة انقر على Theme Overridesثم Fonts ثم Font ثم اختر "تحميل" واختر الملف "Xolonium-Regular.ttf": زد حجم الخط إلى 64 في الحقل "Font Size" ثم كرر نفس العملية على العنوان اﻵخر وعلى الزر في المشهد. ملاحظة: للعقدة Control موقع وأبعاد لكنها تمتلك أيضًا ما يُعرف بالمربط Anchor الذي يحدد نقطة اﻷصل، وهي النقطة المرجعية لحواف العقدة. رتب العقد كما في لقطة الشاشة التالية، وبإمكانك سحب العقد إلى المكان الذي تريده يدويًا أو استخدم المربط لضبط الموقع بدقة أكبر: العنوان ScoreLabel أضف النص 0 اضبط المحاذاة اﻷفقية Horizontal Alignment والعمودية Vertical Alignment على Center. اختر القيمة Center Top لضبط المربط (الخاصية Anchor Preset). الرسالة Message أضف النص "تفادي الزواحف". اضبط المحاذاة اﻷفقية Horizontal Alignment والعمودية Vertical Alignment على Center. اضبط قيمة "نمط الالتفاف التلقائي Autowrap Mode" على Word وإلا سيبقى النص على نفس السطر. اضبط قيمة الخاصية Size X الموجودة على المسار Control>Layout>Transform على القيمة 480 اختر القيمة Center لضبط المربط (الخاصية Anchor Preset). الزر StartButton أضف النص "ابدأ". اضبط قيمة الخاصية Size X الموجودة على المسار Control>Layout>Transform على القيمة 200 والخاصية Size Y على القيمة 100. اختر القيمة Center Bottom لضبط المربط (الخاصية Anchor Preset). ا ضبط قيمة الخاصية Position Y الموجودة على المسار Control>Layout>Transform على القيمة 580. وأخيرًا، اضبط الخاصية Wait Time في المؤقت MessageTimer على 2، والخاصية One Shot على "فعّال ON" ثم أضف السكربت التالي إلى HUD: extends CanvasLayer # Notifies `Main` node that the button has been pressed signal start_game نريد اﻵن عرض رسالة مؤقتة مثل " استعد!" لهذا سنضيف الشيفرة التالية: func show_message(text): $Message.text = text $Message.show() $MessageTimer.start() علينا أيضًا معالجة الحالة التي يخسر فيها اللاعب، لهذا ستعرض الشيفرة التالية رسالة "انتهت اللعبة" لمدة ثانيتين ثم تعود إلى الشاشة الرئيسية وتعرض بعد توقف صغير الزر "ابدأ": func show_game_over(): show_message("Game Over") # Wait until the MessageTimer has counted down. await $MessageTimer.timeout $Message.text = "Dodge the\nCreeps!" $Message.show() # Make a one-shot timer and wait for it to finish. await get_tree().create_timer(1.0).timeout $StartButton.show() تُستدعى الدالة اﻷخيرة عندما يخسر اللاعب. ملاحظة: إن أردت أن توقف اللعبة لفترة وجيزة، بإمكانك استخدام الدالة ()create_timer العائدة لشجرة المشاهد بدلًا من استخدام عقدة مؤقت. وهذه الدالة مفيدة جدًا في إضافة تأخير زمني في الحالات المشابهة لحالتنا التي نرغب فيها الانتظار قليلًا قبل عرض زر "إبدأ". أضف الشيفرة التالية اﻵن لتحديث النتيجة: func update_score(score): $ScoreLabel.text = str(score) صل اﻹشارة ()timeout العائدة للمؤقت MessageTimer واﻹشارة ()pressed العائدة للزر StartButton ثم عدل الشيفرة لتصبح كالتالي: func _on_start_button_pressed(): $StartButton.hide() start_game.emit() func _on_message_timer_timeout(): $Message.hide() ربط المشهد HUD بالمشهد الرئيسي Main بعد أن انتهينا من إنشاء المشهد HUD سنعود إلى المشهد الرئيسي Main. انشئ نسخة من المشهد HUDضمن المشهد الرئيسي كما نسخنا مشهد اللاعب سابقًا. ويجب أن تبدو شجرة المشاهد كالتالي حتى يكون كل شيء في مكانه الصحيح: علينا اﻵن وصل وظائف المشهد HUD إلى السكربت الرئيسي، ويتطلب ذلك بعد اﻹضافات إلى المشهد الرئيسي. صل اﻹشارة start_game للمشهد HUD إلى الدالة ()new_game في المشهد الرئيسي بالنقر على نسخة HUD في المشهد الرئيسي ثم الانتقال إلى "عقدة" في الشريط الجانبي واختيار اﻹشارة start_game ثم النقر عليها نقرًا مزدوجًا لتظهر نافذة "قم بوصل اﻹشارة إلى الدالة" ثم النقر على زر "Pick" في أسفلها واختيار الدالة ()new_game. تأكد من وجود اﻷيقونة الخضراء إلى جوار ()func new_game في السكربت الرئيسي، ولا تنس إزالة الاستدعاء ()new_game من الدالة ()ready_ ﻷننا لا نريد أن تبدأ اللعبة تلقائيًا. عدّل الشيفرة الموجودة ضمن الدالة ()new_game لتعرض الرسالة "استعد!": $HUD.update_score(score) $HUD.show_message("Get Ready") كما عليك استدعاء دالة HUD الموافقة للدالة ()game_over في السكربت الرئيسي: $HUD.show_game_over() أضف أخيرًا الشيفرة التالية إلى الدالة ()on_score_timer_timeout_ كي يبقى عداد النتيجة متزامنًا مع التغيرات: $HUD.update_score(score) أصبحت اﻵن جاهزًا للعب! انقر على زر تشغيل المشهد، وإذا طُلب منك اختيار المشهد اﻷساسي اختر main.tscn. إزالة الزواحف القديمة عندما تنتهي اللعبة وتحاول اللعب مجددًا ستبقى الزواحف من اللعبة القديمة موجودة على الشاشة ومن اﻷفضل أن تختفي جميعها قبل البدء بلعبة جديدة. إذًا لابد من طريقة ﻹخبار الزواحف بتدمير نفسها، وذلك باستخدام الميزة "المجموعات group". اختر المشهد ثم اختر العقدة الرئيسية وانقر على نافذة "عقدة" إلى جوار الفاحص وهو نفس المكان الذي تجد فيه اﻹشارات. انقر على العنوان "مجموعات" ثم اكتب اسمًا للمجموعة الجديدة وليكن "mobs" ثم انقر "أضف" وستظهر المجموعة الجديدة تحت الصندوق النصي: أضف السطر التالي إلى الدالة ()new_game في السكربت الرئيسي: get_tree().call_group("mobs", "queue_free") تستدعي الدالة ()call_group تابعًا محددًا (المعامل الثاني لها) باسمه وتطبقه على كل عناصر المجموعة المختارة (المعامل الأول)، وفي حالتنا يحذف كل زاحف نفسه. وضع اللمسات اﻷخيرة على اللعبة اكتملت اللعبة حاليًا من ناحية الوظيفة، وما سنفعله تاليًا هو بعض اﻹضافات لتحسين المظهر العام لها. الخلفية قد يجد البعض أن الخلفية الرمادية غير جذابة لذا دعونا نغير اللون. ومن الطرق المتبعة نجد العقدة ColorRect التي يجب وضعها تحت العقدة Main مباشرة كي تُرسم خلف جميع العقد. ولهذا العقدة خاصية واحدة هي Color. اختر اللون الذي تريده ثم انقر على Layout>Anchor Preset واختر "على كامل المستطيل"، كما يمكنك تنفيذ العملية من خلال شريط اﻷدوات أعلى نافذة العرض. بإمكانك أيضًا استخدام صورة في الخلفية إن أردت لكنك ستحتاج إلى عقدة من نوع TextureRect. إضافة تأثيرات صوتية للعبة مقاطع الصوت والموسيقى من أكثر العوامل التي تزيد من جاذبية تصميم الألعاب الإلكترونية، لهذا وضعنا في المجلد "art" الخاص بلعبتنا ملفين صوتيين الأول هو "House In a Forest Loop.ogg" لموسيقى الخلفية واﻵخر "gameover.wav" لخسارة اللاعب. وعلينا اﻵن إضافة عقدتين من النوع AudioStreamPlayer كأبناء للعقدة Main وتسميتهما باسم Music و DeathSound. انقر بعد ذلك على الخاصية Stream لكل منهما ثم "تحميل" واختر المقطع الصوتي الموافق. تُدرج المقاطع الصوتية تلقائيًا وتكون الخاصية Loop غير مفعلة لها بصورة افتراضية. فإن أردت أن تشغل الموسيقى دون توقف، فانقر على السهم المجاور لاسم الملف الصوتي في الخاصية stream ثم اختر "اجعله فريدًا" وانقر بعدها على المربع الذي يضم اسم العقدة الصوتية أعلى حاوية الفاحص واختر "stream" ثم فعّل قيمة الخاصية Loop. ولتشغيل الموسيقى أضف التابع ()Music.play$ إلى الدالة ()new_game والتابع ()Music.stop$ إلى الدالة ()game_over ثم أضف أخيرًا التابع ()DeathSound.play$ إلى الدالة ()game_over. اختصارات لوحة المفاتيح طالما أن التحكم باللعبة سيكون عن طريق لوحة المفاتيح، فمن الملائم جدًا أن نبدأ اللعبة بالضغط على أحد مفاتيحها. يمكن إنجاز اﻷمر بالاستفادة من الخاصية "Shortcut" للزر Button. لهذا سننشئ إجراء دخل يربط مفتاحًا بالزر "Start". انقر على مشروع>إعدادات الشروع ثم انقر على النافذة الفرعية "خريطة اﻹدخال" في النافذة التي تظهر. انشئ بعد ذلك وبنفس الطريقة التي أنشأت بها سابقًا إجراءات الحركة اﻷربعة إجراءًا جديدًا باسم start_game واربطه بالمفتاح Enter. وإن أردت أيضًا ربط أزرار أي أداة تحكم أخرى باﻹجراءات السابقة، تأكد من توصيل هذه اﻷداة ثم انقر اﻷيقونة "+" الموجودة إلى يمين كل إجراء ثم اضغط زر اﻷداة الذي تريد ربطه بهذا اﻹجراء. عد إلى الواجه HUD وانقر على الزر StartButton ثم ابحث عن الخاصية "Shortcut" ضمن "الفاحص" ثم انشئ اختصارًا جديدًا بالنقر على مربع النص المجاور واختيار "جديدة Shortcut" ثم النقر على الاختصار الجديد وفتح "Events" وإضافة حدث جديد بالنقر على "Array[InputEvent]". أنشئ حدث جديدة InputEventAction باسم start_game: وهكذا عندما يظهر زر "ابدأ" يمكن النقر عليه أو الضغط على المفتاح "Enter" لتبدأ اللعب! الخلاصة لقد انتهيت من تصميم أولى ألعابك ثنائية البعد وقد تعلمت إنشاء الشخصيات التي تتحكم بها والزواحف التي تتكاثر لتملأ الشاشة واستطعت حساب النتيجة وأنجزت طريقة لتبدأ اللعبة وتنهيها وتستخدم واجهة لها وأضفت مقاطع صوتية. تهانينا! لا زال هناك الكثير لتتعلمه بالطبع لتكون مطور ألعاب إلكترونية محترف، لكن خذ الآن قسطًا من الراحة واستمتع بإنجازك! ترجمة -وبتصرف- للمقالين: Heads_up display و Finishing up اقرأ أيضًا المقال السابق: بناء لعبة ثنائية البعد عبر محرك الألعاب Godot - الجزء الثالث: إنشاء المشهد الرئيسي في اللعبة تعرف على أشهر لغات برمجة الألعاب كيف تصبح مبرمج ألعاب فيديو ناجح دليلك الشامل إلى بناء كاميرا خاصة بشاشات اللمس في محرّك اﻷلعاب جودو
  2. بدأنا في مقال سابق بإنشاء لعبة إلكترونية باستخدام محرك الألعاب جودو، وحان الوقت اﻵن لضم كل شيء معًا وإنشاء مشهد كامل للعبتنا، لهذا سنبدأ في مقال اليوم باستكمال العمل على اللعبة وإنشاء مشهدها الأساسي وإعداده بالطريقة المناسبة. إنشاء عقدة المشهد الرئيسي للعبة لإنشاء مشهد جديد في محرك ألعاب جودو علينا إنشاء عقدة اسمها Main من النوع Node ولا حاجة أن تكون من النوع Node2D لأنها مجرد حاوية لمنطق اللعبة ولن تحتاج فعلًا إلى وظائف هذا النوع من العقد. انقر على زر إنشاء نسخة (أيقونة السلسلة في نافذة المشهد) ثم اختر المشهد "Player.tscn". أضف بعد ذلك العقد التالية كأبناء للعقدة Main وفق اﻷسماء التالية: مؤقت Timer باسم MobTimer للتحكم بمعدل تكاثر الزواحف، واضبط الخاصية Wait Time له على 0.5. مؤقت Timer باسم ScoreTimer لزيادة النتيجة كل ثانية، واضبط الخاصية Wait Time له على 1. مؤقت Timer باسم StartTimer لإضافة تأخير بسيط قبل بدء اللعبة، واضبط الخاصية Wait Time له على 2. عقدة من النوع Marker2D اسمها StartPosition لتحديد موقع البداية بالنسبة للاعب. إضافة إلى ذلك، اضبط الخاصية One Shot للمؤقت StartTimer على "فعّال On" و الخاصية Position للعقدة StartPosition على القيمة التالية(450, 240). تكاثر الأعداء نستخدم المشهد الرئيسي Main في تكاثر الأعداء ونريدهم أن يظهروا في أماكن عشوائية على حواف الشاشة، لهذا أضف عقدة من النوع Path2D باسم MobPath كابن للعقدة الرئيسية. سترى عدة أزرار إضافية في أعلى المحرر عند اختيار اﻷيقونة Path2D: اختر الزر الموجود في المنتصف "إضافة عقدة (في مساحة خالية)" ثم ارسم مسارًا بالنقر ضمن المحرر في النقاط التي يعرضها الشكل التالي. ولكي يكون تحديد النقاط دقيقًا فعّل الخيارين "استخدام المحاذاة للشبكة Use Grid Snap" و "استخدم المحاذاة الذكية Use Smart Snap"، وستجدهما إلى يمين أيقونة "القفل" على شكل مغناطيس بجوار عدة نقاط وآخر بجوار شبكة كما توضح الصورة التالية: ملاحظة مهمة: ارسم المنحني باتجاه عقارب الساعة وإلا ستتكاثر الزواحف إلى الخارج بدلًا من الداخل. بعد تحديد أربع نقاط، انقر على أيقونة "إغلاق المنحني" وسيكتمل هذا المنحني. أضف بعد الانتهاء من رسم المنحني العقدة PathFollow2D كابن للعقدة MobPath وسمها MobSpawnLocation. ستدور هذه العقدة وتتبع المسار عندما تتحرك وبالتالي يمكن استخدامها لاختيار مواقع واتجاهات عشوائية على طول المسار. سيبدو المشهد الرئيسي اﻵن كما يلي: السكربت الرئيسي أضف سكربت (نص برمجي) إلى المشهد Main ثم أضف العبارة export var mob_scene: PackedScene@ التي تسمح لنا باختيار مشهد اﻷعداء الذي نريد صنع نسخة عنه: extends Node @export var mob_scene: PackedScene var score انقر على العقدة Main وستجد الخاصية Mob Scene ضمن الفاحص في لوحة "متغيرات السكربت"، وﻹسناد قيمة إلى هذه الخاصية يمكنك اتباع إحدى الطريقتين التاليتين: اسحب المشهد من حاوية نظام الملفات وأفلته ضمن الخاصية Mob Scene. انقر على زر السهم المجاور للخاصية Mob Scene وانقر "تحميل" ثم اختر mob.tscn. اختر نسخة العقدة Player الموجودة ضمن العقدة Main ثم انقر على حاوية "عقدة" إلى جوار "الفاحص" في الشريط الجانبي لترى قائمة تضم جميع اﻹشارات للعقدة Player. جد اﻹشارة hit وانقر عليها نقرة مزدوجة (أو انقر عليها بالزر الأيمن واختر "توصيل"). ستفتح هذه العملية نافذة جديدة نريد فيها إنشاء دالة جديدة ندعوها game_over تعالج ما نريد فعله عند انتهاء اللعبة. اكتب "game_over" في المربع النصي "الدالة المتلقية Receiver Method" أسفل النافذة ثم انقر زر "وصل Connect". وما سيحدث اﻵن أن اﻹشارة hit التي بثها اللاعب Player سيعالجها السكربت اﻷساسي "Main". أضف اﻵن الشيفرة التالية إلى الدالة الجديدة، وأضف أيضًَا الدالة new_game التي تحضّر كل شيء عند بداية اللعبة: func game_over(): $ScoreTimer.stop() $MobTimer.stop() func new_game(): score = 0 $Player.start($StartPosition.position) $StartTimer.start() صل اﻵن اﻹشارة ()timeout العائدة إلى كل عقدة مؤقت (StartTimer و ScoreTimer و MobTimer) إلى السكربت الرئيسي. وسيشغل المؤقت StartTimer المؤقتين الآخرين ويزيد المؤقت ScoreTimer النتيجة بمقدار 1. func _on_score_timer_timeout(): score += 1 func _on_start_timer_timeout(): $MobTimer.start() $ScoreTimer.start() سننشئ ضمن الدالة نسخة عن العدو (الزواحف)، لهذا، سنختار مكانًا عشوائيًا للبدء على المسار Path2D ونضبط حركة العدو. تدور العقدة تلقائيًا عندما تلحق بالمسار، لهذا سنستفيد منها في اختيار جهة حركة الزاحف وموقعه. وعندما تتكاثر الزواحف سنختار قيمة عشوائية لسرعة حركتها بين 150 و 250. وانتبه إلى أن إضافة نسخة جديدة إلى المشهد تكون من خلال التعليمة add_child: func _on_mob_timer_timeout(): # mob scene أنشئ نسخة من مشهد الزاحف var mob = mob_scene.instantiate() # Path2D اختر مكانًا عشوائيًا على المسار. var mob_spawn_location = get_node("MobPath/MobSpawnLocation") mob_spawn_location.progress_ratio = randf() # اجعل اتجاه الزاحف عمودًا على اتجاه المسار var direction = mob_spawn_location.rotation + PI / 2 # اختر موقعًا عشوائيًًًًًًًًًا للزاحف mob.position = mob_spawn_location.position # أضف بعض العشوائية إلى المسار direction += randf_range(-PI / 4, PI / 4) mob.rotation = direction # اختر سرعة الزاحف var velocity = Vector2(randf_range(150.0, 250.0), 0.0) mob.linear_velocity = velocity.rotated(direction) # إجعل الزواحف تتكاثر بإضافتها إلى الشاشةالرئيسية add_child(mob) ملاحظة هامة: قد تتساءل لماذا نستخدم العدد PI في الدوال التي تتعامل مع الزوايا؟ لأن جودو يستخدم الراديان لقياس الزوايا. تمثّل PI نصف دوره كما يمكن استعمال TAU التي تمثّل دورة كاملة. لكن إن كنت تفضّل العمل مع الدرجات ستحتاج إلى الدالتين ()rad_to_deg و ()deg_to_rad للتحويل بين الدرجات والراديان. اختبار المشهد نختبر اﻵن إذا كانت كل شيء على ما يرام حتى اللحظة، لهذا استدعي الدالة new_game ضمن الدالة ()ready_: func _ready(): new_game() لنجعل أيضًا المشهد Main المشهد الرئيسي في اللعبة، وهو المشهد الذي يعمل تلقائيًا. انقر على زر التشغيل واختر main.tscn عندما يُطلب ذلك. من المفترض أن تكون قادرًا على تحريك اللاعب في جميع الاتجاهات وترى الزواحف تتحرك وتتكاثر، وسترى كيف يختفي اللاعب عندما يصطدم بالعدو. عندما تتأكد أن كل شيء يعمل جيدًا أزل الدالة new_game من الدالة ()ready_. الخلاصة تعلمنا في مقال اليوم كيف ننشئ المشهد الأساسي للعتبنا الإلكترونية وسنكتفي في هذا المقال بهذه المرحلة، ومع ذلك لا تزال اللعبة غير مكتملة وتنقصها بعض اللمسات النهائية وإنشاء واجهة مناسبة للعبة، لذا سنشرح خطوات تعزيز اللعبة بواجهة تتضمن تأثيرات صوتية واختصارات لوحة المفاتيح وغيرها من الخيارات وهذا ما سنراه في المقال التالي من هذه السلسلة. ترجمة -وبتصرف- للمقال: The main game scene اقرأ أيضًا المقال السابق: بناء لعبة ثنائية البعد عبر محرك الألعاب Godot - الجزء الثاني: إنشاء مشاهد اللعبة وبرمجتها إعداد محرك الألعاب جودو Godot للعمل مع قاعدة البيانات SQLite مدخل إلى محرك الألعاب جودو Godot مطور الألعاب: من هو وما هي مهامه
  3. بعد أن أنشأنا في المقال السابق ملفات مشروع لعبة "تفادي الزواحف" ونظمناه، سنبدأ في هذا المقال بالعمل على شخصيات اللعبة (لاعب أساسي وأعداء). إذ سنبني المشهد اﻷول Player (وهو كائن أو عقدة) للاعب وآخر Mob للأعداء، ومن ميزات إنشاء مشهد مستقل لكل منهما هو إمكانية اختبارها بشكل مستقل وقبل أن ننشئ بقية أجزاء اللعبة. هيكلية العقدة نحتاج بداية إلى عقدة جذرية للاعب، وكقاعدة عامة، لا بد أن تعكس العقدة الجذرية للمشهد الوظيفة المرغوبة للكائن وما هو هذا الكائن. لهذا، انقر على زر "عقدة أخرى" وأضف عقدة من نوع Area2D إلى المشهد: سيعرض جودو أيقونة تنبيه إلى جوار العقدة في شجرة المشاهد، تجاهلها اﻵن وسنعود إليها لاحقًا. نتمكن باستخدام Area2D من استشعار الكائنات التي تتداخل أو تعمل ضمن اللاعب، وسنغير اسم العقدة الجديدة إلى Player بالنقر المضاعف عليها. وبعد إنشاء العقدة الجذرية، سنضيف عقدًا إضافية لمنحها مقدرات وظيفية أكبر. لكن قبل ذلك، علينا أن نتأكد من عدم تحريك أو تغيير العقد اﻷبناء عند النقر عليهم. لهذا انقر على اﻷيقونة الواقعة على يسار أيقونة القفل في شريط أدوات المشهد (سيعرض لك وصف اﻷداة عند تمرير مؤشر الفأرة فوقها العبارة "اجعل فروع العقدة المختارة غير قابلة للاختيار"): احفظ المشهد بالنقر على مشهد>حفظ أو اضغط Ctrl + S في ويندوز ولينكس أو Cmd + S في ماك أو إس. سوف نستخدم في مشروعنا أسلوب التسمية المتبع في محرك الألعاب جودو وهو كالتالي حسب لغة البرمجة المستخدمة: في لغة GDScript: نتبع أسلوب باسكال في اﻷصناف (الحرف اﻷول من كل كلمة كبير)، وفي الدوال والمتغيرات أسلوب اﻷفعى (تفصل بين كل كلمتين شرطة سفلية _)، أما الثوابت فتكتب كل حروفها بالشكل الكبير. في لغة #C: تسمى الأصناف والمتغيرات والتوابع بأسلوب باسكال، ونستخدم في تعريف الحقول الخاصة private والمتغيرات المحلية والمعاملات أسلوب سنام الجمل (الحرف اﻷول من كل كلمة كبير ما عدا الكلمة اﻷولى). وتأكد من كتابة أسماء التوابع بشكل دقيق عند ربط اﻹشارات. الرسم المتحرك للشخصية (Sprite) انقر على أيقونة العقدة Player وأضف عقدة ابن من نوع AnimatedSprite2D (استخدم Ctrl + A في ويندوز ولينكس) والتي تتولى أمور مظهر وتحريك اللاعب، ولاحظ وجود إشارة تحذير إلى جانب العقدة. تحتاج العقدة موردًا يُدعى "إطارات السبرايت SpriteFrames"، وﻹنشائه، ابحث عن الخاصية SpriteFrames ضمن النافذة الفرعية Animation في حاوية "الفاحص" ثم انقر على مربع النص empty واختر "جديدة SpriteFrame". انقر مجددًا لفتح لوحة "إطارات-اﻷرسومة". ستجد إلى اليمين قائمة بالرسومات، انقر على الافتراضية وسمها "walk"، ثم انقر على أيقونة إضافة إطار في الزاوية العليا اليمينية وأضف إطارًا آخر سمِّه "up". ابحث بعد ذلك عن الصور المناسبة في المجلد "art" في نظام الملفات وانقل الصور playerGrey_walk[1/2] إلى اﻹطار "walk" بالسحب واﻹفلات، أو بفتح الصورة من خلال أيقونة المجلد وكرر العملية بنقل الصورتين playerGrey_up[1/2] إلى اﻹطار "up". إن أبعاد الصور أكبر من أبعاد نافذة اللعبة، ولا بد من تصغير هذه الصور بالنقر على العقدة AnimatedSprite2D ومن ثم ضبط الخاصية Scale على القيمة Scale. ستجد هذه الخاصية في حاوية الفاحص تحت العنوان Node2D والقائمة "Transform تحويل": أضف أخيرًا عقدة من النوع CollisionShape2D لتكون ابنًا للعقدة Player، وتحدد هذه العقدة "صندوق التصادم" المحيط باللاعب أو حدود منطقة التصادم المحيطة به. وتلائمنا في هذا الصدد كائن من النوع CapsuleShape2D، لهذا انقر في "الفاحص" على المربع إلى جوار العنوان واختر "جديدة CapsuleShape2D". استخدم بعد ذلك مقبضي التحكم بالأبعاد (النقطتين الحمراوين) في نافذة المشهد لتغطية الأرسومة بالغلاف: عندما تنتهي من ذلك سيكون شكل مشهد اللاعب Player كالتالي: تأكد من حفظ المشهد مجددًا بعد هذه التغييرات. سنضيف تاليًا سكربت إلى عقدة اللاعب لتحريكه ثم نُعدّ آلية لترصد التصادم لنعرف إذا ما اصطدم اللاعب بشيء ما. كتابة الشيفرة اللازمة لتحريك اللاعب سنعمل في هذا القسم على كتابة شيفرة لتحريك اللاعب، وإعداده ليترصد التصدامات، لهذا، علينا إضافة بعض الخواص الوظيفية التي لا تقدمها العقد المتوفرة عن طريق إضافة سكربت أو كود برمجي إلى العقدة. انقر على العقدة Player ثم انقر على "إلحاق نص برمجي": لا داعي لتغيير أي شيئ في نافذة إلحاق نص برمجي، اترك كل شيء كما هو وانقر على زر "أنشئ". ملاحظة: إن كنت تريد إنشاء سكربت #C، اختر هذه اللغة من القائمة المنسدلة قبل النقر على "أنشئ". extends Area2D @export var speed = 400 # How fast the player will move (pixels/sec). var screen_size # Size of the game window. تُسمح لنا التعليمة export قبل المتغير speed بضبط قيمته في نافذة الفاحص. ولهذا اﻷمر فائدته إن أردت تعديل قيمة المتغير بالطريقة نفسها التي تعدّل فيها خاصيات أي عقدة موجودة أصلًا في جودو. انقر اﻵن على العقدة Player وسترى الخاصية موجودة ضمن قسم "متغيرات السكربت" في حاوية الفاحص (تحت نفس الاسم الذي يحمله ملف السكربت). وتذكر أن تغيير القيمة في هذا المكان سيلغي القيمة التي يحملها المتغير في السكربت. يتضمن السكربت player.gd تلقائيًا الدالتين ()ready_ و ()process_. فإن لم تختر القالب الافتراضي للسكربت أنشئ هاتين الدالتين. وتُستدعى الدالة ()ready_ عندما تدخل عقدة شجرة المشاهد وهو وقت مناسب لمعرفة أبعاد نافذة اللعبة func _ready(): screen_size = get_viewport_rect().size بإمكاننا اﻵن استخدام الدالة ()process_ لتحديد ما يفعله اللاعب، وتُستدعى هذه الدالة من أجل كل إطار ونستخدمها لتحديث العناصر في لعبتنا والتي نتوقع أن تتغير أحيانًا. فمن أجل لاعبنا لا بد من: التحقق من وجود دخل. تحريكه في الاتجاه المطلوب. تشغيل الرسوم المتحركة المناسبة. كما ذكرنا علينا بداية التحقق من الدخل، أي هل يضغط اللاعب على زر معين مثلًا؟ ففي لعبتنا هناك عناصر إدخال لأربعة اتجاهات علينا أن نتحقق منها. عُرّفت إجراءات الدخل في إعدادات المشروع تحت عنوان "خريطة الإدخال". وفيها نستطيع تعريف أحداث مخصصة وتعيين أزرار مختلفة، وأحداث تتعلق بالفأرة وغيرها من المدخلات. انقر على المشروع، ثم إعدادات المشروع لتفتح نافذة اﻹعدادات، ثم انقر على النافذة الفرعية "خريطة الإدخال" في الأعلى. اكتب بعد ذلك "move_right" (تحرك يمينًا) في الشريط العلوي وانقر الزر "أضف" ﻹضافة الإجراء move_right. علينا اﻵن أن نربط اﻹجراء بزر معين، لهذا انقر على أيقونة "+" إلى اليسار كي نفتح نافذة "تهيئة الحدث event configuration". كل ما عليك الآن هو النقر على الزر الذي تريد ربطه بالحدث سواء زر لوحة مفاتيح أو زر الفأرة. انقر الآن مفتاح السهم اليميني على لوحة المفاتيح وسيظهر الخيار تلقائيًا في مربع "يتم رصد المدخلات.." انقر بعد ذلك على "حسنًا" لتعيين المفتاح. كرر نفس الخطوات لربط الحركات الثلاث الباقية كالتالي: اربط move_left بالسهم اليساري. اربط move_up بالسهم للأعلى. اربط move_down بالسهم للأسفل. يجب أن تظهر خارطة المدخلات كالتالي: انقر اﻵن على "إغلاق" ﻹغلاق إعدادات المشروع. ملاحظة: ربطنا مفتاح واحد بكل إجراء دخل، لكنك تستطيع أن تربط أكثر من مفتاح أو زر عصا تحكم أو زر فأرة بإجراء الدخل نفسه. تستطيع أن تقرر إذا ما ضُغط زر باستخدام العبارة ()Input.is_action_pressed التي تعيد القيمة true إذا ضُغط الزر وfalse إن لم يُضغط. func _process(delta): var velocity = Vector2.ZERO # The player's movement vector. if Input.is_action_pressed("move_right"): velocity.x += 1 if Input.is_action_pressed("move_left"): velocity.x -= 1 if Input.is_action_pressed("move_down"): velocity.y += 1 if Input.is_action_pressed("move_up"): velocity.y -= 1 if velocity.length() > 0: velocity = velocity.normalized() * speed $AnimatedSprite2D.play() else: $AnimatedSprite2D.stop() بدأنا بضبط قيمة velocity على (0, 0) فلن يتحرك اللاعب افتراضيًا، وبعد ذلك تحققنا من كل المدخلات وأضفنا إلى المتغير velocity أو طرحنا منه للحصول على الاتجاه. فلو ضغطنا على السهم اليميني واليساري في نفس الوقت ستكون نتيجة المتجه velocity هي (1, 1)، وفي هذه الحالة نكون قد أضفنا حركة أفقية وعمودية في نفس الوقت، وسيتحرك اللاعب بشكل أسرع بالاتجاه القطري موازنة بالحالة التي يتحرك فيها أفقيًا فقط. لكن بإمكاننا منع حدوث هذا اﻷمر بتسوية قيمة السرعة بأن نضبط قيمتها على 1 ثم نضربه بالقيمة المطلوبة ولن تكون السرعة في الاتجاه القطري عندها أكبر. كما علينا أن تحقق فيما لو تحرّك اللاعب كي نستدعي الدالتين ()play و ()stop في AnimatedSprite2D يُعيد $ عقدة معينة إن كانت موجودة في نفس المسار النسبي ويعيد null إن لم تكن موجودة في هذا المسار. وطالما أن AnimatedSprite2D هي عقدة ابن للعقدة الحالية، بإمكاننا استخدام AnimatedSprite2D$. وطالما حددنا الآن اتجاه الحركة، بإمكاننا تحديث موقع اللاعب. كما نستطيع باستخدام الدالة ()clamp منع اللاعب من مغادرة الشاشة وتقييده ضمن مجال محدد. أضف الشيفرة التالية إلى أسفل الدالة ()process_ (انتبه إلى أن الشيفرة غير منزاحة تحت else? position += velocity * delta position = position.clamp(Vector2.ZERO, screen_size) انقر على الزر "شغل المشهد الحالي" (F6 أو Cmd+R في ماك أو إس) وتأكد من قدرتك على تحريك اللاعب ضمن المشهد في جميع الاتجاهات. اختيار الرسوم المتحركة بإمكاننا تحريك اللاعب الآن، لكننا نحتاج إلى تغيير الرسم المتحرك الذي يمثّل الكائن وفقًا لاتجاهه. ليدنا الرسم "تحرّك" والذي يعرض اللاعب وهو يتحرك يمينًا، ولا بد من قلبه أفقيًا حتى يعبّر عن التحرك نحو اليسار باستخدام الخاصية flip_h. وكذلك لدينا الرسم "up" الذي يجب أن يُعكس عموديًا لتمثيل الحركة نحو اﻷسفل باستخدام الخاصية flip_v. لهذا عليك اضافة الشيفرة التالية إلى أسفل الدالة ()process_: if velocity.x != 0: $AnimatedSprite2D.animation = "walk" $AnimatedSprite2D.flip_v = false # اطلع على املاحظة التالية بخصوص اﻹسناد المنطقي $AnimatedSprite2D.flip_h = velocity.x < 0 elif velocity.y != 0: $AnimatedSprite2D.animation = "up" $AnimatedSprite2D.flip_v = velocity.y > 0 ملاحظة: يُعد استخدام طريقة اﻹسناد المنطقي في هذه الشيفرة اختصارًا شائعًا. فما نفعله هو اختبار موازنة (منطقي) وإسناد قيمة منطقية، لهذا يمكننا تنفيذ اﻷمرين معًا. وما يفعله هذا الاختصار مطابق لعمل الشيفرة التالية: if velocity.x < 0: $AnimatedSprite2D.flip_h = true else: $AnimatedSprite2D.flip_h = false شغّل المشهد وتأكد من تغيّر الرسم مع تغير اتجاه الحركة. عندما تتأكد أن كل شيء يعمل كما يجب، أضف السطر التالي إلى الدالة ()ready_ كي يختفي اللاعب في بداية اللعبة. hide() إعداد التصادمات نريد من اللاعب Player أن يعرف متى يستطدم بالعدو، لكننا لم نصنع اﻷعداء بعد! لا بأس بذلك لأننا سنستخدم حاليًا إشارات جودو لننجز اﻷمر. أضف اﻷسطر التالية إلى أعلى السكربت. فإن كنت تستخدم GDScript، أضفها بعد العبارة extends Area2D، وإن كنت تستخدم لغة #C ضعها بعد العبارة public partial class Player: Area2D. signal hit تُعرّف التعليمة السابقة إشارة خاصة باسم "hit" يبثها اللاعب (يرسلها) عندما يتصادم مع عدو. وسنستخدم الكائن Area2D لالتقاط هذه اﻹشارة. اختر العقدة Player وانقر على النافذة الفرعية "عقدة" ضمن لوحة "الفاحص" كي تعرض قائمة اﻹشارات التي يمكن للاعب بثها: لاحظ وجود إشارتنا المخصصة "hit" أيضًا ضمن تلك القائمة. وطالما أن العدو سيكون عقدة من النوع RigidBody2D، سنحتاج إلى الإشارة body_entered(body: Node2D). أوجد تلك اﻹشارة في القائمة ثم انقر عليها بالزر اليميني واختر "يتصل" لتظهر نافذة "قم بوصل اﻹشارة إلى دالة". لا حاجة لتغيير أي شيء، بل انقر فقط على "وصل" وسيوّلد جودو تلقائيًا الدالة المناسبة في الشيفرة: لاحظ اﻷيقونة الخضراء إلى يسار الشيفرة المخصصة للإشارة وتدل على أن إشارة متصلة مع هذه الدالة. أضف اﻵن الشيفرة التالية إلى الدالة: func _on_body_entered(body): hide() # يختفي اللاعب بعد أن يصطدم. hit.emit() # Must be deferred as we can't change physics properties on a physics callback. $CollisionShape2D.set_deferred("disabled", true) في كل مرة يصدم بها العدو اللاعب ستُرسل اﻹشارة، ولا بد من تعطيل التصادم الخاص باللاعب كي لا نفعّل اﻹشارة hit أكثر من مرة. ملاحظة: قد ينتج عن تعطيل غلاف التصادم الخاص بالمنطقة خطأ إن حدث اﻷمرأثناء معالجة المحرّك للتصادمات. لهذا استخدم الدالة ()set_deferred ﻹخبار المحرّك ألا يعطّل غلاف التصادم حتى يرى أن اﻷمر آمن. أضف أخيرًا دالة نستدعيها ﻹعادة ضبط اللاعب عندما تبدأ لعبة جديدة func start(pos): position = pos show() $CollisionShape2D.disabled = false إنشاء شخصية العدو حان الوقت اﻵن ﻹنشاء اﻷعداء الذي يجب على اللاعب تفاديهم. ولن يكون سلوكهم معقدًا جدًا بل سيتحركون عشوائيًا على أطراف الشاشة، يأخذون اتجاهًا عشوائيًا ويتحركون وفق خط مستقيم. نبدأ عملنا بإنشاء مشهد باسم Mob يشكل الأساس الذي نشتق منه أي عدد نحتاجه من هذه الكائنات في لعبتنا. إعداد العقدة انقر على مشهد>مشهد جديد ثم أضف العقد التالية وفق الترتيب المبين: RigidBody2D: AnimatedSprite2D CollisonShape2D VisibleOnScreenNotifier2D ولا تنسَ ضبط العقدة اﻷم كي لا يمكن اختيار اﻷبناء كما فعلنا سابقًا عند بناء شخصية اللاعب. اختر بعد ذلك العقدة Mob ثم اضبط قيمة الخاصية Gravity Scale على 0، وذلك في قسم RigidBody2D ضمن الفاحص. يمنع هذا اﻷمر الأعداء من السقوط للأسفل. افتح المجموعة "Collision" الموجودة في اللوحة "CollisionObject2D" تحت "RigidBody2D" ضمن الفاحص. الغ بعد ذلك تفعيل الخيار 1 ضمن الخاصية Mask بالنقر عليه كي لا تتصادم اﻷعداء فيما بينها. اضبط العقدة كما فعلنا في مشهد اللاعب، وهنا نستخدم ثلاث رسومات هي fly و swim و walk، وهنالك صورتان لكل مشهد في المجلد "art". تُضبط الخاصية Animation Speed (سرعة التحريك) لكل رسم متحرك على حدى، لهذا اضبط كلًا منها على 3: بإمكانك اﻵن النقر على الزر "تشغيل الرسم المتحرك" إلى يسار "سرعة التحريك" لعرض الرسوم المتحركة. سنختار إحدى هذه الرسوم عشوائيًا حتى يكون للأعداء أشكال مختلفة، وكما هو الحال مع رسومات اللاعب لا بد من تصغير هذه الرسومات، وذلك بضبط الخاصية Scale على (0.75, 0.75) (راجع فقرة إنشاء اللاعب لتتذكر كيفية العمل). علينا اﻵن أن نضيف غلاف CapsuleShape2D من أجل التصادمات كما فعلنا مع اللاعب. ولكي يتماشى الغلاف مع الرسم المتحرك لا بد من تدويره بضبط الخاصية Rotation Degrees على 90 (تحت لوحة "Node2D" والقائمة "Transform" ضمن الفاحص). كتابة شيفرة تحريك العدو أضف سكربت إلى العقدة Mob كما فعلنا سابقًا: extends RigidBody2D نشغّل باستخدام الدالة ()ready_ الرسومات ونختار عشوائيًا أحد اﻷنواع الثلاث لهذه الرسوميات كالتالي: func _ready(): var mob_types = $AnimatedSprite2D.sprite_frames.get_animation_names() $AnimatedSprite2D.play(mob_types[randi() % mob_types.size()]) ما تفعله هذه الشيفرة هو الحصول على أسماء الرسومات من الخاصية frames للعقدة AnimatedSprite2D، وستكون النتيجة مصفوفة تضم اﻷنواع الثلاث: ["walk", "swim", "fly"]. ثم نختار عشوائيًا رقمًا بين 0 و 2 لاختيار أحد اﻹطارات الثلاث من المصفوفة السابقة (يبدأ العدد في المصفوفات من 0) بتطبيق التعليمة randi() % n، والتي تختار عددًا صحيحًا عشوائيًا بين 0 و n-1. وأخيرًا نحتاج إلى شيفرة كي يحذف العدو نفسه عندما يغادر شاشة اللعبة. ولتنفيذ ذلك صل الإشارة ()Screen_exited العائدة للعقدة ()VisibleOnScreenNotifier إلى العقدة Mob (راجع فقرة وصل إشارة اللاعب التي نفّذناها سابقًا) ثم أضف الأمر ()queue_free إلى الدالة التي تظهر في السكربت كالتالي: func _on_visible_on_screen_notifier_2d_screen_exited(): queue_free() وهكذا سيكتمل مشهد العدو. الخلاصة بهذا نكون قد وصلنا لنهاية مقالنا الحالي الذي أنشأنها فيه مشهدين من مشاهد اللعبة ثنائية الأبعاد في محرك جودو، تابع معنا المقال التالي الذي سنقوم فيه بضم المشهدين معًا والسماح للأعداء بالتكاثر على الشاشة والحركة لتحويل المشاهد إلى لعبة تعمل كما خططنا لها. ترجمة -وبتصرف- للمقالات: Creating the Player scene و Coding the player و Creating the enemy اقرأ أيضًا المقال السابق: بناء لعبة ثنائية البعد عبر محرك الألعاب Godot - الجزء الأول: تجهيز الملفات وضبط الإعدادات كيف تحصل على أفكار ألعاب فيديو ناجحة تعرف على أشهر لغات برمجة الألعاب مدخل إلى محرك الألعاب جودو Godot
  4. ننقلك في سلسلة المقالات التالية خطوة بخطوة لإنشاء لعبة كاملة ثنائية البعد باستخدام محرّك اﻷلعاب جودو Godot. وفي نهاية السلسلة ستكون قد أنجزت لعبة بسيطة كتلك الموضحة في الصورة التالية: وسنتعلم من خلال هذه السلسلة كيفية عمل محرّر محرك الألعاب جودو Godot، وكيفية هيكلة المشروع، ومن ثم ستتعلم خطوات بناء اللعبة بشكل عملي. ملاحظة: هذا المقال هو مدخل إلى محرك اﻷلعاب جودو، ويفترض أنك تتمتع ببعض الخبرات البرمجية لاستخدام لغات برمجة الألعاب وبرمجة لعبتك الإلكترونية من خلالها. فإن كنت جديدًا في عالم البرمجة. ننصحك بالعودة إلى أكاديمية حسوب التي تضم عددًا كبيرًا من المقالات والمواضيع التي تناسب القادمين الجدد وتقدم أفضل الدورات التعليمية للبرمجة من الصفر وحتى الاحتراف. سوف نطلق على لعبتا اسم "تفادي الزواحف Dodge the creeps"، ومن المفترض أن تبتعد شخصية اللعبة عن اﻷعداء قدر اﻹمكان. ستتعلم من خلال هذه السلسلة كيف تقوم بما يلي: تنشئ لعبة مكتملة ثنائية البعد باستخدام محرك الألعاب جودو. تهيكل مشروع لعبة بسيطة. تحرك شخصية اللعبة وتغيير شكلها. تنشر أعداء عشوائيًا. تعيد نتيجة اللعبة. لماذا نطور لعبة ثنائية البعد 2D؟ إن كنت جديدًا في تطوير اﻷلعاب أو لا تألف بيئة جودو، ننصحك ان تبدأ بتعلم تصميم اﻷلعاب ثنائية البعد، فهي تسمح لك في تعلم بيئة العمل وترتاح فيها قبل أن تبدأ اﻷلعاب ثلاثية الأبعاد التي تميل أكثر إلى التعقيد. خُصِّصَ هذا المقال والمقالات اللاحقة للمبتدئين الذين لديهم أساسيات في التعامل مع محرك جودو، فإن كنت جديدًا في البرمجة ويصعب عليك كتابة الأكواد من الصفر، بإمكانك الاطلاع على الشيفرة المصدرية للعبة عبر جيت-هب وفهمها. كما حضرنا مسبقًا بعض الملحقات التي تحتاجها، لهذا سنقفز مباشرة إلى الشيفرة التي يمكنك تحميلها من المستودع المخصص على جيت-هب. إعداد المشروع سنُعّد في هذا المقال مشروعنا وننظمه، لهذا شغّل محرك ألعاب جودو وأنشئ مشروعًا جديدًا. ليس عليك سوى تحديد مسار مناسب لتخزين المشروع وبإمكانك ترك بقية القيم كما هي. بعدها عليك تحميل الأرشيف الذي يتضمّن كافة ملفات الصور والمقاطع الصوتية التي سنستخدمها في صنع اللعبة ثنائية الأبعاد الخاصة بنا، ثم استخرج محتوياته وانقل المجلدين ‎/art و ‎/fonts إلى مجلد اللعبة. يجب أن يبدو مجلد اللعبة مشابهًا للقطة الشاشة التالية: صُممت هذه اللعبة لنمط العرض الشاقولي portrait، لهذا لا بد من تعديل قياس نافذة اللعبة. انقر على المشروع ثم اختر إعدادات المشروع لفتح نافذة اﻹعدادات ثم افتح في العمود اليميني القائمة "عرض display" ثم انقر على "نافذة window". واضبط بعد ذلك اتساع نافذة العرض viewport width على 480 وارتفاعها على 720. وتحت الخيار "تمدد Stretch " اضبط "الوضع Mode" على القيمة canvas_items ونسبة العرض على القيمة keep، حيث يساهم هذان الخياران في اتساق العرض على شاشات مختلفة الأبعاد. تنظيم المشروع سنصنع في هذا المشروع ثلاثة مشاهد مستقلة هي Player و Mob وHUD بحيث تجتمع كلها في المشهد الرئيسي Main. ومن اﻷفضل في المشاريع اﻷكبر أن تنشئ مجلدًا يضم المشاهد المختلفة والسكربتات الملحقة بها، لكن لمشروع صغير كهذا، بإمكانك تخزينها في المجلد الجذري للمشروع الذي يُعرّف بالعنوان //:res . وستجد مجلد المشروع في حاوية "نظام الملفات" في الزاوية اليسارية السفلى. الخلاصة تعرفنا في مقال اليوم على أولى مراحل برمجة لعبة ثنائية الأبعاد في محرك الألعاب جودو Godot، وبدأنا بتحديد الشخصيات والمشاهد التي تضمها اللعبة، وحددنا طريقة تنظيم ملفاتها، وندعوك لمتابعة السلسلة التالية من هذه المقالات لتتعرف على الخطوات التالية العملية لإنجاز اللعبة وبرمجتها. ترجمة -وبتصرف- للمقالين: your first 2D game و Setting up the project اقرأ أيضًا المقال السابق: تعلم الميزات الجديدة في محرك الألعاب جودو وطرح الأسئلة حوله إعداد محرك الألعاب جودو Godot للعمل مع قاعدة البيانات SQLite مدخل إلى محرك الألعاب جودو Godot مطور الألعاب: من هو وما هي مهامه
  5. بعد أن اطلعت في مقالات سابقة على مفاهيم محرك الألعاب جودو، حان وقت الحديث عن التصميم الذي يميزه، فكل محرك ألعاب مختلف عن اﻵخر ويلبي حاجات مختلفة. إذ يقدم كل محرك ألعاب مجالًا من الميزات المختلفة لكن تصميم كل محرك ألعاب متفرد عن اﻵخر. ويقود هذا اﻷمر إلى سياقات عمل مختلفة وطرق مختلفة في هيكلة اﻷلعاب. ويعود السبب في ذلك إلى الفلسفة المختلفة في التصميم لكل محرّك. نساعدك في هذا المقال على فهم طريقة عمل جودو انطلاقًا من بعض الدعائم البنيوية للمحرك، فما نعرضه ليس قائمةً بالميزات ولا موازنة بين المحركات. ولكي تعرف ما يناسبك من محركات، لابد من اختبارها بنفسك وفهم تصميمها ومحدوديتها. التصميم والتأليف كائني التوجه يتبنى محرك الألعاب جودو مفهوم التصميم كائني التوجه كأساس له من خلال نظام المشاهد المرن والتسلسل الهرمي للعقد. كما يحاول أن يبتعد عن اﻷنماط البرمجية البحتة كي يقدم طريقة واضحة ومباشرة لهيكلة ألعابك. فمن ناحية أولى، يسمح لك جودو في تأليف أو تجميع المشاهد. إذ تستطيع إنشاء مشهد لأضواء وامضة BlinkingLight وآخر لمصابيح مكسورة BrokenLantern تستخدم اﻷضواء الوامضة والتعامل معها ككائنات جاهزة. وستتمكن باستخدامها من بناء مدينة مملوءة بالمصابيح المكسورة ومن ثم تغيّر لون الضوء الوامض وتخزّين التغيرات لتتغير عندها حالة المصابيح المكسورة في المدينة دفعة واحدة. وفوق كل ذلك يدعم جودو الوراثة وهو أحد المبادئ الأساسية في البرمجة كائنية التوجه oop، فقد يكون مشهد جودو سلاحًا أو شخصية أو غرضًا ما أو بابًا أو مستوى أو جزء من مستوى وبالمختصر أي شيء تريده. ويعمل المشهد عمل الصنف class في الشيفرة الصرفة، ما عدا أنك حر في تصميمه من خلال المحرر مستخدمًا الشيفرة فقط أو مزيجًا من الاثنين. تختلف المشاهد في جودو عن الكائنات الجاهزة prefab في محركات اﻷلعاب ثلاثية اﻷبعاد اﻷخرى في إمكانية الوراثة عنها أو توسيعها. فقد تُنشئ ساحرًا بتوسعة مشهد الشخصية مثلًا. وعندما تُحدّث الشخصية في المحرر ستتحدث معها شخصية الساحر أيضًا. سيمكنك ذلك من بناء مشروعك كي يتطابق التصميم مع هيكلية الشيفرة. وتجدر الملاحظة أن جودو يقدّم أنواعًا مختلفة من الكائنات التي تُدعى عقدًا Nodes، ولكل منها غاية محددة. والعقد أجزاء من شجرة وترث دائمًا من العقدة اﻷب وصولًا إلى الصنف الرئيسي Node. وعلى الرغم من وجود عقد في جودو مثل اﻷشكال المتصادمة التي تستخدمها فيزيائية العقدة اﻷب، تُعد معظم العقد مستقلة عن بعضها. وبعبارة أخرى، لا تعمل العقد كما تعمل المكوّنات components في محركات ألعاب أخرى. فالعقد Sprite2D و Node2D و CanvasItem و Node، تمتلك جميع الخاصيات والميزات للأصناف اﻵباء كالتحويلات أو القدرة على رسم أشكال محددة وتصييرها باستخدام معالج لوني shader محدد. حزم حصرية بالكامل يحاول محرك الألعاب جودو تزويد المستخدمين بأدوات خاصة تلبي معظم احتياجاتهم. إذ يمتلك المحرّك فضاء عمل مخصص لكتابة السكربتات، ومحرر رسوميات، ومحرر خرائط، ومحرر معالج لوني، ومنقح، ومحلل أداء، باﻹضافة إلى قدرته على عرض التغييرات مباشرة على جهازك المحلي أو جهاز متصل عبر الشبكة. إن الغاية من ذلك كله تقديم حزمة متكاملة من اﻷدوات ﻹنشاء اﻷلعاب تحسين تجربة المستخدمين. بإمكانك بالطبع العمل مع برامج خارجية نظرًا لدعمه للإضافات plug-in، والتي تستطيع أن تنشئها بنفسك أيضًا! ويعود وجود لغة GDScript الخاصة بجودو إلى هذا السبب جزئيًا إضافة إلى دعمه لغة #C. فلغة GDScript مصممة لتلائم حاجات المطورين والمصممين ومتكاملة تمامًا مع المحرّك والمحرر. وتتيح لك GDScript كتابة شيفرة اعتمادًا على صياغة اﻹزاحة أو المسافات البادئة indentation، وتتعرف على اﻷنواع، وتزودك بميزة اﻹكمال التلقائي. وتُعد هذه اللغة من لغات برمجة الألعاب وتوفر شيفرة سهلة ومفهومة وتضم أنواعًا مخصصة مثل Vectors و Colors. ومع GDExtension يمكنك كتابة شيفرة عالية اﻷداء باستخدام لغات مصرّفة مثل C و ++C و Rust وبايثون (باستخدام Cython) دون إعادة تصريف المحرّك. ملاحظة: لا يقدم فضاء العمل ثلاثي الأبعاد نفس العدد من الميزات التي يقدمها ثنائي اﻷبعاد، ويحتاج إلى برامج خارجية أو إضافات لإنشاء التضاريس، وتحريك شخصيات الألعاب المعقدة وهكذا. مع ذلك، يزودك جودو بواجهة برمجية متكاملة لتوسعة وظائف المحرر باستخدام شيفرة اللعبة، سنرى ذلك لاحقًا في هذا المقال. (محرر وهو إضافة على جودو 2 ويساعد على إدارة الحالة والانتقالات بصريًا) محرّك مفتوح المصدر يقدّم جودو قاعدة برمجية مفتوحة المصدر بالكامل وفق ترخيص MIT. ويعني ذلك أن كل التقنيات التي تأتي معه هي حرة أيضًا. وقد طوّرت معظم أجزاء المحرّك من الصفر من قبل مساهمين. ويمكن لأي شخص استخدام اﻹضافات المناسبة لمشروعه ولا يعني ذلك أن تُشحن هذه اﻹضافات مع المحرك. من اﻷمثلة عليها نجد Google AdMob أو FMOD. وأيًا منها يمكن أن يأتي على شكل إضافة مصدرها طرف آخر. وتعني القاعدة البرمجية المفتوحة من ناحية أخرى أنه بإمكانك التعلم من محرّك الالعاب وتوسيعه كما تشاء، وتستطيع تنقيح اﻷلعاب بسهولة، إذ يطبع جودو رسائل الخطأ من خلال متتبع المكدّس stack tracer حتى لو اتت اﻷخطاء من المحرّك نفسه. ملاحظة: لا يؤثر ذلك على العمل الذي تنفذّه على جودو إطلاقًا. فلن ترتبط أي قيمة نصيّة بالمحرّك أو أي شيء تفعله عليه. محرّك يطوّره مجتمعه يُطوّر محرك الألعاب جودو من قبل مجتمعه الخاص، فهو منهم ولهم ولجميع مطوري اﻷلعاب، وحاجات ونقاشات المستخدمين هو اﻷساس الذي يقود تطوير نواته. وتركّز الميزات الجديدة التي يقدمها مطوّرو النواة على ما يقدم الفائدة لمعظم مستخدميه، والقلة فقط من مطوري النواة يعملون رسميًا بدوام كامل. لكن المشروع يضم أكثر من 600 مساهم حتى لحظة كتابة هذه المقالة. فالمبرمجون المساهمون يعملون على تطوير الميزات التي يحتاجونها لأنفسهم لهذا سترى تحسينات من جميع النواحي تظهر معًا عند كل إصدار رئيسي للمحرك. محرر جودو هو في الواقع لعبة جودو يعمل محرر جودو على محرّك اللعبة ويستخدم واجهة المحرّك الرسومية ويمكنه إعادة تحميل الشيفرة والمشاهد مباشرة عند اختبار مشروعك أو تشغيل شيفرة اللعبة ضمن المحرر. أي بإمكانك استخدام نفس الشيفرة في والمشاهد في ألعابك أو بناء إضافات وتوسيع المحرر. ويعطي ذلك مصداقية ومرونة لواجهة المستخدم فهي تدعم المحرر ذاته. فعندما تستخدم التعليمة tool@ ستتمكن من تشغيل شيفرة اللعبة ضمن المحرر. (محرر RPG in a Box هو محرر صمم باستخدام جودو 2 ويستخدم واجهة جودو الرسومية لمنظومته البرمجية المبنية على أساس العقد) ضع التعليمة tool@ في بداية ملف GDScript وستعمل الشيفرة ضمن المحرر. يساعدك ذلك على إدراج وتصدير الإضافات وإنشاء إضافة مخصصة مثل محررات مخصصة للمراحل أو إنشاء سكربتات لها نفس العقد وترتبط بنفس الواجهة البرمجية التي تستخدمها في مشروعك. ملاحظة: كُتب محرر جودو بالكامل باستخدام لغة ++C وصُرّف إلى الصيغة الثنائية. ويعني ذلك أنه من غير الممكن إدراجه كمشروع نمطي على شكل ملف project.godot. محركان منفصلان ثنائي البعد وثلاثي البعد من جودو. يوفّر جودو محركين مخصصين ثنائي وثلاثي البعد. وكنتيجة لذلك ستكون وحدة القياس اﻷساسية للمشهد ثنائي البعد هي البكسل. وعلى الرغم من أن المحركين منفصلين، يمكنك تصيير المشاهد ثنائي البعد في المحرّك ثلاثي البعد والعكس صحيح، كما يمكنك كذلك تضمين الشخصيات والواجهات ثنائية البعد في العالم ثلاثي اﻷبعاد. الخلاصة بهذا تكون قد وصلت لنهاية مقال اليوم الذي ألقينا فيه نظرة عامة عن ميزات محرك الألعاب مفتوح المصدر جودو Godot، ووضحنا أسلوب التصميم المتبع في هذا المحرك وكيفية استخدامه في تطوير الألعاب، وأهم الميزات التي يدعمها مثل التصميم كائني التوجه والوراثة، بالإضافة إلى الأدوات والميزات الحصرية المتوفرة في المحرك، ودعمه لتصميم الألعاب ثنائية وثلاثية الأبعاد مع إمكانية تفاعلهما معًا في تطوير الألعاب، وسلطنا الضوء على الجهود المبذولة من قبل مجتمع مطوري جودو في تطوير المحرك وتحسينه باستمرار لضمان أفضل تجربة استخدام. ترجمة -وبتصرف- لمقال: Godot's design philosophy اقرأ أيضًا تعلم الميزات الجديدة في محرك الألعاب جودو وطرح الأسئلة حوله إعداد محرك الألعاب جودو Godot للعمل مع قاعدة البيانات SQLite تعرف على أهمية صناعة الألعاب الإلكترونية أشهر أنواع الألعاب الإلكترونية
  6. يُعد جودو محرّك ألعاب غني بالميزات، وهنالك الكثير لتتعلمه. لهذا سنشرح في هذا المقال كيفية استخدام دليل العمل على اﻹنترنت، والمراجع إلى الشيفرة والانضمام إلى مجتمع جودو لتعلم ميزات وتقنيات جديدة. الاستفادة القصوى من هذا المقال ما سنوضحه في هذا المقال هو طريقة التعامل دليل الاستخدام "user manual" الخاص بمحرك ألعاب جودو والذي يوثّق جميع مفاهيم محرّك الألعاب وميزاته المتاحة. فعندما تتعلم موضوعًا جديدًا، يمكنك البدء في تصفح القسم المخصص لهذا الموضوع في دليل المستخدم هذا. إذ تتيح لك القائمة اليمينية استكشاف مواضيع عامة عن محرك الألعاب، بينما يساعدك شريط البحث على إيجاد صفحات محددة. فإن وجدت صفحة خاصة بالموضوع ستكون مرتبطة غالبًا بصفحات أخرى متعلقة به يترافق هذا الدليل مع مراجع للأصناف "class reference" تشرح لك كل صنف أو دالة أو خاصية متاحة في جودو. فبينما يتحدث الدليل عن الميزات العامة والمفاهيم وكيفية استخدام المحرر، يتحدث مرجع اﻷصناف عن طريقة استخدام الواجهة البرمجية المستخدمة في كتابة سكربتات جودو Godot. وبإمكانك الوصول إلى معلومات هذا المرجع عبر اﻹنترنت أو محليًا. فكي تتمكن من تصفحها محليًا عبر محرر جودو كل ما عليك هو بالانتقال إلى "مساعدة Help" > "البحث في المساعدة Search Help" أو بالضغط على المفتاح F1: أما إن أردت البحث عن طريق اﻹنترنت انتقل إلى قسم مرجع اﻷصناف، وستدلك صفحة المرجع على ما يلي: أين هو موقع الصنف في التسلسل الهرمي، إذ يمكنك النقر على الروابط العليا للانتقال إلى الأصناف اﻵباء والاطلاع على الخاصيات والتوابع الموروثة. ملخص عن وظيفة الصنف وتوضيح حالات استخدامه. شرح خاصيات الصنف وتوابعه و إشاراته و معداته وثوابته. الربط مع صفحات الدليل التي تشرح الصنف أكثر. ملاحظة: إن كان دليل المستخدم أو مرجع الأصناف مفقودًا أو لم يحو على معلومات كافية، يمكنك فتح طلب من مستودع توثيق جودو على جيت هب للإبلاغ عن اﻷمر. بإمكانك النقر مع الضغط على المفتاح Ctrl على أية رابط نصي يمثل اسم صنف أو خاصية أو تابع أو إشارة أو ثابت للانتقال إليه. تعلم التفكير مثل المبرمجين إن موضوع تعلم أساسيات البرمجة وطريقة تفكير مطوري اﻷلعاب خارج سياق توثيق جودو لكنه أمر أساسي لك إن اردت أن تصبح مطور ألعاب . لذا إن كنت جديدًا في عالم البرمجة وكنت مهتمًا بتخصص برمجة وصناعة الألعاب الإلكترونية فننصحك بأن تُلمَّ قبل ذلك بأياسيات البرمجة قبل البدء، ويمكنك الاعتماد على أحد المصدرين التاليين: أكاديمية حسوب التي تقدم لك كمًا كبيرًا من المقالات المتخصصة بتعلم مختلف لغات البرمجة إضافة إلى دورات تدريبية عملية تبدأ بك من الصفر وحتى الاحتراف صممها وقدمها مبرمجون محترفون على دراية كاملة بمتطلباتك وتطلعاتك. موسوعة حسوب التي تعد أكبر مرجع باللغة العربية لتوثيق أشهر لغات البرمجة ومن بينها Python و JavaScript والعديد من اللغات والتقنيات الأخرى. التعلّم من خلال مجتمع جودو يتميز محرّك جودو بمجتمع يتطور ويزداد تعداده باستمرار. فإن واجهتك مشكلة ما وأردت المساعدة في فهم طريقة عمل شيء ما، بإمكانك سؤال مستخدمين آخرين ينتمون إلى أي من مجتمعات جودو النشطة. وأفضل مكان لطرح اﻷسئلة وإيجاد حلول لاسئلة طرحت مسبقًا هو الموقع الرسمي للأسئلة واﻷجوبة ask.godotengine . إذ تظهر الإجابات في نتائج محرّك البحث وتُخزّن ليستفيد اﻵخرون من النقاشات التي تدور في المنصة. وبمجرد أن تطرح سؤالًا، بإمكانك أن تستخدم رابطه لمشاركته في منصات أخرى. لكن قبل أن تطرح سؤالًا، تأكد من وجود أجوبة مسبقة عنه في هذه المنصة أو ابحث عنها باستخدام محرّك البحث الذي تفضلّه. الطريقة الصحيحة لطرح الأسئلة حول محرك جودو إن طرحك للسؤال بشكل جيد وتقديم تفاصيل دقيقة يساعد اﻵخرين في اﻹجابة عن سؤالك بسرعة. وننصحك عند طرح السؤال أن يتضمن المعلومات التالية: وصف الغاية من السؤال: يجب أن تشرح ما الذي تحاول فعله من وجهة نظر تصميمية. فإن لم تتمكن من تصور طريقة لتطبيق الحل، قد تكون هناك حلول أخرى أبسط لتحقيق نفس الغاية. مشاركة رسالة الخطأ كما هي تمامًا: إن كان هناك خطأ. انسخ رسالة الخطأ بدقة من المنقح بالنقر على أيقونة "انسخ الخطأ Copy Error". فمعرفة رسالة الخطأ تساعد أعضاء المجتمع في تحديد السبب الذي أدى لوقوع المشكلة. مشاركة عينة من الشيفرة: إن كان الخطأ في الشيفرة. فلن يتمكن اﻵخرون من مساعدتك في حل المشكلة دون رؤية الشيفرة. لذا شارك الشيفرة على شكل نص مباشرة بنسخ ولصق جزء من الشيفرة في رسالتك أو استخدام مواقع مثل Pastebin لمشاركة الملفات الطويلة. مشاركة لقطة شاشة: لحاوية المشهد في المحرر إضافة إلى شيفرتك. فالشيفرة التي تكتبها تؤثر على عقد عقد المشاهد. إذًا عليك التفكير بالمشاهد كجزء من شيفرتك المصدرية. كذلك لا تستخدم هاتف محمول لالتقاط الصور، فالدقة المنخفضة والانعكاسات قد تُصعّب فهم الصورة. لهذا استخدم الأداة التي يوفّرها نظام التشغيل لديك لالتقاط صورة للشاشة (مثل الزر Print Screen). كما يمكنك استخدام ShareX في ويندوز مثلًا أو FlameShot في لينكس. مشاركة فيديو للعبتك وهي تعمل: أمر مفيد جدّا. يمكنك استخدام برامج مثل OBS Studio أو Screen to GIF لالتقاط فيديو لسطح مكتبك، ثم استخدام خدمات مثل streamable أو مزوّد سحابي لرفع ومشاركة الفيديو. اﻹشارة إلى نسخة جودو التي تستخدمها: وخاصة إن لم تكن النسخة مستقرة stable version. لأن الجواب قد يختلف نتيجة لتغير الميزات والواجهة باستمرار. باتباعك اﻹرشادات السابقة ستزيد فرص حصولك على الجواب الدقيق الذي تبحث عنه، وسيوفر وقتك ووقت اﻷشخاص الذين يساعدونك في حل مشكلتك. مصادر تعليمية حول محرك الألعاب جودو إن كنت تبحث عن دورات حول إنشاء نوع لعبة إلكترونية مثل خطوات إنشاء لعبة تقمص الأدوار "Role-Playing Games" أو غيرها من أنواع الألعاب الإلكترونية، ننصحك بالاطلاع على قسم المصادر والدورات التعليمية Tutorials and resources الذي يعرض محتوى متخصصًا يقدمه مجتمع جودو. وإذا كنت مهتمًا بمعرفة المزيد من التفاصيل عن محرك ألعاب جودو Godot أو لغة برمجة الألعاب GDScript وطريقة تطوير الألعاب ثنائية الأبعاد وثنائية الأبعاد باللغة العربية، فننصحك بالاطلاع على سلسلة المقالات المنشورة في أكاديمية حسوب تحت وسم godot، كما يمكنك الاطلاع على العديد من المقالات المفيدة في قسم مقالات صناعة الألعاب الذي ينشر بصورة دورية العديد من المقالات التي تفيدك كمطور ألعاب. ويمكنك كذلك طرح أي سؤال أو مشكلة تعترضك خلال برمجة لعبتك الخاصة في قسم الأسئلة والأجوبة في الأكاديمية أو في مجتمع حسوب IO. الخلاصة تعرفنا في مقال اليوم على طريقة الاستفادة من الميزات الجديدة التي يوفرها لك محرك الألعاب جودو Godot وأهمية التفكير البرمجي لك كمطور ألعاب وكيفية طرح سؤال حول أي مشكلة تقنية تصادفك خلال صناعة لعبتك بطريقة صحيحة وحلها بسرعة وكفاءة، وأخيرًا ختمنا المقال بمصادر تعليمية مفيدة حول Godot وتطوير الألعاب. ترجمة -وبتصرف- لمقال: Learning new features اقرأ أيضًا دليلك الشامل إلى بناء كاميرا خاصة بشاشات اللمس في محرّك اﻷلعاب جودو تعرف على محرر محرك اﻷلعاب جودو Godot إعداد محرك الألعاب جودو Godot للعمل مع قاعدة البيانات SQLite تشغيل محرك الألعاب جودو على بعض أنواع العتاد غير المدعوم تعرف على أشهر لغات برمجة الألعاب
  7. سنعمل في هذا المقال على بناء كاميرا لشاشة لمس في محرك الألعاب جودو كي يتمكن اللاعب من تحريك الكاميرا حول محورها وتكبير وتصغير وتدوير الكاميرا عن طريق اللمس. تهيئة الكاميرا ثنائية البعد افتح محرك الألعاب جودو وأنشئ مشروعك الأول، وابدأ بعقدة من النوع CameraD2، ولجعلها حساسة للمس، سنضيف سكريبت يدير العملية، وذلك بالنقر عليها بالزر الأيمن للفأرة ثم اختيار "إلحاق نص برمجي attach script" ولنسمّه "TouchCameraController.gd". ملاحظة أضفنا أيقونة إلى المشهد لكي نرى الكائن الذي يتحرك. إعداد الكاميرا نحتاج بداية إلى مجموعة من المتغيرات للتحكم بالكاميرا التي تمثلها في جودو العقدة Camera2D. تمثل هذه المتغيرات سرعة الحركة المحورية وسرعة التكبير والتصغير، وسرعة الدوران، وأخرى للتحكم في إمكانية التحريك أو التكبير أو التدوير. وإضافة إلى ذلك، ننشئ متغيرات لتخزين حالة الكاميرا ومدخلات اللمس. إليك طريقة تعريف المتغيرات: extends Camera2D @export var zoom_speed: float = 0.1 @export var pan_speed: float = 1.0 @export var rotation_speed: float = 1.0 @export var can_pan: bool @export var can_zoom: bool @export var can_rotate: bool var start_zoom: Vector2 var start_dist: float var touch_points: Dictionary = {} var start_angle: float var current_angle: float قمنا في البداية بتوسيع الصنف Camera2D في Godot الذي يمثل كاميرا ثنائية الأبعاد 2D في جودو ثم حددنا مجموعة المتغيرات التي يمكن تعديلها وهي: zoom_speed: قيمة عددية تحدد سرعة عملية التكبير والتصغير للكاميرا. pan_speed: قيمة عددية تحدد سرعة عملية التحريك الجانبي للكاميرا. rotation_speed: قيمة عددية تحدد سرعة عملية تدوير الكاميرا. can_pan: قيمة بوليانية تحدد إمكانية التحريك الجانبي للكاميرا. can_zoom: قيمة بوليانية تحدد إمكانية التكبير أو التصغير للكاميرا. can_rotate: قيمة بوليانية تحدد إمكانية تدوير الكاميرا. ثم عرفنا المتغيرات التي ستخزن معلومات عن اللمس وهي: start_zoom لتخزين قيمة بداية عملية التكبير أو التصغير الحالي للكاميرا. start_dist لتخزين المسافة بين نقاط اللمس عند بداية التكبير أو التصغير. touch_points لتخزين مواقع نقاط اللمس على الشاشة لاستخدامها في حسابات التكبير والتدوير. start_angle لتخزين زاوية بداية التدوير لحساب الزاوية المطلوبة للتدوير. current_angle لتخزين الزاوية الحالية لعملية التدوير لتحديث تدوير العنصر المرئي بشكل مستمر. تحريك الكاميرا حول محورها لنبدأ اﻵن بتحريك الكاميرا حول محورها، وهي الحركة اﻷبسط التي تنفذها الكاميرا في المشهد. سنحتاج إلى وسيلة لترصّد بعض أحداث الدخل، لهذا سنتجاوز override الدالة (input(event_ للتحقق من أحداث اللمس touch والسحب drag على الشاشة والاستجابة لها بالشكل المناسب: func _input(event): if event is InputEventScreenTouch: _handle_touch(event) elif event is InputEventScreenDrag: _handle_drag(event) تخزّن الدالة (handle_touch(event_ موقع كل نقطة لُمست على الشاشة ضمن القاموس touch_points وتستخدم دليل اللمس touch index كمفتاح، وهذا أساسي لتتبع المواقع التي تُلمس على الشاشة. كما سنضبط قيمة المتغير start_dist على 0 إن كان عدد النقاط التي لُمست أقل من 2: func _handle_touch(event: InputEventScreenTouch): if event.pressed: touch_points[event.index] = event.position else: touch_points.erase(event.index) if touch_points.size() < 2: start_dist = 0 بإمكاننا تحريك الكاميرا حول محورها بالاستفادة من نقطة لمس واحدة، وذلك باستخدام الدالة (handle_drag(event_ المعرفة كالتالي: func _handle_drag(event: InputEventScreenDrag): touch_points[event.index] = event.position if touch_points.size() == 1 and can_pan: offset -= event.relative * pan_speed إن شغّلت اللعبة على محاكي أندرويد سترى كيف تتحرك الكاميرا: إضافة ميزة التكبير والتصغير سنضيف اﻵن إمكانية التكبير والتصغير (تقريب وإبعاد)، لهذا سنعدّل الدالة (handle_touch(event_ كي نعالج حالة وجود نقطتي لمس والتي سنحسب فيها المسافة اﻷولية بينهما ونخزّنها: func _handle_touch(event: InputEventScreenTouch): if event.pressed: touch_points[event.index] = event.position else: touch_points.erase(event.index) if touch_points.size() == 2: var touch_point_positions = touch_points.values() start_dist = touch_point_positions[0].distance_to(touch_point_positions[1]) start_zoom = zoom start_dist = 0 نضيف بعد ذلك إمكانية التحكم بالتكبير والتصغير إلى الدالة handle_drag(event)_، فعند وجود نقطتي لمس، نحسب المسافة الحالية بينهما وبناء عليها نضبط التكبير والتصغير: func _handle_drag(event: InputEventScreenDrag): touch_points[event.index] = event.position # Handle 1 touch point if touch_points.size() == 1 and can_pan: offset -= event.relative * pan_speed # Handle 2 touch points elif touch_points.size() == 2 and can_zoom: var touch_point_positions = touch_points.values() var current_dist = touch_point_positions[0].distance_to(touch_point_positions[1]) var zoom_factor = start_dist / current_dist zoom = start_zoom / zoom_factor limit_zoom(zoom) # This is about to be created! نستخدم الدالة (limit_zoom(zoom لمنع التكبير أو التصغير من تجاوز الحدود وسيقف التكبير أو التصغير عند حد معين: func limit_zoom(new_zoom: Vector2): if new_zoom.x < 0.1: zoom.x = 0.1 if new_zoom.y < 0.1: zoom.y = 0.1 if new_zoom.x > 10: zoom.x = 10 if new_zoom.y > 10: zoom.y = 10 انقر على زر التشغيل لترى النتيجة: إضافة الدوران لنضف أخيرًا إمكانية تدوير الكاميرا، لهذا سنقيس الزاوية الأولية بين نقطتي اللمس من خلال الدالة handle_touch(event)_: func _handle_touch(event: InputEventScreenTouch): if event.pressed: touch_points[event.index] = event.position else: touch_points.erase(event.index) if touch_points.size() == 2: if touch_points.size() == 2: var touch_point_positions = touch_points.values() start_dist = touch_point_positions[0].distance_to(touch_point_positions[1]) start_angle = get_angle(touch_point_positions[0], touch_point_positions[1]) start_zoom = zoom elif touch_points.size() < 2: start_dist = 0 نضيف بعد ذلك إمكانية التحكم بالدوران ضمن الدالة handle_drag(event)_: func _handle_drag(event: InputEventScreenDrag): touch_points[event.index] = event.position if touch_points.size() == 1: if can_pan: offset -= event.relative * pan_speed elif touch_points.size() == 2: var touch_point_positions = touch_points.values() var current_dist = touch_point_positions[0].distance_to(touch_point_positions[1]) var current_angle = get_angle(touch_point_positions[0], touch_point_positions[1]) #this will be created below var zoom_factor = start_dist / current_dist if can_zoom: zoom = start_zoom / zoom_factor if can_rotate: rotation -= (current_angle - start_angle) * rotation_speed start_angle = current_angle # حدث الزاوية اﻷولية إلى الزاوية الحالية limit_zoom(zoom) تٌستخدم الدالة (get_angle(p1, p2 لحساب الزاوية: func get_angle(p1: Vector2, p2: Vector2) -> float: var delta = p2 - p1 return fmod((atan2(delta.y, delta.x) + PI), (2 * PI)) جرّب تدوير اﻷيقونة اﻵن! السكريبت المكتمل إليك الشيفرة الكاملة: extends Camera2D @export var zoom_speed: float = 0.1 @export var pan_speed: float = 1.0 @export var rotation_speed: float = 1.0 @export var can_pan: bool @export var can_zoom: bool @export var can_rotate: bool var start_zoom: Vector2 var start_dist: float var touch_points: Dictionary = {} var start_angle: float var current_angle: float func _ready(): start_zoom = zoom func _input(event): if event is InputEventScreenTouch: _handle_touch(event) elif event is InputEventScreenDrag: _handle_drag(event) func _handle_touch(event: InputEventScreenTouch): if event.pressed: touch_points[event.index] = event.position else: touch_points.erase(event.index) if touch_points.size() == 2: var touch_point_positions = touch_points.values() start_dist = touch_point_positions[0].distance_to(touch_point_positions[1]) start_angle = get_angle(touch_point_positions[0], touch_point_positions[1]) start_zoom = zoom elif touch_points.size() < 2: start_dist = 0 func _handle_drag(event: InputEventScreenDrag): touch_points[event.index] = event.position if touch_points.size() == 1: if can_pan: offset -= event.relative * pan_speed elif touch_points.size() == 2: var touch_point_positions = touch_points.values() var current_dist = touch_point_positions[0].distance_to(touch_point_positions[1]) var current_angle = get_angle(touch_point_positions[0], touch_point_positions[1]) var zoom_factor = start_dist / current_dist if can_zoom: zoom = start_zoom / zoom_factor if can_rotate: rotation -= (current_angle - start_angle) * rotation_speed start_angle = current_angle # Update the start_angle to the current_angle for the next drag event limit_zoom(zoom) func limit_zoom(new_zoom: Vector2): if new_zoom.x < 0.1: zoom.x = 0.1 if new_zoom.y < 0.1: zoom.y = 0.1 if new_zoom.x > 10: zoom.x = 10 if new_zoom.y > 10: zoom.y = 10 func get_angle(p1: Vector2, p2: Vector2) -> float: var delta = p2 - p1 return fmod((atan2(delta.y, delta.x) + PI), (2 * PI)) الخلاصة صممنا في هذا المقال سكريبت كاميرا تتجاوب مع أفعال اللمس على الشاشة في محرك الألعاب جودو 4، ويمكنها التحرك حول محورها أو التكبير والتصغير أو الدوران. انتبه فقط إلى ضرورة ربط السكريبت بعقدة من النوع Camera2D واستمتع بعملك! ترجمة -وبتصرف- لمقال Building a touchscreen camera in Godot 4: A comprehensive guide اقرأ أيضًا تشغيل محرك الألعاب جودو على بعض أنواع العتاد غير المدعوم تعرف على أشهر محركات الألعاب تعرف على أشهر لغات برمجة الألعاب مدخل إلى محرك الألعاب جودو
  8. نتحدث في مقالنا عن أمثل الطرق ﻹعداد وتصدير الأصول أو الموجودات assets من بليندر Blender إلى محرّك اﻷلعاب جودو Godot، ونغطي خلاله العمل مع الخامات texture والتعامل مع قنوات لونية مختلفة، وبعض الإعدادات الشائعة لملفات المشاهد ثلاثية اﻷلعاب gLTF، ثم نتحدث عن فعالية استخدام هذه التنسيق. إعداد الخامة Texture عليك بداية إعداد الخامة texture، لهذا يمكنك الانتقال فورًا إلى التحرير اللوني shading، وقد تلاحظ وجود كائنين. والسبب في ذلك أننا سنستعرض تقنيتين مختلفتين لهما فائدة كبيرة جدًا، وستلاحظ أن معاملات الكائن اﻷول جاهزة وفي مكانها. وفي الفقرات التالية نوفر لك دليلًا سريعَا يوضح الدمج مع بقية الأصول التصميمية في ملف gLTF الذي سنصدّره والذي يستخدم لنقل وتحميل النماذج ثلاثية الأبعاد. القناة Alpha وخريطة Albedo تمثّل Albedo الخريطة اللونية التي يمكن سحبها إلى القاعدة اللونية Base Color. وإن وجدت القناة Alpha، سيتوجب عليك سحبها إلى مكانها. أما خريطة Albedo فهي الخريطة اللونية التي تحتاجها وبإمكانك سحبها إلى القاعدة اللونية. وبالعودة إلى قناة Alpha، وإن كان لديك أية قناة قد هيأتها سابقًا، فعليك وضعها ضمن القسم Alpha. وإن أردتها أن تعمل ضمن محرك اﻷلعاب الذي تريده، انتقل إلى المواد material وبعدها إلى وضع المزج blend mode وغيّرها إلى اقتصاص ألفا Alpha clip. وتذكر أن الطريقة التي تُعد فيها القناة هنا هي نفسها التي ستظهر عندما يتطلب اﻷمر تغيير بعض اﻹعدادات. ستجد في لوحة المواد لديك نمطًا للمزج تصل إليه كالتالي viewport display ثم settings ثم Blend Mode، وسيؤثر ذلك على طريقة عرض محرك اﻷلعاب لخرائطك: واضح Opaque: وهو اﻹعداد الافتراضي، تُرى فيه المواد بشكل كامل ولا يسمح بأي وضع شفاف، أي يتجاهل هذا الخيار أية معلومات تقدمها القناة Alpha ويتعامل مع المواد على أنها ظاهرة تمامًا. اقتصاص ألفا Alpha clip: ويُعرف هذا النمط أيضًا باختبار ألفا Alpha Test أو الاقتصاص Cutout، ويستخدم معلومات قناة Alpha ﻹنشاء فصل ثنائي واضح بين المناطق كاملة الوضوح وكاملة الشفافية. وهذا أمر مثالي للكائنات التي تتمتع بشفافية محددة بدقة مثل الأسوار وأوراق اﻷشجار أو القصاصات الورقية، إذ لا تريد حينها مناطق نصف شفافة. تظليل ألفا Alpha Hashed: يسمح هذا النمط باﻷوضاع نصف الشفافة للمواد، ويعطي أفضل النتائج عند تجميع الكائنات الشفافة فوق بعضها على شكل طبقات. يستخدم نمط التشويش العشوائي dithered pattern لمحاكاة الشفافية، وينتج عنه خامة مشوشة لكنها تعطي توزيعًا أفضل عمومًا للسطوح الشفافة مقارنة بنمط مزج ألفا Alpha Blend. مزج ألفا Alpha Blend: يسمح هذا النمط بالوضع نصف الشفاف الكامل، وهو مثالي لمواد مثل الزجاج أو السوائل، إذ يمزج قناة Alpha مع القناة اللونية ليعطي تمثيلًا دقيقًا للشفافية. مع ذلك قد يواجه هذا النمط مشاكل مع توزيع العمق اللوني وخاصة عند تتداخل عدة كائنات شفافة. المظهر المعدني والخشونة يستخدم مخطط عمل يعتمد على التصيير الفيزيائي Physical Based Rendering ليحاكي المواد الحقيقة في محركات اﻷلعاب ثلاثية اﻷبعاد. الخرائط المعدنية تحدد الخرائط المعدنية Metallic Maps أية أقسام من نموذجك لها مظهر معدني وتلك التي ليس لها هذا المظهر. ففي الخامة ذات التدرجات الرمادية، تعبر القيمة (1.0) للون اﻷبيض أن السطح معدني، بينما تعبر القيمة (0.0) عن سطح غير معدني. وعليك الانتباه إلى أن هذه الخاصية قد تكون ثنائية وغير متدرجة في أغلب اﻷحيان، فإما أن يكون السطح معدنيًا أو غير معدني. لهذا سيكون لهذه الخريطة قيم سوداء تمامًا أو بيضاء تمامًا غالبًا، ونادرًا ما تستخدم قيم تدريجية (رمادية). خرائط الخشونة تتحكم خرائط الخشونة Roughness Maps بتفصيل نعومة أسطح المواد وتحدد مدى الخشونة أو النعومة التي تبديها. ففي هذه اﻷرضية ذات التدرج الرمادي، تشير قيم اللون اﻷبيض إلى سطح خشن، يعكس الضوء باتجاهات مختلفة، معطيًا مظهرًا ليس لامعًا. بينما تشير قيم اللون الأسود إلى سطح ناعم يعكس الضوء باتجاهات محددة أكثر، معطيًا مظهرًا لامعًا. لكن كيف يمكن تصدير كل ذلك؟ كيف تُنفّذ هذه الإعدادات لتصديرها لاحقًا من الجيد فصل اﻷرضيات التي تحجب محيط الكائن وخرائط الخشونة والمظهر المعدني (ORM اختصارًا) وإسنادها إلى القناتين اللونيتين الزرقاء والخضراء وهو طريقة جيدة في حزم اﻷرضيات لجعلها أكثر فعالية. وعندما يكون لديك عدة خرائط متصلة مع خرائط ORM ستُجمّع كلها ضمن خامة ORM واحدة. وتأكد من ضبط خرائط الخشونة والمظهر المعدني والخرائط النمطية normal map على قيم غير لونية كي يكون الفضاء اللوني صحيحًا وبالتالي ستنقل البيانات بشكل صحيح. وتذكر أيضًا أن أية تغييرات تجريها على اﻷرضيات ستُصدّر أيضًا. حجب محيط المادة إن حجب المحيط Ambient Occlusion عملية مزعجة للكثيرين، وخاصة عند تصديرها من بليندر. والحل اﻷبسط هو تحديد عقدة الخامة ومضاعفتها بالضغط على المفتاحين Shift + D، ثم تجميعها بالضغط على المفتاحين CTRL + G والذي يُنشئ مجموعة من اﻷرضيتين في الوسط. احذف الخريطة الموجودة في الوسط: ستجد على اليمين المدخلات inputs والمخرجات outputs ضمن النافذة الفرعية "Group": أزل المدخلات فلن نحتاجها، ثم غيّر اسم الشعاع Vector تحت المدخلات إلى Occlusion وغيّر نوعه إلى float اضغط على Tab وستظهر عقدة مجموعة جديدة: غيّر اسم العقدة إلى "glTF Settings" كما في الصورة التالية تمامًا، فأي خطأ سيمنعه من العمل: صل اﻵن خريطة الحجب إلى عقدة المجموعة "glTF Settings": تصدير الخريطة النمطية الخريطة النمطية normal map هو نمط من اﻷرضيات المستخدمة في النماذج ثلاثية اﻷبعاد لمحاكاة التفاصيل الصغيرة للسطح مثل النتوءات دون الحاجة ﻹضافة مضلعات جديدة في النموذج. تُعد الخريطة النمطية بسيطة، واحرص على عدم استخدام قيم لونية عند ضبطها ثم صلها مع عقدة الخرائط النمطية وبعدها إلى normal. هذه هي الطريقة اﻷبسط لتصديرها. إعدادات إضافية أخرى ستجد في نافذة اﻹعدادات settings الخيار "Backface Culling" (ويعني إخفاء الوجه عند النظر من الخلف)، فإن فعّلته هنا سيُفعّل في محرًك اﻷلعاب الذي تنقل ملف اﻹعدادات إليه. عند تفعيل هذا الخيار، يتحقق محرك الرسوميات من توجّه كل مضلّع، فغن كان مواجهًا للكاميرا فسيُصيّر بشكل اعتيادي، وإن كان معاكسًا لها، سيتجاوزه محرّك الألعاب ولن يصيّره. ولهذا الأمر إيجابيات على اﻷداء، فهو يقلل عدد المضلعات التي يجدر بالمحرّك معالجتها بشكل واضح. ولكي تعمل هذه التقنية جيدًا، ينبغي أن يكون النموذج مغلقًا بالشكل الصحيح، أي لا يحتوي أية ثقوب تسمح بالنظر من خلالها إلى الوجه الخلفي لمضلعات أخرى. فإن فّعلّ خيار إخفاء الوجه عند النظر من الخلف وكان هناك ثقوب، فستظهر بعض أجزاء النموذج وكأنها مفقودة عند النظر من زاوية معينة. ومن المهم الانتباه إلى أن تفعيل هذا الخيار ليس محبذًا النماذج المسطحة والرقيقة مثل اﻷوراق او غيرها من المواد الشفافة أو نصف الشفافة والتي يمكن أن يُرى منها وجهي المضلع، بعد ذلك يمكنك تصدر الكائن بالانتقال إلى File ثم Export GLTF. ما الذي يجب تذكره عند تصدير GLTF؟ ينبغي الانتباه إلى عدة أشياء عند تصدير GLTF، لهذا سنناقش إعدادات تصدير النموذج ثلاثي اﻷبعاد بصيغة GLTF: التنسيق Format: أكثر التنسيقات استخدامًا هو صيغة GLB الثنائية، لأنها تضم النموذج ثلاثي اﻷبعاد واﻷرضيات في ملف واحد. مع ذلك يعطيك تنسيقا (glTF(GLTF + BIN + textures و glTF Embedded تحكمًا أوسع لأنهما يفصلان بين المكونات. ويُعد تنسيق (glTF(GLTF + BIN + textures مفيدُا إن أردت مشاركة اﻷرضيات مع كائنات أخرى. التضمين include: تحدد في هذا القسم أية أجزاء من ملف بلندر ستصدره. فالخيار "خيارات منتقاة Selected Options" يُصدّر فقط النماذج التي اخترتها، وجميع الخيارات في المجموعة الفعّالة حاليًا في حال اخترت "المجموعة الفعالة Active Collection". التحويل transform: إن كنت تواجه مشاكل مع توجّه النموذج في محرّك اﻷلعاب، بإمكانك تغيير المحورين "أعلى Up" و "للأمام Forward". وتذكّر اختلاف التوجّهات في محركات الألعاب المختلفة. تصدير المواد Material Export: عليك التأكد من تفعيل هذا الخيار. الصور Images: بإمكانك اختيار صيغة الصور التي تريدها من هذا القسم. هندسة النموذج Geometry: يتضمن هذا القسم خيارات التصدير المتعلقة بهندسة النموذج، فإذا كان نموذجك يستخدم ألوان Vertex فعّل الخيار المتعلق به وإلا فقم بتعطيله، اما خيار Apply Modifiers فهو يطبق جميع المعدلات على النموذج الخاص بك قبل التصدير. التحريك Animation: يساعدك هذا القسم في تصدير الرسوم المتحركة، وبإمكانك تصدير الرسوم المتحركة النمطية normal animations ومفاتيح الشكل shape keys ورسوم اﻷغلفة skinning كي تتحكم بها في محرّك اﻷلعاب الذي تريد. إدراج ملف glTF في محرك اﻷلعاب جودو عند اكتمال تصدير الملف، افتح محرّك اﻷلعاب جودو واستورد هذا الملف. وتأكد أن الصور المضمّنة في تنسيق glTf Embedded قد ضُبطت على "استخراج اﻷرضيات". ومن المفترض أن يتلائم الملف المصدّر جيدًا. في حالتنا الموضحة بالصور التالية، اخترنا اقتصاص ألفا Alpha clip عند التصدير، لكنه ظهر في محرك ألعاب جودو على شكل مقص ألفا Alpha Scissor. لاحظ كيف ظهرت الخرائط بالشكل الصحيح في جودو! وقد تلاحظ كيف تبدو غريبة ومليئة بألوان زاهية، يُدعى هذا اﻷمر خامة ORM أي أن اﻷرضيات قد حُزّمت ضمن خرائط مختلفة وأقنية مختلفة للخامة مما يجعل هذه الخرائط أكثر فعالية. وقد تلاحظ أيضًا ظهور قسم الانبعاثات Emision والخريطة النمطية Normal Map أيضًا. الخلاصة باتباعك الخطوات التي شرحناها في هذا المقال، ستتمكن من تصدير عناصر أو أصول الألعاب الخاصة بك بفعالية من بليندر إلى جودو Godot. لا تتردد في ترك أية تساؤلات أو اقتراحات في قسم التعليقات أسفل الصفحة لتعم الفائدة لجميع المهتمين بتصميم الألعاب الإلكترونية. ترجمة -وبتصرف- لمقال: How to Efficiently export Assets from Blender to your game engine اقرأ أيضًا مطور الألعاب: من هو وما هي مهامه بلندر للمبتدئين: كيف تصمّم وتحرّك روبوت - نمذجة الجسم والرأس كيف تصمّم وتحرّك روبوت: خامات بلندر ومفاتيح الشكل إنشاء مجسم ثلاثي الأبعاد لشجرة باستخدام برنامج بلندر
  9. نتحدث في هذا المقال عن استخدام محرر قواعد البيانات SQLite للعمل مع جودو، ونعرض بداية اﻷسباب التي تدفع مطوري اﻷلعاب للعمل مع محرر قواعد بيانات أصلًا، ونتعرف بعدها على محرر قواعد البيانات SQLite والذي يُعد قاعدة بيانات مضمّنة صغيرة تسمح للمستخدم تخزين البيانات والاستعلامات ضمنها. لكن لماذا على استخدام قاعدة بيانات هذه؟ إن الميزة المفيدة لهذه القاعدة هو قدرتها على استيعاب كل البيانات في منطقة واحدة، واﻷهم من كل ذلك هو القدرة على الحصول على البيانات بأبسط طريقة. حتى تبدأ العمل معنا في هذا المقال، افتح محرك الألعاب جودو وأنشئ مشروعًا جديدًا. إعداد قاعدة البيانات إذا كنت مطور ألعاب إلكترونية فقد تحتاج لاستخدام قواعد البيانات في لعبتك من أجل تخزين بيانات اللاعبين وحفظ المستوى أو النقاط التي حصلوا عليها، ولتجهيز قاعدة البيانات SQLite التي سنستخدمها في هذا المقال، حمّل متصفح قواعد البيانات DB Browser for SQLite الذي يساعدك في إدارة قاعدة البيانات من خلال واجهة رسومية يمكنك من خلالها إنشاء قاعدة البيانات وتحريرها بسهولة. سنبدأ بإنشاء قاعدة بيانات جديدة، لهذا افتح متصفح قاعدة البيانات وانقر على النافذة "قاعدة بيانات جديدة New Database". وانتقل بعد ذلك إلى المجلد الذي يضم مشروع جودو الذي أنشأته سابقًا وأنشئ ضمنه مجلدًا جديدًا يحمل الاسم "datastore"، فلنختر الاسم "data" لقاعدة بياناتنا الجديدة. تظهر بعد ذلك نافذة "تحرير تعريف الجدول Edit table definition"، اختر عندها الاسم "Scoreboard" لهذا الجدول وسنخزن في هذا الجدول نتيجة كل لاعب أو عدد النقاط التي حصل عليها في اللعبة. لنبدأ بإنشاء أول اﻷعمدة "id" بالنقر على الزر "Add"، وستكون عناصره من النوع الصحيح INTEGER وانقر على الخيارات "غير فارغ NN" و"تزايد تلقائي AI"، مما يسمح له بأن يكون مرجعًا لنا للحصول على البيانات من الجدول أو إلحاق بيانات أخرى. أنشئ تاليًا حقلًا field نصيًا TEXT وسمه "name" وذلك لتخزين اسم المستخدم الذي نريد معرفة نتيجته. ويستخدم النوع السابق لتخزين أكثر من ا تيرابايت من البيانات النصية، فانتبه إلى ذلك! ثم أنشئ أخيرًا حقل النتيجة "score" واجعله من النوع الصحيح INTEGER. انقر اﻵن على الزر "موافق OK" وانتقل إلى مشاهدة قاعدة البيانات من خلال النقر على "تصفح البيانات Browse Data"، وسترى جدولك وقد ظهر. بإمكانك اﻵن من هذه النافذة أن تدخل البيانات يدويًا إن أردت، وذلك بالنقر على أيقونة اﻹضافة ومن ثم إدخال ما تريد. إن انتقلنا إلى "تنفيذ استعلام execute SQL"سترى المكان الذي تنفذ فيه الاستعلامات التي نريد على قاعدة البيانات. سنجرّب الاستعلامات بإدخال بعض البيانات، لهذا اكتب الاستعلام التالي: insert into scoreboard (name,score) values ('nori',50),('finepointcgi',20) عند تنفيذ هذا الاستعلام على النحو التالي: سترى النتيجة التالية: وعند تنفيذ الاستعلام Select * from scoreboard، سترى نتيجة عملك. ولننتقل اﻵن إلى محرك الألعاب جودو من أجل استكمال عملية ربطه مع قاعدة البيانات SQLite. تنزيل اﻹضافة الخاصة بقاعدة البيانات SQlite لننتقل اﻵن إلى جودو ثم نفتح النافذة الفرعية "مكتبة الأصول أو مكتبة الموجودات Asset library" التي تمثل مستودعًا لأي أدوات أو موارد إضافية تريد تضمينها في اللعبة، ثم اكتب sqlite واختر الإضافة التي تملك الرقم 2shady4u فهي إضافة جيدة وذات أداء مستقر. جرّب بعد ذلك تثبيتها وانتظر لحين اكتمال التنزيل. سنضيف تاليًا عقدة، لهذا سننشئ سكريبت ونسمّيه "MainSystem.gd" وسيحتوي هذا الملف على كافة السكريبتات والتعليمات التي تتفاعل مع البيانات، لذا علينا تحميل أن نقوم بتحميل قاعدة البيانات في بدايته، وكي تتمكن من القيام بالتحميل المسبق للبيانات عليك استخدام الدالة preload مع تمرير العنوان التالي لوسيط لهذه الدالة: res://addons/godot-sqlite/bin/gdsqlite.gdns إدخال بيانات إلى قاعدة البيانات الآن انسخ الشيفرة التالية إلى ملف السكريبت الذي أنشأته في الخطوة السابقة: const SQLite = preload("res://addons/godot-sqlite/bin/gdsqlite.gdns") var db var db_name = "res://DataStore/database" func _ready(): db = SQLite.new() db.path = db_name func commitDataToDB(): db.open_db() var tableName = "PlayerInfo" var dict : Dictionary = Dictionary() dict["Name"] = "this is a test user" dict["Score"] = 5000 db.insert_row(tableName,dict) ننشئ في الكود أعلاه المتغيرين db و db_name بعد تحميل قاعدة البيانات، ونسند للثاني عنوان قاعدة البيانات "res://DataStore/database". ومن أجل تهيئة قاعدة البيانات، نستدعي التابع ()SQLite.new داخل الدالة ()ready ونسند قيمته إلى المتغير db، وسيُهيئ ذلك صنفًا لإعداد قاعدة البيانات. نحتاج بعد ذلك إلى ضبط مسار قاعدة البيانات كالتالي db.path= db_name ونضيف بعدها دالة جديدة تُدعى ()commiteDataToDB سنستخدمها ﻹيصال البيانات إلى قاعدة البيانات. ننشئ ضمن الدالة ()commiteDataToDB قناة اتصال مع قاعدة البيانات لهذا نستدعي التابع ()db.open_db الذي يهيئ قناة الاتصال مع قاعدة البيانات ويسمح لنا بتنفيذ استعلامات عليها. ولاختيار اسمٍ للجدول، نعرّف متغيرًا بالاسم tablename ونضبطه قيمته على "PlayerInfo". ثم ننشئ قاموسًا dict يحدد المعلومات التي نريد إدراجها في قاعدة البيانات، ويكون مفتاح القاموس بمثابة العمود والقيمة بمثابة الصف عند إضافة معلومات القاموس إلى قاعدة البيانات من خلال التعليمة INSERT. نستدعي أخيرًا الدالة (db.insert_row(tableName,dict ﻹضافة القاموس (الذي يمثل المُدخل الجديد) إلى قاعدة البيانات. قراءة البيانات من قاعدة البيانات كما هو الحال عند الكتابة إلى قاعدة البيانات، لا بد من فتح قناة اتصال مع قاعدة البيانات واختيار الجدول الذي نريد القراءة منه. ثم ننشئ بعد ذلك الاستعلام الذي نريد باستدعاء التابع ()db.query وكتابة تعليمات الاستعلام ضمنه كمعامل نصي. وبمجرد استدعاء هذا التابع سيتصل مع قاعدة البيانات وينفذ الاستعلام ويخزن النتيجة ضمن المصفوفة query_result. لا بد بعد ذلك من التنقل بين عناصر المصفوفة من العنصر 0 وصولًا إلى آخر عنصر الذي تمثله الخاصية size للمصفوفة query_result للحصول على الكائنات الموجودة في قاعدة البيانات، ومن ثم طباعة النتيجة. func readFromDB(): db.open_db() var tableName = "PlayerInfo" db.query("select * from " + tableName + ";") for i in range(0, db.query_result.size()): print("Qurey results ", db.query_result[i]["Name"], db.query_result[i]["Score"]) الخلاصة هذا هو اﻷمر برمّته! فقد تعلمنا في مقال اليوم طريقة إضافة البيانات إلى قاعدة بيانات ومن ثم تعاملنا معها. ولعللك لاحظت أن استخدام قواعد البيانات أسهل وأسرع من استخدام الملفات لتخزين البيانات في لعبتك الإلكترونية. وتسمح لك باسترجاع البيانات التي تحتاجها فقط بدلًا من قراءة الكثير من الملفات. وعندما ترى أن بياناتك أضخم من عدة ملفات، من الجيد عندها الانتقال إلى قاعدة بيانات. ترجمة وبتصرف للمقال: Setting up Godot to work with SQLite اقرأ أيضًا تعرف على أهمية صناعة الألعاب الإلكترونية مدخل إلى محرك الألعاب جودو تعرف على محرر محرك اﻷلعاب جودو Godot كيف ومتى نستخدم SQLite
  10. نتحدث في هذا المقال عن بعض المشاكل التي يتعرض لها مستخدمو محرك الألعاب جودو Godot 4 عند محاولة العمل على عتاد لا يدعمه محرّك اﻷلعاب. فإن كنت تعمل على أجهزة حواسيب مصنّعة قبل عام 2013، فقد لا تملك برامج تشغيل العتاد Vulkan حيث تدعم هذه الأجهزة OpenGL 3.0 فقط من أجل عرض الرسومات ثلاثية الأبعاد على حاسوبك. وبالتالي إذا حاولت تشغيل محرك الألعاب جودو 4 ضمن بيئة عمل وهمية VirtualBox، ففي هذه الحالة قد تصادفك بعض العقبات. وسنوضح لك في هذا المقال طريقة للالتفاف على تلك المشاكل والعقبات وسبل حلها، فإذا كانت لديك أي مشكلات في التعامل مع إقلاع محرك ألعاب جودو 4 على جهازك تابع معنا قراءة هذا المقال. أين تكمن المشكلة في جودو 4؟ لنفترض أن ثبّت محرك ألعاب جودو 4 وأنت متحمس بالفعل لبدء العمل على صناعة لعبتك الإلكترونية، ثم نقرت نقرة مزدوجة على أيقونة البرنامج، وفوجئت بطهور رسالة خطأ تخبرك بفشل تهيئة برنامج تشغيل بطاقة الفيديو لديك لأنها لا تدعم Vulkan أو OpenGL كما هو موضح في الصورة التالية: لحل هذه المشكلة أمامك خيارات سنشرحهمها في الفقرات التالية. تحديث برامج تشغيل العتاد أو الالتفاف على الموضوع لديك اﻵن خياران، الأول هو أن تحدّث برنامج تشغيل بطاقة الفيديو لديك من خلال التوجه إلى موقع الويب الخاص بمصنع بطاقة العرض لديك، ومن ثم تنزيل وتثبيت آخر إصدار لهذه البطاقة. وفي حال لم يكن الخيار الأول متاحًا لديك، يمكن في هذه الحالة فتح محرر سطر اﻷوامر Command prompt أو الطرفية على جهازك ثم تكتب الأمر Godot، بعدها ابحث عن الملف التنفيذي للمحرك جودو، ثم شغله بعد إضافة الوسيط التالي لأمر التشغيل كما يلي: >Godot_v4.2.1-beta3_mono_win64.exe --rendering-drive opengl3 كما هو هو مبين في الشاشة التالية: ستعمل هذه الحيلة في أغلب اﻷحيان وسيُحمّل برنامج جودو ويعمل بشكل صحيح على جهازك. حل مشكلة النقر على زر التشغيل Play قد يبدو كل شيء على ما يرام حتى الآن، لكن قد تفاجئ بعد أن تنقر على زر التشغيل، بظهور رسالة الخطأ نفسها من جديد. لا تقلق يمكنك أيضًا إصلاح هذا الأمر من خلال الانتقال إلى القائمة مشروع Project ثم اختيار إعدادات المشروع Project Settings وبعدها ثم بتفعيل الخيار إعدادات متقدمة Advanced Settings كما في الصورة التالية. بعد أن تظهر لك النافذة أعلاه انتقل ذلك إلى قسم المحرر Editor ثم اختر الخيار تشغيل Run ثم اجعل قيمة المتغير Main Run Arguments كما يلي: rendering-drive opengl3-- وانقر بعد ذلك على زر إغلاق Close ومن المفترض أن يعمل زر التشغيل بشكل صحيح ودون أي مشكلات. خطوات إضافية للعمل على VitrualBox أو على جهاز محدد إن كنت تعمل على الجهاز الافتراضي VirtualBox، أو لم تنجح الخطوات السابقة لحل المشكلة، عليك في هذه الحالة اتباع بعض الخطوات الإضافية. انتقل إلى المتصفح وحمّل برامج تشغيل العتاد Mesa dist Windows في حال كان نظام تشغيل حاسوبك هو ويندوز Windows، أما إن كنت تعمل على إحدى توزيعات نظام التشغيل لينكس Linux فلن تحتاج إلى ذلك. حمّل اﻹصدار MingW من برنامج تشغيل العتاد Mesa وبرنامج ضغط الملفات 7-Zip الذي سوف تحتاجه لاستخراج ملفات برنامج تشغيل العتاد. عند اكتمال عملية التنزيل انتقل إلى مجلّد تنزيلات downloads، ثم استخرج الملفات باستخدام البرنامج 7-zip ثم افتح المجلد الناتج وشغّل الملف System Wide Deploy الذي سيخبرك بأنه سيثبّت برامج تشغيل العتاد OpenGL الخاص بالحواسب المكتبية. اختبار برامج تشغيل العتاد عليك تاليًا اختبار كلا برنامجي تشغيل العتاد OpenGL الخاص بسطح المكتب، ومايكروسوفت OpenGL على DirectX 3D12. سيعمل برامج تشغيل العتاد الأول على المعالج المركزي CPU وسيحاول الثاني العمل على المعالج الرسومي GPU. تشغيل جودو 4 عد مجددًا إلى محرر سطر اﻷوامر واكتب الأمر التالي: Godot –rendering-driver opengl3 ويجب أن يعمل جودو كما هو مطلوب، وتذكر أن ما فعلناه هنا هو الالتفاف حول المشكلة، فلا تتوقع أداءً استثنائيًا! لكن على اﻷقل ستشغّل محرك ألعاب جودو 4 بصورة صحيحة. أما إن كنت تعمل على توزيعة لينكس منت Mint، فلن تحتاج لعملية الالتفاف تلك، وسيعمل جودو حتى على العتاد غير المدعوم لأن برنامج تشغيل العتاد Mesa مضمّن معه. الخلاصة قد يكون تشغيل محرك الألعاب جودو 4 على عتاد لا يدعمه أمرًا صعبًا على مطور الألعاب الإلكترونية، لكن حل هذه المشكلة ليس مستحيلًا! كل ما عليك هو تجربة الخطوات التي شرحناها في المقال وتستأنف العمل على جودو، وإن واجهتك أي مشكلة في التعامل مع محرك الألعاب جودو لا تتردد في طرحها في قسم التعليقات أسفل المقال لنساعدك على حلها. ترجمة -وبتصرف- للمقال Making Godot 4 work on (some)unsupported hardware اقرأ أيضّا مدخل إلى محرك الألعاب جودو Godot تعرف على محرر محرك اﻷلعاب جودو Godot تعرف على أشهر محركات الألعاب Game Engines
  11. نعرض في هذا المقال لمحة موجزة عن واجهة محرك الألعاب جودو Godot، ونلقي نظرة على شاشاتها المختلفة وقوائمها كي تعرف كيف ترتب الواجهة بما يلائمك. مدير المشروع وهي أول نافذة تظهر عندما تُشغّل جودو Godot، وتضم نافذتين فرعيتين أولهما "المشاريع الخاصة Local projects" التي تتيح لك إدارة المشاريع الموجودة على حاسوبك وإدراج أو إنشاء مشاريع جديدة وغيرها. أما النافذة الأخرى فهي "مشاريع مكتبة الملحقات Asset Library Projects" التي تساعدك على البحث عن مشاريع تجريبية في مكتبة الموجودات مفتوحة المصدر وتضم الكثير من المشاريع التي يطوّرها مجتمع جودو. تستطيع أيضًا تغيير لغة المحرر الافتراضية (اﻹنكليزية) من خلال النقر على زر القائمة المنسدلة أعلى ويمين نافذة المحرك. نظرة أولى إلى محرر جودو عندما تفتح مشروعًا موجودًا أو تنشئ مشروعًا جديدًا، سيعرض لك المحرّك نافذة المحرر كما في لقطة الشاشة التالية: تتكون النافذة من قوائم وشاشات رئيسية وأزرار للتحكم أعلى النافذة: ستجد في منتصف الشاشة نافذة العرض مع شريط أدواتها في الأعلى، وستجد ضمن الشريط أدوات لتحريك أو تحجيم أو قفل عقد المشهد. وستجد على طرفي نافذة العرض حاويات docks وفي أسفلها لوحة أدوات سفلية. يتغيّر شريط اﻷدوات وفقًا لسياق العمل والعقدة المختارة. إليك لقطة شاشة شريط أدوات مشهد ثنائي البعد: وشريط أدوات مشهد ثلاثي اﻷبعاد: لنلق نظرة اﻵن إلى الحاويات وأولها الحاوية "نظام الملفات FileSystem" التي تعرض قائمة بملفات المشروع بما في ذلك السكربتات والصورة ومقاطع الصوت وغيرها: أما الحاوية الثانية فهي "المشهد Scene" التي تعرض قائمة بالعقد الفعّالة: وتتيح لك حاوبة "الفاحص Inspector" تعديل خصائص العقدة المختارة: تظهر لوحة اﻷدوات السفلية تحت نافذة العرض وتضم طرفية التنقيح debug console ومحرر الرسوم المتحركة والمازج الصوتي وغيرهم من اﻷدوات. تشغل اللوحة مساحة لا بأس بها لهذا تكون مخفية افتراضيًا. عندما تنقر على أي عنصر من اللوحة تتمدد شاقوليًا. إليك لقطة شاشة للوحة وهي تعرض المحرر الرسومي: الشاشات الرئيسية اﻷربعة هناك أربعة أزرار للشاشات الرئيسية أعلى المحرر وهي "الثنائي 2D" و "الثلاثي 3D" و "Script" و "AssetLib". الشاشة 2D ستستخدم الشاشة ثنائية البعد 2D لمختلف أنواع الألعاب، فإضافة إلى اﻷلعاب ثنائية اﻷبعاد ستستخدم هذه الشاشة لبناء الواجهات. الشاشة 3D تتعامل في النافذة ثلاثية اﻷبعاد مع الشبكات واﻷضواء ومراحل تصميم اﻷلعاب ثلاثية الأبعاد: ملاحظة: بالنقر على الزر "perspective" تحت شريط اﻷدوات سيفتح لك قائمة بخيارات تتعلق بالمشهد ثلاثي اﻷبعاد. الشاشة Script تعرض هذه الشاشة محرر الشيفرة المتكامل والمزود بمنقح وآلية ﻹكمال الشيفرة ومراجع مدمجة إلى الشيفرة: الشاشة AssetLib تضم الشاشة مكتبة من الإضافات مفتوحة المصدر والسكربتات وغيرها من الموجودات التي تساعد في مشروعك: مراجع مدمجة إلى اﻷصناف يزوّدك جودو بمراجع مدمجة إلى اﻷصناف وتوابعها وخاصياتها وثوابتها وإشاراتها ويساعدك في البحث عنها بسهولة بإحدى الطرق التالية: الضغط على زر F1 (أو Alt+Space في ماك أو fn+F1 في الحواسب المحمولة التي تحتوي الزر fn). النقر على الزر "البحث في المساعدة Search help" في أعلى ويمين شاشة السكربت الرئيسية. النقر على قائمة "مساعدة Help" ثم "البحث في المساعدة Search Help". النقر على اسم الصنف أو الدالة او المتغير المدمج مع الضغط على الزر Ctrl. عند استخدام أية طريقة من الطرق السابقة تنبثق نافذة اكتب فيها ما تريد البحث عنه، كما يمكنك استخدامها لتصفح الكائنات والتوابع المتاحة. انقر نقرة مضاعفة على العنصر لفتح الصفحة المتعلقة به ضمن نافذة السكربت. ترجمة -وبتصرف-للمقال First look at Godot's editor. اقرأ أيضًا مدخل إلى محرك الألعاب جودو Godot مدخل إلى صناعة ألعاب المتصفح برمجة لعبة متاهة باستخدام محرك يونيتي Unity
  12. يساعدك هذا المقال على تقدير إذا ما كان محرّك الألعاب جودو Godot ملائمًا لاحتياجاتك، إذ سنقدم لك بعض الميزات العامة للمحرك كي نعرض ما يمكنك إنجازه، واﻹجابة عن أسئلة مثل " مالذي عليّ معرفته كي أبدأ العمل؟". لن تكون هذه المقدمة شاملة، لكننا سنقدّم الكثير من المفاهيم العامة في سلسلة المقالات المتتالية. ما هو محرك الألعاب جودو Godot جودو Godot هو محرك ألعاب ثنائية وثلاثية أبعاد عام اﻷغراض يدعم مختلف أنواع المشاريع، يساعدك في بناء اﻷلعاب والتطبيقات التي يمكن نشرها على الحواسب أو أجهزة الهاتف المحمول وعلى الويب أيضًا. يمكنك أيضًا بناء ألعاب مخصصة لمنصات الألعاب console games لكن ذلك يتطلب مهارات برمجية عالية أو الاستعانة بمطوّر ليساعدك على ذلك. ملاحظة: لا يمكن أن يقدّم لك مطورو جودو وسيلة مفتوحة المصدر لنقل اللعبة إلى منصات اﻷلعاب نظرًا لشروط الترخيص التي يضعها صانعو تلك المنصات. وبصرف النظر عن المحرّك الذي تستخدمه، سيكون إصدار نسخة من اللعبة على منصة أمرًا مجهدًا. ما الذي يمكن لمحرك جودو فعله؟ طوّر محرّك جودو أصلًا في المنزل من قبل استدوديو ألعاب أرجنتيني، وقد بدأ العمل عليه عام 2001 ثم حُسِّن كثيرًا منذ ذلك الحين وحتى إطلاق النسخة مفتوحة المصدر منه عام 2014. من اﻷلعاب التي طوّرت باستخدام جودو نذكر "Ex-Zodiac" و "Helms of Fury": ومن التطبيقات التي تعتمد عليه نجد برنامج الرسم النقطي مفتوح المصدر "Pixelorama" وكذلك "voxel RPG creator": كيف يعمل محرك جودو وكيف يبدو؟ يأتي المحرّك مع محرر ألعاب كامل الميزات وأدوات أصلية مدمجة معه لتقدم حلولًا لمعظم المهام الشائعة.من هذه اﻷدوات محرر شيفرة ومحرر رسوم متحركة ومحرر خرائط tilemap editor ومحرر المعالج اللوني shader ومنقح debugger ومحلل أداء Profiler وغيرها. يجاهد الفريق لتقديم محرر ألعاب غني بالميزات مع تجربة مستخدم تتطور باستمرار، وطالما أن هناك دائمًا ما يمكن تحسينه، سيستمر تطوير واجهة المحرّك. بإمكانك أيضًا العمل على برمجيات خارجية أخرى إن أردت، إذ يقدّم المحرك دعمًا رسميًا للمشاهد ثلاثية اﻷبعاد المصممة على بلندر Blender والإضافات الخاصة ببرنامج فيجوال ستديو كود و إيماكس Emacs لدعم البرمجة باستخدام GDScript و #C. كما يدعم المحرّك أيضًا فيجيوال ستوديو ولغة #C على ويندوز. لغات البرمجة في جودو بإمكانك استخدام لغة GDScript وهي لغة برمجة عالية التكامل خاصة بمحرك جودو وتتمتع بصياغة سهلة، أو يمكن استخدام لغة #C الشائعة الاستخدام في عالم الألعاب. هاتان اللغتان هما اللغتان الرئيسيتان المدعومتان من قبل محرك جودو. لكن باستخدام اﻹضافات عبر تقنية GDExtension، ستتمكن من كتابة ألعاب أو خوارزميات باستخدام لغة C أو لغة ++C دون إعادة تصريف المحرّك. وتستطيع استخدام هذه التقنية أيضًا في دمج مكتبات يؤمنها طرف آخر وغيرها من أدوات تطوير البرمجيات SDK مع المحرّك. كما يمكنك إضافة وحدات برمجية جاهزة وميزات إلى المحرّك وهي مجانية ومفتوحة المصدر. ما الذي علي معرفته لاستخدام محرك جودو؟ يُعد محرّك جودو محركًا مبنيًا على الكثير من الميزات، ومع وجود اﻵلاف منها ستجد أن هنالك الكثير لتتعلمه. وللاستفادة من كامل إمكانياته، لا بد أن تمتلك خلفية جيدة في البرمجة. ومع أننا نحاول جعل المحرّك سهل الاستخدام، سيفيدك تعلّم التفكير مثل المبرمجين. ويعتمد المحرّك على البرمجة كائنية التوجه، لهذا ستساعدك معرفة بعض المفاهيم مثل الأصناف والكائنات في كتابة شيفرة أكثر فعالية. إما إذا كنت جديدًا في عالم البرمجة، ننصحك بالاطلاع على دورات تعلم البرمجة التي تقدمها أكاديمية حسوب والتي تأخذك خطوة بخطوة إلى طريق احتراف البرمجة. المفاهيم الرئيسية لمحرك اﻷلعاب جودو يتمحور عمل أي محرك ألعاب حول مجموعة من المفاهيم اﻷساسية التي تٌستخدم لبناء التطبيقات. وفي جودو، تُمثّل اللعبة على شكل شجرة tree مكوّنة من عقد nodes تتجمع مع بعضها لتشكل مشهدًا scene، وترتبط هذه العقد ببعضها كي تكون قادر على التخاطب فيما بينها باستخدام إشارات signals. سنلقي نظرة سريعة في هذا المقال على المفاهيم اﻷربعة السابقة ونتعلم طبيعة عمل المحرك. المَشاهد scenes تُجزّأ اللعبة في جودو إلى مشاهد يمكن استخدامها بشكل متكرر، وقد يكون المشهد شخصية أو سلاحًا أو قائمة ضمن واجهة المستخدم أو بيت أو مستوى كامل للعبة وعمومًا أي شيء قد تفكّر به. تتمتع مشاهد جودو بالمرونة، إذ تؤدي دور الكائنات الجاهزة prefab والمشاهد في محركات ألعاب أخرى. بإمكانك أيضًا إنشاء مشاهد متداخلة، كأن تضع شخصية ضمن مرحلة عن طريق سحب وافلات مشهد ضمن آخر ليكون ابنًا له. العقد nodes يتكون المشهد من عقدة أو أكثر وتمثّل هذه العقد أصغر الكتل البنائية التي ترتبها في الشجرة. إليك مثالًا عن عقدة لشخصية في لعبة: تتكون الشخصية من عقدة نوعها CharacterBody2D وتُدعى "Player" وضمنها ثلاث عقد أبناء هي Camera2D و Sprite2D و CollisionShape2D. ملاحظة: تنتهي أسماء العقد السابقة باللاحقة "2D" لأن المشهد ثنائي البعد. وتنتهي أسماء العقد في المشاهد ثلاثة اﻷلعاب باللاحقة "3D". وانتبه إلى أن العقد من النوع "الفراغي Spatial" لم تُعد تُسمّى "Node3D" ابتداءًا من الإصدار 4 لجودو. لاحظ كيف تبدو العقد والمشاهد متطابقة في المحرر، فعندما تُخزّن شجرة عقد على أنها مشهد، سيعرض المحرر عقدة واحدة ويخفي بنيتها الداخلية ضمنه. يقدّم جودو مكتبة قابلة للتوسّعة تضم أنواعًا مختلفة من العقد التي يمكن دمجها أو توسعتها لبناء عقد أقوى. فكل ما ستبنيه وتتعامل معه سواء في التصاميم ثنائية أو ثلاثية اﻷبعاد هي العقد. شجرة المشهد scene tree تتجمع كل مشاهد اللعبة في شجرة من المشاهد أو (شجرة مشهد scene tree)، وشجرة المشاهد هي شجرة من العقد لكن من اﻷسهل تخيّل اللعبة كمشاهد لأنها تمثّل الشخصيات واﻷسلحة واﻷبواب والواجهات بطريقة أوضح. اﻹشارات signals ترسل العقد إشارات عندما تقع بعض الأحداث، وتساعدك هذه الميزة في تأسيس اتصالات بين العقد دون أن تفعل ذلك يدويًا ضمن الشيفرة، مما يمنحك مرونة في هيكلة المشاهد. ملاحظة: تُعد اﻹشارات نسخة جودو من من نمط "المراقب observer" في محركات أخرى. تُرسل اﻷزرار إشارات عند النقر عليها مثلًا، وبالتالي يمكنك الاتصال بهذه اﻹشارة لتشغيل شيفرة محددة كاستجابة لحدث معين، كبدء اللعبة أو عرض قائمة. وقد تخبرك إشارات أخرى مدمجة عن تصادم كائنين أو عند دخول شخصية منطقة محددة وغيرها الكثير. وبإمكانك تعريف إشارات جديدة مخصصة للعبتك. خلاصة تعرفنا في هذا المقال على المفاهيم البنيوية اﻷريعة لمحرك اﻷلعاب جودو والعقد والمشاهد وشجرة المشاهد واﻹشارات وهي ما ستتعامل معه دائمًا. فالعقد هي الكتل البنائية اﻷصغر في اللعبة والتي تجمع بينها لتشكل مشهدًا ثم تجمع المشاهد لتشكل شجرة مشاهد. ثم تستخدم بعد ذلك اﻹشارات كي تتفاعل العقد مع اﻷحداث التي تقع في عقد أخرى أو فروع أخرى من شجرة المشاهد. قد تخطر في بالك اﻵن الكثير من اﻷسئلة، لهذا نطلب منك التروي ومتابعة ما ستعرضه في مقالات أخرى لتحصل على الكثير من اﻷجوبة. ترجمة -وبتصرف- للمقال Introduction to Godot والمقال Overview of Godot's key concepts. اقرأ أيضًا أشهر أنواع الألعاب الإلكترونية مطور الألعاب: من هو وما هي مهامه أشهر لغات برمجة الألعاب
×
×
  • أضف...