بدأنا في المقال السابق شرح بعض المفاهيم الرياضية الأساسية التي يحتاج مطور الألعاب لمعرفتها، مثل الاستيفاء الخطي linear interpolation -أو lerp اختصارًا- والجداء النقطي Dot Product، والجداء الشعاعي Cross Product. وسنستكمل في مقال اليوم شرح مفهوم رياضي مهم وهو التحويلات الهندسية Transforms الذي يسمح لنا بتغيير مكان أو شكل الأشياء في الفضاء باستخدام المصفوفات.
متطلبات العمل
قبل المتابعة في قراءة هذا المقال، يجب توفر دراية جيدة عن اﻷشعة vectors وكيفية استخدامها في تطوير اﻷلعاب. لهذا ننصح بالعودة إلى سلسلة مقالات الأشعة على أكاديمية حسوب، ومطالعة مقال رياضيات اﻷشعة ضمن توثيق جودو الرسمي.
التحويلات في المستوي ثنائي البعد
نستخدم في المستوي أو في الفضاء ثنائي البعد اﻹحداثيات المألوفة X
و Y
، ولنتذكر أنه في محرك ألعاب جودو وفي معظم التطبيقات الرسومية في الحواسيب، يشير المحور Y إلى اﻷسفل كما في الصورة التالية:
ولكي نوضح الفكرة، لنتأمل شكل سفينة الفضاء ثنائي البعد في الصورة التالية:
تشير السفينة هنا إلى نفس اتجاه المحور X
، فلو أردنا منها التحرك نحو اﻷمام، نضيف مقدار الحركة إلى الإحداثي اﻷفقي X
فتتحرك نحو اليمين:
position += Vector2(10, 0)
لكن ما الذي يحدث عندما تدور السفينة؟
كيف يمكن اﻵن تحريكها نحو اﻷمام؟ إن كنتم تتذكرون علم المثلثات في المدرسة، فقد تبدأون بالتفكير في الزوايا والنسب المثلثية sin و cos، ثم تنفذون عملية حسابية مثل:
position += Vector2(10 * cos(angle), 10 * sin(angle))
سيعمل هذا الحل، لكن هناك طرق أفضل تلائم عملنا مع اﻷلعاب تعتمد بشكل أساسي على مفهوم التحويلات الهندسية transforms.
لنلق نظرة مجددًا على السفينة التي تدور، ولنتخيل هذه المرة أن للسفينة منظومة إحداثياتها الخاصة التي تحملها معها ولا تتعلق بإحداثيات الشاشة العامة:
تُخزّن هذه اﻹحداثيات المحلية ضمن الكائن transform
، وبالتالي، يمكن تحريك السفينة إلى اﻷمام وفقًا للمحور X
الخاص بها ولا حاجة أن نفكر بالزوايا والدوال الرياضية اﻷخرى. ولتنفيذ اﻷمر في جودو، نستخدم الخاصية transform
التي تمتلكها جميع العقد المشتقة من Node2D
.
position += transform.x * 10
ينص السطر السابق على إضافة الشعاع X
للتحويل مضروبًا بالعدد 10.
لنشرح هذا الأمر بشيء من التفصيل، تضم الخاصية transform
اﻹحداثيين x
و y
الممثلان للإحداثيات المحلية الخاصة بالعقدة، وهما شعاعي واحدة unit vector أي أن طويلة كل منهما تساوي الواحد. كما يطلق على هذان الشعاعان شعاعي توجيه direction vectors، ويدلان على الاتجاه الذي يشير إليه المحور X
الخاص بالسفينة. نضرب بعد ذلك شعاعي التوجيه بالعدد 10 لتكبيرهما والانتقال إلى مسافة أبعد.
ملاحظة: تتعلق الخاصية transform
لعقدة بالعقدة اﻷم لها أي تنسب إحداثياتها الخاصة إلى إحداثيات العقدة اﻷم. فإن أردنا الحصول على اﻹحداثيات العامة بالنسبة إلى الشاشة، نستخدم global_transform
.
تضم الخاصية transform
إضافة إلى المحاور المحلية، مكونًا يُدعى شعاع الأصل origin
ويمثل اﻹنسحاب translation أو تغيير الموضع.
يمثل الشعاع اﻷزرق في الصور التالية شعاع اﻷصل transform.origin
ويساوي شعاع الموضع position
للكائن:
التحويل بين الفضاء المحلي والعام
يمكننا تحويل اﻹحداثيات من الفضاء المحلي للعقدة إلى الفضاء العام عن طريق التحويلات. حيث تضم العقد من النوع Noode2D
والنوع Spatial
في جودو دوال برمجية مساعدة مثل ()to_local
و ()to_global
لتحقيق هذا الأمر:
var global_position = to_global(local_position)
إليكم مثالًا عن كائن في مستوي ثنائي البعد، ونريد تغيير موقع نقرة الفأرة -وهو في الفضاء العام- أي المكان الذي نقرنا فيه على الشاشة، إلى إحداثيات محلية منسوبة إلى الكائن، بمعنى آخر نريد معرفة مكان النقرة من منظور الكائن نفسه بدلاً من المكان على الشاشة، لتحقيق ذلك نكتب الكود التالي:
extends Sprite func _unhandled_input(event): if event is InputEventMouseButton and event.pressed: if event.button_index == BUTTON_LEFT: printt(event.position, to_local(event.position))
للمزيد حول آلية التحويل من إحداثيات عامة إلى إحداثيات محلية في محرك جودو ننصحكم بقراءة توثيق Transform2D
للاطلاع على كافة الخاصيات والتوابع المتاحة.
التحويلات في الفضاء ثلاثي البعد
يطبق مفهوم التحويل في الفضاء ثلاثي البعد 3D بنفس أسلوب تطبيقه في الفضاء ثنائي البعد 2D، بل يغدو تطبيقها أهم لأن العمل مع الزوايا في الفضاء ثلاثي البعد سيقود إلى مشكلات عديدة كما سنوضح بعد قليل.
ترث العقد ثلاثية البعد من العقدة الأساسية Node3D
التي تضم معلومات التحويل. ويحتاج التحويل في الفضاء ثلاثي البعد لمعلومات أكثر مقارنة مع الفضاء الثنائي البعد. حيث يبقى شعاع الموضع Position
محفوظًا ضمن الخاصية Origin
، لكن الدوران موجود ضمن خاصية تدعى basis
تضم ثلاثة أشعة واحدة unit vectors تمثل المحاور اﻹحداثية المحلية الثلاث للعقدة X
و Y
و Z
.
وعندما نختار عقدة ثلاثية البعد في محرر جودو، سنتمكن باستخدام نافذة Gizmo من عرض التحويلات والتعامل معها.
تفعيل نمط الفضاء المحلي Local Space
لنتذكر أن الفضاء العام Global Space هو الفضاء الذي يعتمد على محاور المشهد العامة. بمعنى آخر، إذا كنا نحرك أو ندير كائنًا في هذا الفضاء، فإن تحركاته ستكون بناءً على محاور العالم أو المشهد الذي يوجد فيه هذا الكائن، أما الفضاء المحلي Local Space فهو الفضاء الذي يعتمد على محاور الكائن نفسه. أي أن للكائن لديه محاور خاصة به مثل المحور X
و Y
و Z
الخاص به وعندما نحرك أو ندير الكائن في الفضاء المحلي، فإن تحركاته تكون بالنسبة له هو، وليس بالنسبة للمشهد بأكمله.
يتيح لنا محرر جودو عرض الاتجاهات المحلية للجسم والتعامل معها بسهولة، وذلك من خلال تفعيل خيار Local Space Mode، مما يسمح بتحريك الجسم أو تدويره وفقًا لمحاوره الخاصة بدلًا من محاور المشهد العامة، وستمثل المحاور الثلاث الملونة في هذا الوضع المحاور اﻷساسية المحلية للجسم.
وكما هو الحال في الفضاء ثنائي البعد، يمكننا في الفضاء ثلاثي الأبعاد استخدام المحاور المحلية لتحريك الجسم إلى اﻷمام. وفي هذه الحالة، يكون المحور Y
Y-Upوفق نظام Y-Up أي أنه موجه نحو الأعلى، وبالتالي سيكون الاتجاه الأمامي للجسم بشكل افتراضي هو المحور السالب Z-
وبالتالي كي نحرك الجسم للأمام حسب اتجاهه الخاص -وليس حسب اتجاه المشهد- نكتب الكود التالي:
position += -transform.basis.z * speed * delta
تلميح: يمتلك جودو قيم معرّفة افتراضيًا لبعض الاتجاهات الشائعة، على سبيل المثال يمثل الاختصار Vector3.FORWARD
الاتجاه الأمامي في الفضاء ثلاثي الأبعاد:
Vector3.FORWARD == Vector3(0, 0, -1)
الخاتمة
تعلمنا في هذا المقال كيف يمكن لمطور الألعاب أن يتعامل مع التحويلات الهندسية عمليًا داخل محرك ألعاب جودو سواء في المحرك ثنائي البعد 2D أو ثلاثي البعد 3D ويستفيد منها في التحكم بحركة واتجاه العناصر داخل اللعبة من خلال الخصائص المدمجة في المحرك وبعيدًا عن التعقيدات الرياضية مثل الزوايا الدوال المثلثية.
ترجمة -وبتصرف- لمقال Transforms
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.