آخر ما يلزمنا ﻹكمال اللعبة ثنائية الأبعاد تفادي الزواحف التي بدأنا العمل عليها في مقال سابق هو بناء واجهة المستخدم 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
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.