مدونة Metlivi

كيفية الفصل بين حالتي الخمول والتفاعل في حلقة لعبة الحيوان الأليف الافتراضي

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

15 أكتوبر 2026قراءة تستغرق 6 دقائقبقلم Metlivi Editorial Team
القسم 1

تحديد المقصود بـ "الخمول" و"التفاعل"

تعامل مع هاتين الحالتين كأنماط سلوكية، وليس بالضرورة كمشاهد مختلفة أو حلقات منفصلة. في وضع الخمول (idle)، يُنفّذ الحيوان الأليف روتينه المعتاد: كاختيار حركة محيطية بسيطة، أو التقدم في مؤقت زمني، أو تشغيل رسم متحرك غير أساسي. أما في الوضع التفاعلي (interactive)، فتتولى اللعبة معالجة إجراء مقصود من اللاعب مثل النقر، أو السحب، أو أمر محدد. قد يستمر الحيوان الأليف في الحركة أثناء التفاعل؛ والفرق الجوهري يكمن في أيّ النظامين يمتلك صلاحية اتخاذ القرارات وتغيير حالة أسلوب اللعب.

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

القسم 2

الحفاظ على استقلالية الحلقة الخارجية عن سلوك الحيوان الأليف

ينبغي لدالة الاستدعاء الراجعة لإطارات المحرك (frame callback) أن تقوم بتنسيق المهام بدلاً من احتواء جميع قواعد الحيوان الأليف. ويُعد التسلسل التالي نهجًا مفيدًا: جمع المدخلات، وتطبيق الأوامر الصالحة، وتقديم المحاكاة، ثم تصيير (render) الحالة الأخيرة. حافظ على فصل عملية جمع المدخلات عن المحاكاة حتى لا تُعامل النقرة عن طريق الخطأ كتكة مؤقت، وحافظ على خلو عملية التصيير من أي تغييرات في أسلوب اللعب. يصف كتاب "Game Programming Patterns" هذا الفصل بأنه معالجة للمدخلات، وتحديث للعبة، ثم تصيير ضمن حلقة متكررة؛ وتكون التحديثات ذات الخطوات الثابتة مفيدة عندما تتطلب المحاكاة فاصلاً زمنيًا مستقرًا. Game Loop, Game Programming Patterns

بالنسبة لألعاب الويب، تقوم دالة requestAnimationFrame بجدولة العمل قبل إعادة الرسم وتوفر طابعًا زمنيًا يمكنك استخدامه لقياس الوقت المنقضي. وعادةً ما توقف المتصفحات دوال الاستدعاء الراجعة هذه مؤقتًا في علامات التبويب غير النشطة، لذا لا تفترض أنها ستستمر كساعة حائط موثوقة أثناء تشغيل اللعبة في الخلفية. Window.requestAnimationFrame(), MDN

القسم 3

توجيه مدخلات اللاعب عبر الأوامر

قم بتحويل المدخلات الأولية إلى أمر مبسط مثل start_play، أو stop_play، أو pet_tap. يتحقق معالج الأوامر مما إذا كان الإجراء صالحًا للوضع الحالي، ويحدّث النموذج المشترك مرة واحدة، ويُطلق أي إشارة عرض ناتجة عن ذلك. هذا النهج يجنبك وضع منطق الإجراءات في دوال استدعاء الأزرار، ودوال استدعاء الرسوم المتحركة، وروتين الخمول في آن واحد.

على سبيل المثال، إذا نقر اللاعب بينما الحيوان الأليف يلعب بالفعل، حدد النتيجة بدقة وبشكل متعمد: إما تجاهل النقرة، أو اختيار نشاط مختلف، أو إيقاف النشاط الحالي. تجنب السماح لكل من محدد الخمول ومعالج النقر بتعيين نشاط جديد خلال دورة التحديث نفسها. في المحركات التي تعتمد تمرير الأحداث، عالج مدخلات اللعب في المرحلة المناسبة وراعِ استهلاك واجهة المستخدم للمدخلات؛ حيث تشير وثائق Node في Godot إلى أن المدخلات غير المعالجة (unhandled input) تكون عادةً الخيار الأنسب لأسلوب اللعب عندما تكون الأولوية لعناصر التحكم في واجهة المستخدم الرسومية. Node class, Godot documentation

القسم 4

تسيير وقت الخمول باستخدام ساعة واضحة

بالنسبة للسلوك الذي يجب أن يتقدم باستمرار أثناء الجلسة المرئية، قم بتجميع وقت المحاكاة المنقضي وتشغيل قرار الخمول عند الوصول إلى الفاصل الزمني المحدد له. لا تعتمد على عدّ الإطارات، فتردد الإطارات متغير. في محرك Godot، تستقبل دالة _process(delta) الوقت المنقضي منذ إطار الخمول السابق، بينما تتبع دالة _physics_process(delta) تكات الفيزياء؛ وتشير الوثائق أيضًا إلى أن فرق الوقت المجمع (accumulated delta) قد يختلف عن ثواني العالم الحقيقي في ظل ظروف معينة. Node class, Godot documentation

اختر الساعة بما يناسب السلوك. يمكن للحركة التجميلية عادةً استخدام الوقت المنقضي للإطار. أما الحركة المرتبطة بالتصادمات فمكانها الصحيح في تحديث الفيزياء الخاص بالمحرك. ويمكن لمؤقت "اختيار حركة محيطية كل بضع ثوانٍ" للحيوان الأليف استخدام مؤقت المحاكاة، ولكن يجب أن تقرر ما يحدث بعد الإطارات الطويلة أو التوقف المؤقت: هل تحدد سقفًا للوقت المنقضي، أم تنفذ قرارًا واحدًا، أم تستدرك الوقت بخطوات محدودة؟ إن الاستدراك غير المقيد قد يجعل الحيوان الأليف يقفز عبر العديد من الحالات فجأة عند استئناف اللعبة.

القسم 5

جعل انتقالات الحالات صريحة ومحددة

قم بإعداد جدول انتقالات مبسط قبل إضافة المزيد من الحالات. على سبيل المثال، الانتقال من idle → playing يبدأ نشاطًا اختاره اللاعب؛ والانتقال من playing → idle يحدث عند انتهائه أو إلغائه بواسطة اللاعب؛ والانتقال من idle → resting قد يختاره الروتين التلقائي المستقل. حدد تأثيرات الدخول والخروج في مكان واحد، مثل بدء مؤقت زمني أو مسحه واختيار الرسم المتحرك المناسب. لا تعتمد على اكتمال الرسم المتحرك وحده كدليل على تغير نمط أسلوب اللعب، إذ يمكن مقاطعة العرض المرئي أو تخطيه.

يجب أن تقوم دالة الانتقال بالتحقق من صحة الوضع الحالي، وتحديث النموذج، وإرجاع نتيجة يمكن للمصيّر (renderer) عرضها. يفصل هذا بين "ما يفعله الحيوان الأليف" و"كيفية رسم هذا الإجراء". كما يوفر هذا النهج هدفًا واضحًا للاختبارات: إرسال أمر، وفحص الوضع الناتج، ثم التحقق من أن روتين الخمول لم يعد يكتب فوقه ويلغيه.

القسم 6

تحديد آلية التعامل مع الوقت في الخلفية

توجد سياستان شائعتان، واختيار الأنسب بينهما يعتمد على تصميم اللعبة. في حالة الحيوان الأليف المقتصر على مدة الجلسة، يمكن إيقاف المحاكاة أثناء التعليق واستئنافها من حالتها السابقة. أما اللعبة التي تهدف إلى استمرار تقدم المؤقتات أثناء إغلاقها، فيجب عليها تسجيل مرجع زمني وتسوية الوقت المنقضي عند العودة. تعامل مع ذلك كعملية حسابية منفصلة للاستئناف بدلاً من محاولة تشغيل حلقة الإطارات في الخلفية؛ حيث قد يتم إيقاف دوال استدعاء الرسوم المتحركة مؤقتًا في المتصفح لعلامات التبويب غير النشطة. Window.requestAnimationFrame(), MDN

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

القسم 7

التحقق من التحديثات المتعارضة والمدخلات المفقودة

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

إذا كنت تستخدم تحديثًا ثابتًا (fixed update) للمحاكاة، فتذكر أنه قد يعمل صفر أو مرة واحدة أو عدة مرات بين الإطارات المصيّرة. توثق Unity هذا السلوك لدالة FixedUpdate وتوصي به لحسابات الفيزياء؛ بينما تختلف اعتبارات التوقيت بالنسبة للمدخلات والتحديثات البصرية. FixedUpdate(), Unity documentation يقوم نظام الإدخال في Unity (Input System) أيضًا بوضع أحداث الأجهزة في قائمة انتظار ومعالجتها وفقًا لوضع التحديث الذي تم ضبطه، لذا احرص على مواءمة معالجة المدخلات مع الحلقة التي تستهلك تلك الأوامر. Input event queue, Unity Input System

القسم 8

فصل عملي يستحق التطبيق

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

القسم 9

المصادر

قراءات ذات صلة

متابعة استكشاف الموضوع