نتعرف في هذا المقال على طريقة بناء شريط صحة Health Bar يضم قلوبًا أو غيرها من اﻷيقونات، كما سنتعرف على طريقة عرض نسبة تضرر الشخصية في لعبة على شكل نص يطفو فوق الشخصية.
ثلاث طرق لبناء شريط صحة يضم قلوبًا
من الطرق الشائعة في إظهار صحة اللاعب عرض سلسلة من اﻷيقونات -غالبًا بشكل قلوب- يختفي بعضها عندما يتعرض اللاعب إلى ضرر. وسنناقش ثلاث طرق لعرض الأيقونات أطلقنا عليها تسميات بسيطة simple وفارغة empty وجزئية partial.
تعرض الصورة السابقة ثلاث حالات ممكنة لعرض شريط الصحة:
- الطريقة البسيطة: تعرض القلوب ممتلئة بالكامل
- الطريقة الفارغة: تعرض قلوب فارغة وأخرى ممتلئة
- الطريقة الجزئية: تعرض القلوب نصف ممتلئة
إعداد شريط اﻷيقونات
نستخدم في هذا المثال صور قلوب أبعادها 53x45 حصلنا عليها من موقع Kenney.nl: Platformer Art Deluxe. ومن المفترض أن يكون وضع الشريط ضمن شاشة عرض معلومات المستخدم HUD أو واجهة المستخدم UI سهلًا، لذا من المنطقي أن نبني هذا الشريط ضمن مشهد مستقل.
سنبدأ بعقدة من النوع Node2D
كي نُبقى اﻷمور على نفس السوية، ونضبط قيمة الخاصية Sepration
ضمن Constants
في القسم Theme Overrides
من الفاحص على القيمة 5
.
نضيف بعد ذلك عقدة ابن من النوع TextureRect
ثم نسحب أيقونة القلب إلى الخاصية Texture
ونضبط قيمة Strech Mode
على Keep
. نعيد تسمية العقدة لتكون 1
ثم باستخدام مفتاحي Ctrl+D ننسخ هذه العقدة بعدد القلوب التي نريد عرضها في الشريط 5 مثلًا. ستبدو لوحة العقد في محرك جودو كالتالي:
إضافة السكريبت
يغطي السكريبت التالي حالات الشريط الثلاث التي ذكرناها، حيث سنحمّل في البداية الخامات وهي هنا اﻷيقونات التي نحتاجها ونعرف اﻷشرطة الثلاث، وتجدر الملاحظة بأن الكود سيغطي جميع حالات الشريط الثلاثة، وقد نحتاج لاستخدام حالة واحدة فقط في اللعبة، عندها نزيل الكود المتعلق بالحالات الأخرى كما يلي:
extends HBoxContainer enum modes {SIMPLE, EMPTY, PARTIAL} var heart_full = preload("res://assets/hud_heartFull.png") var heart_empty = preload("res://assets/hud_heartEmpty.png") var heart_half = preload("res://assets/hud_heartHalf.png") @export var mode : modes func update_health(value): match mode: MODES.simple: update_simple(value) MODES.empty: update_empty(value) MODES.partial: update_partial(value)
يؤدي استدعاء الدالة ()update_health
العائدة إلى الشريط عرض القيمة الممرة إليه وفقًا للنمط المختار.
ملاحظة: لن نضيف آليات تحقق من حدود القيمة المدخلة كالتأكد مثلًا من أن الصحة بين 0 و 100، فهناك طرق كثيرة لعرض الصحة في اﻷلعاب لذا سنترك الأمر لكم.
نتنقل في الدالة ()update_simple
بين أشرطة الأيقونات ونضبط ظهور كل عقدة TextureRect
:
func update_simple(value): for i in get_child_count(): get_child(i).visible = value > i
واﻷمر مشابه في الدالة ()update_empty
ما عدا أننا نغير اﻷيقونة إلى اﻷيقونة الفارغة بدلًا من إخفائها:
func update_empty(value): for i in get_child_count(): if value > i: get_child(i).texture = heart_full else: get_child(i).texture = heart_empty
أما في الحالة اﻷخيرة، فلدينا أيقونة ثالثة وضعف القيم الممكنة فمن خلال إنقاص القيمة بمقدار 1 مثلًا يعطي نصف قلب وإنقاص 1 مرة أخرى تعطي قلبًا فارغًا:
func update_partial(value): for i in get_child_count(): if value > i * 2 + 1: get_child(i).texture = heart_full elif value > i * 2: get_child(i).texture = heart_half else: get_child(i).texture = heart_empty
توضح الصورة أدناه مثالًا عن عمل كل شريط:
إنشاء نصوص طافية فوق الشخصية
هناك طرق عدة لتحقيق النصوص الطافية floating text، منها استخدام خط كتابة نقطية bitmap font وبناء صورة لكل عدد انطلاقًا من اﻷرقام المكونة له، ومن ثم استخدام العقدة Sprite2D
لعرض وتحريك النص الناتج.
لكن ما سنفعله في مقالنا هو استخدام العقدة Label
واسمها FCT وبهذا سنمتلك مرونة في تغيير الخط إضافة إلى سهولة عرض اﻷعداد كنصوص أو عرض نصوص أخرى مثل "أخفق miss".
نضيف المورد الذي نريده في الخاصية Label Settings
ونختار خطًا مناسبًا وقياسًا مناسبًا له، وقد استخدمنا في المثال الخط Xolonium.ttf والقياس 28
مع إطار خارجي أسود بعرض 4 بكسل.
نضيف اﻵن السكريبت التالي إلى العقدة Label
:
extends Label func show_value(value, travel, duration, spread, crit=false):
نستدعي عند توليد النصوص الطافية الدالة ()show_value
التي تضبط قيم المعاملات التالية:
-
value
وهو العدد أو النص الذي نريد توليده -
travel
وهو عقدة شعاعVector2
التي تمثل اتجاه حركة النص أو العدد -
duration
تحدد كم سيبقى النص على قيد الحياة -
spread
يحدد أن الحركة ستكون عشوائية عبر هذا القوس -
crit
يشير لأن الضرر كبير في حال كانت قيمتهtrue
وهذا ما تفعله الدالة ()show_value
:
text = value var movement = travel.rotated(rand_range(-spread/2, spread/2)) rect_pivot_offset = rect_size / 2
تضبط الدالة قيمة النص أو العدد ومن ثم تجعل حركته عشوائية وفقًا لقيمة الانتشار spread
مابين 90+ و90- مثلًا. وقد نغير أبعاد النصوص المتحركة، لهذا ضبطنا قيمة الخاصية rect_pivot_offset
لتمثل مركز عنصر التحكم وبالتالي يكون تغيير اﻷبعاد منسوبًا إلى المركز.
$Tween.interpolate_property(self, "rect_position", rect_position, rect_position + movement, duration, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT) $Tween.interpolate_property(self, "modulate:a", 1.0, 0.0, duration, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
نجري بعد ذلك استيفاء interpolation على قيمتي الخاصية بين لحظتين هما rect_position
لتحريك العدد الطافي و modulate.a
ﻹخفاء هذا النص بشكل تدريجي وسلس:
if crit: modulate = Color(1, 0, 0) $Tween.interpolate_property(self, "rect_scale", rect_scale*2, rect_scale, 0.4, Tween.TRANS_BACK, Tween.EASE_IN)
إن كانت اﻹصابة بالغة، سنغير لون النص ونزيد حجمه لإظهار التأثير. وتجدر الملاحظة بأننا حددنا لون النص في هذه الحالة ليكون أحمر ومن اﻷفضل أن تعرف متحولًا لإسناد قيمة اللون الذي نريده:
$Tween.start() yield($Tween, "tween_all_completed") queue_free()
نبدأ بعد ذلك عملية بناء اﻹطارات البينية من خلال التعليمة Tween
وننتظر حتى تنتهي ثم نزيل العنوان Label
.
إدراة النصوص الطافية FCTManager
ننشئ اﻵن عقدة صغيرة تدير توليد النصوص وتحديد مكانها، وستُلحق بكيانات اللعبة التي نريد أن نضيف إليها تأثير النصوص الطافية. نسمي هذه العقدة من النوع Node2D
بالاسم FCTManager
ونضيف إليها السكريبت التالي:
extends Node2D var FCT = preload("res://FCT.tscn") export var travel = Vector2(0, -80) export var duration = 2 export var spread = PI/2 func show_value(value, crit=false): var fct = FCT.instance() add_child(fct) fct.show_value(str(value), travel, duration, spread, crit)
يمكن تعديل ما نريده من خصائص العقدة من خلال نافذة الفاحص Inspector، لكن الدالة ()show_value
أيضًا تولد النص الطافي وتضبط خصائصه. وبإمكاننا إلحاق نسخة من هذه العقدة بأي وحدة من وحدات اللعبة نريدها أن تمتلك تأثير النصوص الطافية، ثم نضيف كود مشابه لما يلي ضمن التابع ()take_damage
للوحدة:
$FCTManager.show_value(dmg, crit)
تجدر الإشارة لأنه في الحالة التي تضم فيها لعبتنا عددًا كبيرًا من الوحدات، فقد يؤثر هذا اﻷمر على اﻷداء جراء توليد وتحرير النصوص الطافية باستمرار لعدد كبير من الوحدات. في حالات كهذه، ينصح بتوليد عدد محدد تمامًا من النصوص الطافية من خلال FCTManager
ثم نظهرها ونخفيها بدلًا من توليدها وتحريرها في نهاية الحركة.
الخاتمة
تعرفنا في هذا المقال على طريقة بناء شريط صحة يضم أيقونات تعرض حالة اللاعب مثل تناقص صحته أو نفاذ ذخيرته، كما تحدثنا عن أحد طرق لتوليد نصوص تطفو حول الشخصية وتختفي للدلالة على حالة معينة مثل مقدار اﻹصابة التي تلقتها.
ترجمة -وبتصرف- للمقالين: HeartContainers: 3 ways و Floating Combat Text
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.