في هذا المقال ستبرمج لعبتك الأولى لتحريك أيقونة جودو Godot في مسارات دائرية باستخدام لغة البرمجة GDScript. وسنفترض أنك على معرفة بأساسيات البرمجة، وتعرف ما هي لغات البرمجة المتاحة في محرك الألعاب جودو لتتمكن من تنفيذ برنامجك الأول الذي سيحرك الصورة في مسار دائري كما في الصورة التالية:
إعداد المشروع
من الأفضل إنشاء مشروع جديد للبدء من الصفر، ويجب أن يحتوي مشروعك على صورة واحدة فقط هي أيقونة محرك الألعاب جودو التي تستخدم غالبًا في مجتمع المطورين لبناء النماذج الأولية.
ستحتاج إلى إنشاء عقدة Sprite2D
لعرضها في اللعبة، لذا عليك أن تنتقل للتبويب "مشهد Scene"، ثم تنقر فوق الزر"عقدة أخرى Other Node".
اكتب Sprite2D
في شريط البحث لتصفية النتائج، ثم انقر نقرًا مزدوجًا على Sprite2D
لإنشاء العقدة.
يُفترض أن تحوي علامة تبويب المشهد الآن على عقدة Sprite2D
فقط.
تحتاج عقدة Sprite2D
إلى خلفية للعرض. وستلاحظ من قائمة "الفاحص" Inspector على اليمين أن خاصية Texture تشير إلى أنها فارغة، لعرض أيقونة جودو، انقر واسحب ملف الأيقونة icon.svg
من قائمة نظام الملفات FileSystem إلى الخانة Texture
ملاحظة: يمكنك إنشاء عقد Sprite2D
تلقائيًا عن طريق سحب وإفلات الصور في نافذة العرض، ثم انقر واسحب الأيقونة في نافذة العرض لتثبيتها في وسط نافذة اللعبة.
إنشاء نص برمجي جديد
لإنشاء سكربت أو نص برمجي جديد وربطه بالعقدة، انقر بزر الفأرة الأيمن على Sprite2D
في قائمة "المشهد Scene" وحدد خيار "إلحاق نص برمجي Attach Script" كما في الصورة التالية:
ستظهر نافذة "إلحاق نص برمجي Attach Node Script"، حيث تتيح لك تحديد لغة النص البرمجي ومسار الملف من بين خيارات أخرى.
غيّر حقل "القالب Template" من "Node: Default" (أي عقدة افتراضية) إلى "Object: Empty" (أي كائن فارغ) وذلك لبدء العمل بملف فارغ، ثم اترك الخيارات الأخرى على قيمها الافتراضية وانقر فوق الزر "أنشئ Create" لإنشاء النص البرمجي.
ملاحظة: يجب أن تتطابق أسماء ملفات سكربت C# مع اسم الصنف الذي تتبع له. في هذه الحالة، يجب تسمية الملف MySprite2D.cs
من المفترض أن تظهر مساحة عمل لكتابة الكود البرمجي مع فتح ملف sprite_2d.gd
الجديد وسطر الشيفرة البرمجية التالية:
بلغة GDScript:
extends Sprite2D
بلغة C#:
using Godot; public partial class MySprite2D : Sprite2D { }
كل ملف GDScript هو عبارة عن صنف class بشكل ضمني. وتُحدد الكلمة المفتاحية extends
الصنف الذي يرثه أو يوسعه هذا الكود البرمجي. في هذه الحالة الصنف هو Sprite2D
، مما يعني أن الكود البرمجي سيصل إلى جميع خصائص ودوال عقدة Sprite2D
، بما في ذلك الأصناف التي ترث منها هذه العقدة مثل Node2D
و CanvasItem
و Node
ففي حالتنا هذه يرث الصنف Sprite2D يرث من Node2D، والذي بدوره يرث من CanvasItem. وبالتالي سيصل صنفك الجديد إلى خصائص ودوال كل من Sprite2D و Node2D و CanvasItem.
ملاحظة: إذا أغفلت السطر الذي يحتوي على الكلمة المفتاحية extends
في لغة GDScript سيمدّد الصنف تلقائيًا إلى عقدة RefCounted
، أي سيصبح بشكل افتراضي صنفًا فرعيًا من RefCounted الذي يستخدمه محرك ألعاب جودو لإدارة ذاكرة تطبيقك.
يمكنك رؤية كافة الخصائص الموروثة في قائمة "الفاحص Inspector"، مثل خاصية texture
الخاصة بالعقدة مما يسمح لك بتحريرها بسهولة داخل المحرر أو برمجيًا داخل النص البرمجي.
ملاحظة: تعرض قائمة "الفاحص Inspector" خصائص العقدة في "حالة العنوان Title Case" افتراضيًا، مع كلمات بأحرف كبيرة ومنفصلة باستخدام مسافة. أما في شيفرة GDScript، فتكون هذه الخصائص مكتوبة بحالة الثعبان snake_case (أي بحالة الأحرف الصغيرة مع كلمات مفصولة عن بعضها باستخدام شرطة سفلية_).
يمكنك التمرير فوق اسم أي خاصية في قائمة "الفاحص" Inspector لرؤية وصفها ومعرّفها في الشيفرة.
تعليمة طباعة Hello World
لا ينفذ النص البرمجي حاليًا أي شيء. سنجعله يطبع النص Hello world في الخرج.
أضف الشيفرة التالية إلى نصك البرمجي:
بلغة GDScript:
func _init() : print(“Hello, world!”)
بلغة C#:
public MySprite2D() { GD.Print("Hello, world!"); }
دعونا نشرح ما سبق. تُحدد الكلمة المفتاحية func
دالة جديدة تسمى _init
وهو اسم خاص لمنشئ أو باني الصنف لدينا. إذا عرّفت هذه الدالة، فسوف يستدعي جودو دالة _init()
لكل كائن أو عقدة عند إنشائه في الذاكرة.
ملاحظة: لغة البرمجة GDScript هي لغة تعتمد على المسافة البادئة، فالفراغ في بداية السطر الذي يحوي تعليمة الطباعة ()print
ضروري لعمل الشيفرة البرمجية، فإذا أغفلتها أو لم تضع مسافة بادئة في بداية السطر بشكل صحيح سينبهك المحرر عليها باللون الأحمر ويعرض رسالة الخطأ التالية: "مسافة بادئة مطلوبة".
احفظ المشهد باسم sprite_2d.tscn إذا لم تكن قد فعلت ذلك بالفعل، ثم اضغط على F6
(Cmd + R
على macOS) لتشغيله. انظر إلى اللوحة السفلية للخرج لترى النص Hello world
احذف الدالة _init()
، بحيث يتبقى لديك فقط السطر extends Sprite2D
.
تدوير العقدة
حان الوقت لتحريك العقدة وتدويرها. لفعل بذلك، سنضيف متغيرين جديدين إلى النص البرمجي هما سرعة الحركة المقاسة بوحدة البكسل في الثانية، والسرعة الزاوية المقاسة بالراديان في الثانية. أضف التالي بعد السطر extends Sprite2D
.
بلغة GDScript:
var speed = 400 var angular_speed = PI
بلغة C#:
private int _speed = 400; private float _angularSpeed = Mathf.Pi;
نكتب المتغيرات الجديدة بالقرب من بداية النص البرمجي، بعد الأسطر التي تحوي extends، وقبل الدوال. وستحتوي كل نسخة عقدة مرتبطة بهذا النص البرمجي على نسخة خاصة بها من خصائص speed
و angular_speed
.
ملاحظة: تقاس الزوايا في محرك جودو بالراديان افتراضيًا، ولكن هناك دوال وخصائص مدمجة متاحة إذا كنت تفضل حساب الزوايا بالدرجات بدلاً من ذلك.
لتحريك أيقونة جودو، نحتاج إلى تحديث موقعها وتدويرها في كل إطار ضمن حلقة اللعبة. يمكننا استخدام الدالة الافتراضية _process()
الخاصة بالصنف Node
. فإذا عرفتها في أي صنف يوسع الصنف Node
مثل Sprite2D
فسوف يستدعي جودو هذه الدالة في كل إطار ويمرر له قيمة باسم دلتا delta
تمثل المدة الزمنية التي انقضت منذ الإطار الأخير.
ملاحظة: تعمل الألعاب عن طريق عرض العديد من الصور في الثانية يطلق على كل منها إطار، ويتم ذلك بشكل حلقة متكررة. نقيس المعدل الذي تنتج فيه اللعبة الصور بمعدل الإطارات في الثانية (FPS). تهدف معظم الألعاب إلى 60 إطارًا في الثانية، على الرغم من أنك قد تجد أرقامًا مثل 30 إطارًا في الثانية على أجهزة الجوال الأبطأ أو أرقام بين 90 إلى 240 في ألعاب الواقع الافتراضي.
يبذل المطورون قصارى جهدهم لتحديث عالم الألعاب وعرض الصور بفواصل زمنية ثابتة، لكن هناك دائمًا اختلافات بسيطة في أوقات عرض الإطارات. لهذا السبب يعطي جودو قيمة زمن دلتا delta
، كي يجعل الحركة مستقلة عن معدل الإطارات.
في نهاية الكود البرمجي، عرّف الدالة _process()
كما يلي:
بلغة GDScript:
func _process(delta) : rotation += angular_speed * delta
تحدد الكلمة المفتاحية func
في الكود السابق دالة جديدة. بعد ذلك علينا كتابة اسم الدالة والقيم التي تأخذها بين قوسين. وتنهي النقطتان : التعريف وتمثل الكتل التي تتبعها محتوى الدالة أو تعليماتها.
بلغة C#:
public override void _Process(double delta) { Rotation += _angularSpeed * (float)delta; }
ملاحظة: لاحظ كيف أن الدالة _process()
مثل الدالة _init()
تبدأ بشرطة سفلية. ووفق العُرف المتبع، تبدأ جميع دوال جودو الافتراضية بشرطة سفلية وهي ذاتها الدوال المضمنة التي يمكنك تعريفها للتواصل مع جودو.
يستخدم السطر rotation += angular_speed * delta
داخل الدالة لتحديث دوران العقدة أو الصورة في كل إطار استنادًا إلى سرعة الدوران والمدة الزمنية المنقضية، حيث أن الخاصية rotation
هي خاصية موروثة عن الصنف Node2D
التي تمتد منها العقدة Sprite2D
وهي تتحكم في دوران العقدة.
اقتباسنصيحة: في محرر الشيفرة، يمكنك ضغط ctrl على أي خاصية أو دالة مدمجة مثل
position
أوrotation
أو_process
لفتح الوثائق المعنية في علامة تبويب جديدة.
شغّل المشهد لمشاهدة أيقونة جودو تدور في مكانها.
اقتباسملاحظة: لاحظ في لغة C# كيف أن القيمة
delta
التي تأخذها الدالة_Process()
من نوعdouble
، لذلك يجب تحويلها إلى نوعfloat
عند تطبيقها على الدوران.
متابعة العمل على تحريك العقدة
دعنا الآن نجعل العقدة تتحرك في مسار دائري.
أضف السطرين التاليين داخل دالة _process()
مع التأكد من إضافة مسافة بادئة للسطرين الجديدين بنفس طريقة المسافة البادئة للسطر rotation += angular_speed * delta
قبلهما.
بلغة GDScript:
var velocity = Vector2.UP.rotated(rotation) * speed position += velocity * delta
بلغة C#:
var velocity = Vector2.Up.Rotated(Rotation) * _speed; Position += velocity * (float)delta;
كما رأينا سابقًا، تحدد الكلمة المفتاحية var
متغيرًا جديدًا. فإذا وضعته في بداية النص البرمجي، فإنه يُحدد خاصية الصنف. بينما إذا وضعته داخل الدالة، فإنه يُحدد متغيرًا محليًا يوجد ضمن نطاق الدالة نفسها فقط.
نحدد متغيرًا محليًا يسمى velocity
وهو متجه ثنائي الأبعاد يمثل الاتجاه والسرعة معًا. لتحريك العقدة للأمام، نبدأ من ثابت الصنف Vector2 وهو Vector2.UP
يمثل متجه يشير لأعلى، ونديره عن طريق استدعاء طريقة Vector2 وهي rotated()
.
التعبير التالي Vector2.UP.rotated(rotation)
هو شعاع يشير إلى الأمام بالنسبة إلى صورة الأيقونة مضروبًا بخاصية speed
، حيث يعطينا سرعة يمكننا استخدامها لتحريك العقدة للأمام.
نضيف velocity * delta
إلى psotion
العقدة لتحريكها. والموقع نفسه من نوع Vector2 وهو نوع مدمج في جودو يمثل متجه ثنائي الأبعاد.
شغّل المشهد الآن لمشاهدة أيقونة جودو تتحرك في مسار دائري.
بهذا نكون انتهينا من كتابة كود برمجي لتحريك العقدة بمفردها في محرك ألعاب جودو. وستتعلّم في الدرس التالي كيفية الحصول على مدخلات من اللاعب واستخدامها للتحكم بالعقدة.
النص البرمجي الكامل لتحريك العقدة
فيما يلي ملف sprite_2d.gd
الكامل لاستخدامه كمرجع.
بلغة GDScript:
extends Sprite2D var speed = 400 var angular_speed = PI func _process(delta) : rotation += angular_speed * delta var velocity = Vector2.UP.rotated(rotation) * speed position += velocity * delta
بلغة C#:
using Godot; public partial class MySprite2D : Sprite2D { private int _speed = 400; private float _angularSpeed = Mathf.Pi; public override void _Process(double delta) { Rotation += _angularSpeed * (float)delta; var velocity = Vector2.Up.Rotated(Rotation) * _speed; Position += velocity * (float)delta; } }
الخلاصة
تعلمنا في مقال اليوم طريقة كتابة برنامج بسيط لتحريك العقد في جودو وضبط سرعتها واتجاهها، والجدير بالذكر أنّ تحريك العقدة الذي تعلمناه في هذا المقال لا يأخذ بعين الاعتبار الاصطدام بالجدران أو الأرض. وستتعلّم المزيد عند إنشاء أول لعبة ثنائية الأبعاد في جودو ونستخدم نهجًا آخر لتحريك الكائنات مع اكتشاف التصادمات.
ترجمة بتصرف لقسم Creating your first script من توثيق جودو الرسمي.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.