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

الاستماع لمدخلات اللاعب في جودو Godot


Naser Dakhel

نشرح في مقال اليوم كيفية إضافة ميزة مهمة لأي لعبة بناء على المقال السابق الذي أنشأنا فيه سكربت للعبة بسيطة لتحريك أيقونة جودو Godot في مسارات دائرية، ألا وهي إعطاء التحكم بالحركة للاعب، ولذلك نحتاج لتعديل الكود البرمجي الذي كتبناة في ملف sprite_2d.gd.

1 

لدينا أداتان رئيسيتان لمعالجة مدخلات اللاعب في جودو هما:

  • دوال رد نداء الدخل المضمّنة في جودو built-in input callbacks، وبالأخص الدالة _unhandled_input()‎_ التي تستدعى لمعالجة الأحداث التي لم يتم التعامل معها بواسطة العقد الأخرى والدالة ‎_process()‎ وهي دالة افتراضية مضمنّة تستدعيها جودو كل مرة يضغط فيها اللاعب على مفتاح وتُستخدم للتفاعل مع الأحداث التي لا تحصل في كل إطار بشكل مستمر مثل الضغط على Space للقفز، راجع استخدام InputEvent للمزيد عن استرجاع استدعاءات المدخلات
  • الكائن المتفرّد Input، إن الكائنات المتفردة Singelton هي عبارة عن كائنات يمكن الوصول إليها بشكل عام، وتقدم جودو الوصول للعديد منها في السكربتات، إنها الأداة الأفضل لتفقد المدخلات في كل إطار.

سنستخدم الكائنInput لأننا نريد أن نعرف إذا ما كان يريد اللاعب التحرك أو الدوران في كل إطار.

يجب استخدام المتغير الجديد direction من أجل الدوران، استبدل السطر rotation += angular_speed * delta في دالة ‎_process()‎ بالشيفرة التالية:

بلغة GDScript:

var direction = 0
if Input.is_action_pressed("ui_left"):
    direction = -1
if Input.is_action_pressed("ui_right"):
    direction = 1

rotation += angular_speed * direction * delta

بلغة C#‎:

var direction = 0;
if (Input.IsActionPressed("ui_left"))
{
    direction = -1;
}
if (Input.IsActionPressed("ui_right"))
{
    direction = 1;
}

Rotation += _angularSpeed * direction * (float)delta;

إن المتغير المحلي direction هو مُضَاعف multiplier يمثل الاتجاه الذي يريد اللاعب الدوران نحوه وزيادته تضخّم مقدار الدوران، وتمثل القيمة 0 أن اللاعب لم يضغط على مفتاح السهم اليميني أو اليساري، والقيمة 1 تعني أن اللاعب يريد الدوران نحو اليمين، و‎‎-1 تعني أنه يريد الدوران نحو اليسار.

يجب التصريح عن مجموعة شروط واستخدام Input لإنتاج هذه القيم، نبدأ الشرط بالكلمة المفتاحية if في GDScript وننهيها بنقطتين، ويكون الشرط هو التعبير بين الكلمة المفتاحية ونهاية السطر.

نستدعي Input.is_action_pressed()‎ للتحقق فيما إذا كان المفتاح مضغوطًا ضمن هذا الإطار، إذ يأخذ التابع سلسلة نصية تمثل المدخلات ويعيد true إذا كان المفتاح قد ضُغط وإلا يعيد false.

إن الفعلين المستخدمين سابقًا "uileft" و "uiright" مُعرفين مسبقًا في جودو، إذ يُفعّلان عندما يضغط اللاعب السهمين اليميني واليساري على لوحة المفاتيح أو الزرين اليمين واليسار على قبضة التحكم.

ملاحظة: يمكن مشاهدة وتعديل المدخلات في المشروع الخاص بك بالذهاب إلى "إعدادات المشروع Project settings" والنقر على تبويبة "خريطة الإدخال Input Map". أخيرًا نستخدم direction كمُضاعف عند تحديث زاوية الدوران rotation الخاص بالعقدة:
 

 rotation += angular_speed * direction * delta

يجب أن تتحرك الأيقونة عند الضغط على Left و Right عند تشغيل المشهد بهذه الشيفرة.

التحرك عند الضغط على Up

نحتاج لتعديل الشيفرة التي تحسب السرعة velocity من أجل التحرك عند الضغط فقط، بدّل السطر الذي يبدأ بـ var velocity بالشيفرة التالية:

بلغة GDScript:

var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_up"):
    velocity = Vector2.UP.rotated(rotation) * speed

بلغة C#‎:

var velocity = Vector2.Zero;
if (Input.IsActionPressed("ui_up"))
{
    velocity = Vector2.Up.Rotated(Rotation) * _speed;
}

هيئنا متجه السرعة velocity بالقيمة Vector2.ZERO وهو ثابت مضمّن في نوع Vector يمثل متجه ثنائي الأبعاد بطول 0.

إذا ضغط اللاعب "ui_up" نحدث قيمة السرعة وتتحرك الشخصية إلى الأمام.

2.gif

البرنامج الكامل

التالي هو الملف الكامل sprite_2d.gd كمرجع.

بلغة GDScript:

extends Sprite2D

var speed = 400
var angular_speed = PI


func _process(delta):
    var direction = 0
    if Input.is_action_pressed("ui_left"):
        direction = -1
    if Input.is_action_pressed("ui_right"):
        direction = 1

    rotation += angular_speed * direction * delta

    var velocity = Vector2.ZERO
    if Input.is_action_pressed("ui_up"):
        velocity = Vector2.UP.rotated(rotation) * speed

    position += velocity * delta

بلغة C#‎:

using Godot;

public partial class MySprite2D : Sprite2D
{
    private float _speed = 400;
    private float _angularSpeed = Mathf.Pi;

    public override void _Process(double delta)
    {
        var direction = 0;
        if (Input.IsActionPressed("ui_left"))
        {
            direction = -1;
        }
        if (Input.IsActionPressed("ui_right"))
        {
            direction = 1;
        }

        Rotation += _angularSpeed * direction * (float)delta;

        var velocity = Vector2.Zero;
        if (Input.IsActionPressed("ui_up"))
        {
            velocity = Vector2.Up.Rotated(Rotation) * _speed;
        }

        Position += velocity * (float)delta;
    }
}

تستطيع الآن الدوران باستخدام الأسهم يمين ويسار والتحرك للأمام عن طريق ضغط Up إذا شغّلت المشهد.

الخلاصة

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

إن المتغيرات التي تضعها في أول الملف بلغة GDScript هي خاصيات الصنف، التي تدعى متغيرات الأعضاء، ويمكن تعريف الدوال التي ستكون في أغلب الأحوال دوال الأصناف الخاصة بك.

تقدم جودو العديد من التوابع الافتراضية التي يمكن تعريفها لتتصل مع الأصناف الخاصة بك مع المحرك، وتضم  الدالة‎_process()‎‎ لتطبيق التغييرات للعقدة في كل إطار، والدالة ‎‏‎‎‎‏unhandled_input()‎‎_‏‏‎‏‏‎ لاستقبال المدخلات مثل ضغط المفاتيح أو الأزرار من المستخدم، وهناك المزيد أيضًا. كما يسمح الصنف المتفرد Input بالتفاعل مع إدخالات اللاعب في أي مكان من الشيفرة الخاصة بك، وستستخدمها بالتحديد في حلقة ‏‏‏‎‏process()‎‎‎_

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

ترجمة - وبتصرف - لقسم Listening to player input من توثيق جودو الرسمي.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...