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

سنكتشف في هذا المقال متى يدخل أو يخرج كائن من الشاشة، وسنتعرّف على كيفية إنشاء وتحريك شخصية في ألعاب المنصات ثنائية الأبعاد.

إنشاء شخصية وتحريكها في ألعاب المنصات ثنائية الأبعاد

سننشئ الأن شخصيةً في ألعاب المنصات ثنائية الأبعاد. يُفاجَأ المطورون المبتدئون في أغلب الأحيان بمدى تعقيد برمجة شخصيات ألعاب المنصات، لذا يوفر محرّك ألعاب جودو Godot بعض الأدوات المُضمَّنة للمساعدة، ولكن يمكن القول بأن هناك عددًا كبيرًا من الحلول التي تضاهي عدد الألعاب الموجودة. لن نتعمق في شرح الميزات مثل ميزات القفزات المزدوجة أو الانحناء أو القفز على الحائط أو الرسوم المتحركة، بل سنناقش أساسيات الحركة في ألعاب المنصات.

ملاحظة: يمكن استخدام العقدة RigidBody2D لإنشاء شخصية لألعاب المنصات، ولكننا سنركز على استخدام العقدة CharacterBody2D، إذ تُعَد الأجسام الحركية Kinematic مناسبةً لألعاب المنصات، حيث لن تكون مهتمًا كثيرًا بالفيزياء الواقعية بقدر الاهتمام بالشعور المتجاوب في اللعبة.

سنبدأ بعقدة CharacterBody2D، ونضيف إليها عقدتي Sprite2D و CollisionShape2D، ثم نرفق السكربت التالي بالعقدة الجذر للشخصية:

extends CharacterBody2D

@export var speed = 1200
@export var jump_speed = -1800
@export var gravity = 4000


func _physics_process(delta):
    # إضافة الجاذبية في كل إطار
    velocity.y += gravity * delta

    # ‫يؤثر الدخل على المحور x فقط
    velocity.x = Input.get_axis("walk_left", "walk_right") * speed

    move_and_slide()

    # السماح بالقفز عند وجود الشخصية على الأرض فقط
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = jump_speed

يمكننا ملاحظة أننا نستخدم إجراءات الإدخال التي عرّفناها في خريطة الإدخال InputMap وهي: "walk_right" و "walk_left" و "jump"، لذا يمكن الاطلاع على إجراءات الإدخال InputActions لمزيد من التفاصيل.

تعتمد القيم المُستخدَمة للسرعة speed والجاذبية gravity وسرعة القفز jump_speed اعتمادًا كبيرًا على حجم الشخصية الرسومية Sprite الخاصة باللاعب، وتكون خامة Texture اللاعب 108x208 بكسل في هذا المثال، وإذا كانت الصورة أصغر حجمًا، فستستخدم قيمًا أصغر.

نريد أيضًا قيمًا عالية للشعور بالسرعة والاستجابة، إذ تؤدي الجاذبية المنخفضة إلى لعبة نشعر فيها بعدم التوازن؛ بينما تمثل القيمة العالية العودة إلى الأرض بسرعة والجاهزية للقفز مرةً أخرى.

سنتحقق من التابع is_on_floor()‎ بعد استخدام الدالة move_and_slide()‎ التي تضبط قيمة هذا التابع، لذا يجب عدم التحقق منه قبل ذلك، وإلّا سنحصل على القيمة من الإطار السابق.

الاحتكاك Friction والتسارع Acceleration

تُعَد الشيفرة البرمجية السابقة بداية جيدة، إذ يمكننا استخدامها كأساس لمجموعة متنوعة من متحكمات المنصات، ولكنها تواجه مشكلة الحركة اللحظية Instantaneous Movement، ولكن يمكننا الحصول على شعور طبيعي أكثر من خلال تسارع الشخصية مثلًا حتى تصل إلى سرعتها القصوى، ثم تتوقف عند عدم وجود دخل.

إحدى الطرق لإضافة هذا السلوك هي استخدام الاستيفاء الخطي Linear Interpolation أو "lerp"، بحيث ننتقل باستخدام الاستيفاء الخطي من السرعة الحالية إلى السرعة القصوى عند التحرك، وننتقل باستخدام الاستيفاء الخطي من السرعة الحالية إلى الصفر أثناء التوقف، وبالتالي سيوفر تعديل مقدار الاستيفاء الخطي مجموعة متنوعة من أنماط الحركة.

ملاحظة: يمكن الاطلاع على مقال الاستيفاء للحصول على مزيد من المعلومات عن الاستيفاء الخطي.

extends CharacterBody2D

@export var speed = 1200
@export var jump_speed = -1800
@export var gravity = 4000
@export_range(0.0, 1.0) var friction = 0.1
@export_range(0.0 , 1.0) var acceleration = 0.25

func _physics_process(delta):
    velocity.y += gravity * delta
    var dir = Input.get_axis("walk_left", "walk_right")
    if dir != 0:
        velocity.x = lerp(velocity.x, dir * speed, acceleration)
    else:
        velocity.x = lerp(velocity.x, 0.0, friction)

    move_and_slide()
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = jump_speed

سنجرب هنا تغيير قيم الاحتكاك friction والتسارع acceleration لمعرفة مدى تأثيرها على شعورنا أثناء اللعب. فقد يحتاج مستوى الجليد إلى قيم منخفضة جدًا مثلًا، مما يجعل الحركة أصعب.

01_platformer1.gif

تمنحنا هذه الشيفرة البرمجية نقطة بداية لبناء متحكم منصات خاص بك، لذا يمكن الاطلاع على المقالات اللاحقة لمزيد من ميزات المنصات المتقدمة مثل القفز على الحائط.

تحديد متى يدخل كائن إلى الشاشة أو يغادرها

يوفر محرّك الألعاب العقدة VisibleOnScreenNotifier2D، حيث إذا أرفقنا هذه العقدة بالكائن، فسنتمكّن من استخدام إشارات screen_entered و screen_exited الخاصة بها.

تطبيق عملي 1

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

توضح الشيفرة البرمجية التالية حركة المقذوف:

extends Area2D

var velocity = Vector2(500, 0)

func _process(delta):
    position += velocity * delta

يمكن حذف المقذوف تلقائيًا عند تحرّكه خارج الشاشة من خلال إضافة العقدة VisibleOnScreenNotifier2D والاتصال بإشارة screen_exited الخاصة بها.

func _on_VisibleOnScreenNotifier2D_screen_exited():
    queue_free()

تطبيق عملي 2

ليكن لدينا مثلًا عدو ينفّذ بعض الإجراءات مثل التحرك على طول مسار أو تشغيل رسوم متحركة، ولن يظهر على الشاشة سوى عدد قليل من الأعداء في الوقت نفسه في خريطة كبيرة تحتوي على العديد من الأعداء، إذ يمكننا تعطيل إجراءات العدو أثناء وجوده خارج الشاشة باستخدام العقدة VisibleOnScreenNotifier2D كما هو الحال في جزء الشيفرة البرمجية التالي:

var active = false

func _process(delta):
    if active:
        play_animation()
        move()

func _on_VisibleOnScreenNotifier2D_screen_entered():
    active = true

func _on_VisibleOnScreenNotifier2D_screen_exited():
    active = false

الخاتمة

استعرضنا في هذا المقال كيفية استخدام العقدة VisibleOnScreenNotifier2D لتحديد متى يدخل كائن إلى الشاشة أو يغادرها، مما يساعد في تحسين أداء اللعبة من خلال إدارة الكائنات غير المرئية بكفاءة؛ كما تناولنا أساسيات إنشاء شخصية وتحريكها في ألعاب المنصات ثنائية الأبعاد باستخدام العقدة CharacterBody2D، مع التركيز على مفاهيم مثل الجاذبية، القفز، والتسارع للحصول على حركة سلسة واستجابة طبيعية.

يمكن تنزيل شيفرة المشروع البرمجية من Github للاطلاع عليه وفهمه أكثر.

ترجمة -وبتصرّف- للقسمين Entering/Exiting the screen و Platform character من توثيقات Kidscancode.

اقرأ أيضًا


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

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

اقتباس

سنكتشف في هذا المقال متى يدخل أو يخرج كائن من الشاشة، وسنتعرّف على كيفية إنشاء وتحريك شخصية في ألعاب المنصات ثنائية الأبعاد.

إنشاء شخصية وتحريكها في ألعاب المنصات ثنائية الأبعاد

سننشئ الأن شخصيةً في ألعاب المنصات ثنائية الأبعاد. يُفاجَأ المطورون المبتدئون في أغلب الأحيان بمدى تعقيد برمجة شخصيات ألعاب المنصات، لذا يوفر محرّك ألعاب جودو Godot بعض الأدوات المُضمَّنة للمساعدة، ولكن يمكن القول بأن هناك عددًا كبيرًا من الحلول التي تضاهي عدد الألعاب الموجودة. لن نتعمق في شرح الميزات مثل ميزات القفزات المزدوجة أو الانحناء أو القفز على الحائط أو الرسوم المتحركة، بل سنناقش أساسيات الحركة في ألعاب المنصات.

ملاحظة: يمكن استخدام العقدة RigidBody2D لإنشاء شخصية لألعاب المنصات، ولكننا سنركز على استخدام العقدة CharacterBody2D، إذ تُعَد الأجسام الحركية Kinematic مناسبةً لألعاب المنصات، حيث لن تكون مهتمًا كثيرًا بالفيزياء الواقعية بقدر الاهتمام بالشعور المتجاوب في اللعبة.

سنبدأ بعقدة CharacterBody2D، ونضيف إليها عقدتي Sprite2D و CollisionShape2D، ثم نرفق السكربت التالي بالعقدة الجذر للشخصية:

extends CharacterBody2D @export var speed = 1200 @export var jump_speed = -1800 @export var gravity = 4000 func _physics_process(delta): # إضافة الجاذبية في كل إطار velocity.y += gravity * delta # ‫يؤثر الدخل على المحور x فقط velocity.x = Input.get_axis("walk_left", "walk_right") * speed move_and_slide() # السماح بالقفز عند وجود الشخصية على الأرض فقط if Input.is_action_just_pressed("jump") and is_on_floor(): velocity.y = jump_speed

يمكننا ملاحظة أننا نستخدم إجراءات الإدخال التي عرّفناها في خريطة الإدخال InputMap وهي: "walk_right" و "walk_left" و "jump"، لذا يمكن الاطلاع على إجراءات الإدخال InputActions لمزيد من التفاصيل.

في تجربتي في تطوير الألعاب، وجدت أن إنشاء وتحريك الشخصيات في ألعاب الـ2D المنصات ليس مجرد رسم وتحريك، بل هو عملية متكاملة تجمع بين الإبداع والتقنية. الأمر يتطلب فهم دقيق لكيفية تحرك الشخصية بسلاسة داخل بيئة اللعبة، مع الانتباه إلى تفاصيل مثل الإطارات، والتوقيت، وتناسق الحركة مع القصة أو الأجواء العامة. لاحظت أيضًا أن متابعة أخبار ودعم الصناعات الإبداعية يمكن أن يلهمك كثيرًا، مثلما قرأت مؤخرًا عن 1xbet Maroc التي أصبحت راعيًا رسميًا لجمعية كرة الدودجبول المغربية، وهو مثال على كيفية دعم العلامات التجارية للمجالات الرياضية والفنية. في العمل على الشخصيات، من المهم اختبار التحريك باستمرار، وتلقي الملاحظات من اللاعبين أو الفريق، لأن ذلك يساهم في تحسين التجربة البصرية وجعل الشخصية أكثر حيوية وإقناعًا.

تعتمد القيم المُستخدَمة للسرعة speed والجاذبية gravity وسرعة القفز jump_speed اعتمادًا كبيرًا على حجم الشخصية الرسومية Sprite الخاصة باللاعب، وتكون خامة Texture اللاعب 108x208 بكسل في هذا المثال، وإذا كانت الصورة أصغر حجمًا، فستستخدم قيمًا أصغر.

نريد أيضًا قيمًا عالية للشعور بالسرعة والاستجابة، إذ تؤدي الجاذبية المنخفضة إلى لعبة نشعر فيها بعدم التوازن؛ بينما تمثل القيمة العالية العودة إلى الأرض بسرعة والجاهزية للقفز مرةً أخرى.

شكرا لك!



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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.


×
×
  • أضف...