تطوير ألعاب تناسب جميع الشاشات

عند تطوير لعبة لـ Android، من المهم توقع مجموعة متنوعة من تجارب اللاعبين المحتملة والاستمرار في التكيّف مع احتياجات التفاعل مع اللاعبين في الوقت الفعلي. فمن خلال دعم تجارب اللاعبين المختلفة، فإنك تزيد من مرونة أسلوب اللعب، مما يساعدك في توسيع نطاق وصول لعبتك.

تشمل الاختلافات المحددة في تجربة اللاعب ما يلي:

  • أشكال الأجهزة: على الرغم من أنّ الهواتف توفّر تجربة استخدام جهاز Android التقليدي، إلا أنّه من الممكن التفاعل مع الألعاب من خلال عوامل تصميم أخرى. يمكن لأجهزة ChromeOS تشغيل حاوية Android لعرض لعبتك. الأجهزة اللوحية التي تعمل بنظام Android تدعم عدة مستويات مختلفة من الدقة. توفّر أجهزة Android TV تجارب غنية بالتفاصيل وأكثر وضوحًا. يمكن للّاعبين محاكاة بيئة متعددة النوافذ باستخدام أداة إضافة العرض. وعند استخدام الهواتف القابلة للطي، يمكن للّاعبين تغيير حجم الشاشة أثناء جلسة اللعب.
  • طرق التفاعل: يمكن للمشغلات تقديم مدخلات من خلال لمس شاشة الجهاز، ولكن يمكنها أيضًا استخدام الماوس أو لوحة اللمس أو لوحة المفاتيح أو وحدة التحكم بدلاً من ذلك. فضلاً عن ذلك، يتيح توفر أدوات إضافة العرض والأجهزة القابلة للطي للّاعبين تجربة لعبتك على شاشة أكبر، ما يجعل جلسات اللعب الأطول والواجهات الأكثر تعقيدًا أكثر إمكانية.
  • دعم الأجهزة: لا تشتمل بعض الأجهزة التي تعمل بنظام التشغيل Android على أجهزة نموذجية أكثر في الأجهزة المحمولة باليد، مثل الكاميرا الخلفية، ونظام تحديد المواقع العالمي (GPS)، واتصال الشبكة. يجب أن تتكيّف لعبتك مع الأجهزة المتاحة أن تتعامل بشكل ملائم مع المواقف التي لا تتوفّر فيها ميزات معيّنة.

يعرض هذا الدليل أفضل الممارسات المتعلقة بتطوير لعبتك لتناسب أنواعًا مختلفة من الشاشات وتفاعلات المستخدمين. كما يقدم هذا الدليل اقتراحات حول تصميم لعبتك ووضع استراتيجية اختبار فعالة.

أفضل الممارسات المتعلّقة بتصميم الألعاب

عند التخطيط لتصميم لعبتك وبنيتها، اتّبِع أفضل الممارسات الموضّحة في الأقسام التالية.

الاستجابة لتغييرات الإعدادات يدويًا

عندما يكتشف نظام Android تغييرًا في الضبط، مثل تغيير في حجم الشاشة أو اتجاه الشاشة أو طريقة الإدخال، يعيد النظام تشغيل النشاط الحالي تلقائيًا. للحفاظ على الحالة داخل تطبيق أو لعبة، يستدعي النشاط تلقائيًا onSaveInstanceState() قبل إعادة تشغيله و onRestoreInstanceState() بعد إعادة تشغيله. ومع ذلك، تتطلب هذه العملية إعادة تحميل النشاط لجميع الخدمات والموارد المرتبطة. لمزيد من المعلومات عن هذا السلوك التلقائي، اطّلِع على دليل التعامل مع تغييرات الإعدادات.

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

للتعرّف على كيفية إضافة منطق تغيير الإعدادات هذا إلى لعبتك، راجِع القسم الخاص بكيفية إنشاء معالِجات تغيير الإعدادات المخصّصة.

إنشاء بنية مرنة

لإتاحة لعبتك على أكبر عدد ممكن من الأجهزة، يُرجى اتّباع أفضل الممارسات التالية:

  • نشر حِزم تطبيقات Android بدلاً من حِزم APK الفردية تتيح لك حِزم تطبيقات Android تجميع عناصر ذات درجات دقة مختلفة ونماذج معمارية مختلفة، مثل x86 وARM، في أداة واحدة. والأفضل من ذلك أنّ تنسيق "مجموعات حزمات تطبيق Android" يتيح حدودًا أعلى لحجم لعبتك، إذ يمكن أن يصل حجم كل حزمة APK أساسية إلى 150 ميغابايت، بينما يمكن أن يصل حجم الحزمة نفسها إلى غيغابايت.
  • إتاحة بُنى x86 تساعد هذه الخطوة في تحسين أداء لعبتك على الأجهزة التي لا تتوافق مع ARM، إذ يمكن لهذه الأجهزة الآن تنفيذ التعليمات بدون الحاجة إلى ترجمتها أولاً.

إضافة دعم Vulkan

من خلال إتاحة Vulkan، يمكن للعبتك تحقيق أداء أفضل للرسومات. تدعم معظم الأجهزة واجهة برمجة تطبيقات الرسومات هذه.

إنشاء معالِجات تغيير الضبط المخصّصة

لتوضيح أنواع تغييرات الإعدادات التي تعالجها لعبتك نفسها، أضِف السمة android:configChanges إلى كل عنصر <activity> في ملف البيان الذي يمثّل شاشة أو واجهة معقّدة.

يوضح مقتطف الرمز التالي كيفية الإشارة إلى أنّ لعبتك تراعي التغييرات في حجم الشاشة واتجاه الشاشة وطريقة الإدخال:

<activity ...
    android:configChanges="screenSize|orientation|keyboard|keyboardHidden">
</activity>

عند حدوث تغييرات الإعدادات المعلَن عنها، يستدعي النظام الآن طريقة مختلفة، وهي onConfigurationChanged(). ومن خلال هذه الطريقة، يمكنك إضافة منطق لتعديل واجهة المستخدم في لعبتك:

التعامل مع التغييرات في إعدادات الشاشة

تتعامل لعبتك مع تغيير حجم الشاشة واتجاه الشاشة يدويًا عند تضمين القيمتين screenSize وorientation على التوالي في سمة android:configChanges. يمكنك استخدام هذه القيم الجديدة لتحديث محتوى المشهد ومناطق إدخال اللاعب. للحصول على إرشادات حول كيفية تصميم تصميم اللعبة بهدف تسهيل عملية التحديث، راجع الدليل حول التوافق مع أحجام الشاشات المختلفة.

أثناء تنفيذ onConfigurationChanged() في لعبتك، استخدِم الكائن الذي تم تمريره Configuration وكائن Display مدير النوافذ لتحديد القيم المعدّلة لحجم الشاشة واتجاه الشاشة، على التوالي.

يعرض مقتطف الرمز التالي طريقة الحصول على حجم شاشة اللعبة واتجاهها المُعدَّلَين:

Kotlin

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    val density: Float = resources.displayMetrics.density
    val newScreenWidthPixels = (newConfig.screenWidthDp * density).toInt()
    val newScreenHeightPixels = (newConfig.screenHeightDp * density).toInt()

    // Get general orientation; either Configuration.ORIENTATION_PORTRAIT or
    // Configuration.ORIENTATION_LANDSCAPE.
    val newScreenOrientation: Int = newConfig.orientation

    // Get general rotation; one of: ROTATION_0, ROTATION_90, ROTATION_180,
    // or ROTATION_270.
    val newScreenRotation: Int = windowManager.defaultDisplay.rotation
}

Java

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    float density = getResources().getDisplayMetrics().density;
    int newScreenWidthPixels = (int) (newConfig.screenWidthDp * density);
    int newScreenHeightPixels = (int) (newConfig.screenHeightDp * density);

    // Get general orientation; either Configuration.ORIENTATION_PORTRAIT or
    // Configuration.ORIENTATION_LANDSCAPE.
    int newScreenOrientation = newConfig.orientation;

    // Get general rotation; one of: ROTATION_0, ROTATION_90, ROTATION_180,
    // or ROTATION_270.
    int newScreenRotation = getWindowManager().getDefaultDisplay()
            .getRotation();
}

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

جودة الشاشة الخاصة باللعبة

تشرح الأقسام التالية كيفية ضبط تفاعل لعبتك مع تغيرات حجم الشاشة أو اتجاه الشاشة، وذلك بناءً على صفات اللعبة:

وضع ملء الشاشة

على بعض الأنظمة الأساسية، مثل ChromeOS، يمكن عرض تطبيقات وألعاب Android في النوافذ وتغيير حجمها تلقائيًا. إذا كان يجب تشغيل لعبتك دائمًا في وضع ملء الشاشة، يمكنك ضبط السمة android:resizeableActivity على false في أحد عناصر <activity>، كما هو موضّح في مقتطف الرمز التالي:

<activity ...
    android:resizeableActivity="false">
</activity>

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

اتجاه الشاشة

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

<activity ...
    android:screenOrientation="landscape">
</activity>

مستويات جودة الشاشة الخاصة بالجهاز

توضح الأقسام التالية كيفية التعامل مع تغييرات التهيئة المستندة إلى الشاشة بحيث تتوفر سمات محددة تتميز بها بعض الأجهزة.

نسبة العرض إلى الارتفاع

تعتمد بعض الأجهزة نِسب عرض إلى ارتفاع مختلفة. على سبيل المثال، تم تصميم الأجهزة القابلة للطي لدعم نسبة العرض إلى الارتفاع 21:9 عندما تكون في الحالة المطوية. للتعامل مع هذا التنوع المحتمل في نسبة العرض إلى الارتفاع، قم بإجراء واحد على الأقل من الخطوات التالية:

  • استهداف الإصدار 8.0 من نظام التشغيل Android (المستوى 26 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث.
  • تغيير حجم مشهد اللعبة والواجهة في اللعبة: ضبط android:resizeableActivity على true على الأجهزة التي تعمل بنظام التشغيل Android 7.0 (المستوى 24 لواجهة برمجة التطبيقات) والإصدارات الأحدث
  • حدِّد الحدّ الأقصى لنسبة العرض إلى الارتفاع المتوافقة. في سمة <meta-data> المرتبطة بلعبتك، يمكنك ضبط android.max_aspect على 2.4، كما هو موضّح في مقتطف الرمز التالي. ومع ذلك، تذكَّر أنّ نسب العرض إلى الارتفاع أكبر من النسبة التي حددتها، قد تؤدي إلى ظهور اللعبة في إطار مُعدّ للعرض على شاشة عريضة أفقيًا ضمن إحدى شاشات العرض.

    <application>
    <meta-data android:name="android.max_aspect"
               android:value="2.4" />
    </application>
    

أنشطة متعددة مرئية في الوقت نفسه

يتوافق العديد من الأجهزة الحديثة مع مجموعة متنوعة من تنسيقات الشاشة، بما في ذلك وضع "تقسيم الشاشة" و"نافذة ضمن النافذة" ومساحات العرض الكبيرة. عند استخدام أحد هذه التخطيطات، يمكن للنظام جعل أنشطة متعددة مرئية في نفس الوقت.

على الأجهزة التي تعمل بنظام التشغيل Android 9 (المستوى 28 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، يمكن استئناف جميع الأنشطة الظاهرة جدًا في الوقت نفسه. ولكي ينجح هذا السلوك، يجب تفعيل كلّ من لعبتك والمصنّع الأصلي للجهاز. يمكنك إضافة الدعم داخل لعبتك من خلال ضبط android.allow_multiple_resumed_activities على true في بيان اللعبة، كما هو موضّح في المقتطف التالي:

<application>
    <meta-data android:name="android.allow_multiple_resumed_activities"
               android:value="true" />
</application>

ويمكنك بعد ذلك اختبار لعبتك على أجهزة مختلفة لمعرفة أي منها يوفّر دعم المصنّع الأصلي للجهاز اللازم لتشغيل ميزة الاستئناف المتعدّد بشكل صحيح.

للحصول على مزيد من المعلومات حول إعداد لعبتك لتظهر كجزء من عرض نوافذ متعددة، راجع الدليل حول كيفية إضافة إتاحة النوافذ المتعددة.

التعامل مع أنواع مختلفة من نماذج التفاعل

ستعالج لعبتك بيانات لوحة المفاتيح ومدى توفّرها يدويًا عند تضمين القيمتَين keyboard وkeyboardHidden على التوالي في سمة android:configChanges. يمكنك استخدام هذه القيم الجديدة لتحديث أسلوب الإدخال الأساسي للعبتك.

عند تهيئة لعبتك بحيث تدعم أنواعًا متعددة من إدخالات المستخدمين، ضع ما يلي في الاعتبار:

  • رصد طرق الإدخال بدلاً من الأجهزة الفردية وتسهِّل طريقة التفكير هذه تحسين تجربة اللاعبين بدون التركيز كثيرًا على الجهاز المحدّد الذي قد يمتلكه اللاعب.
  • أدرِج السمة keyboardHidden في قائمة تغييرات الإعدادات التي تمت معالجتها يدويًا. وبهذه الطريقة، يمكن للعبتك تتبُّع الأوقات التي تكون فيها لوحة المفاتيح متصلة بالجهاز ولكن لا يمكن استخدامها.
  • حدِّد طرق الإدخال المتاحة حاليًا. لإجراء ذلك، يمكنك الاتصال بالرقم getInputDeviceIds() عند بدء تشغيل اللعبة وبعد كل تغيير في الإعدادات.

    يمكنك غالبًا تحديد الطريقة التي يخطط بها اللاعب للتفاعل مع لعبتك بناءً على جهاز الإدخال المفضل لديه:

    • يستخدم اللاعبون عادةً لوحة المفاتيح أو وحدة تحكم في الألعاب لإجراء تسلسلات أزرار سريعة.
    • عادةً ما يستخدم اللاعبون شاشة تعمل باللمس أو لوحة لمس لتنفيذ إيماءات أكثر تعقيدًا.
    • يستخدم اللاعبون عادةً الماوس للإدخال بدقة أعلى.

تقدم الأقسام التالية أفضل الممارسات لأنواع محددة من أجهزة الإدخال.

لوحة المفاتيح

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

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

يجب أن يتمكّن اللاعبون أيضًا من فتح قوائم اللعبة والتنقّل بينها باستخدام لوحة المفاتيح. المفتاح Esc هو عملية ربط شائعة لإيقاف مشهد مؤقتًا وعرض قائمة اللعبة.

للحصول على مزيد من المعلومات حول إتاحة إدخال لوحة المفاتيح في لعبتك، يمكنك الاطّلاع على دليل كيفية إتاحة التنقّل باستخدام لوحة المفاتيح ودليل كيفية التعامل مع إجراءات لوحة المفاتيح.

وحدة تحكّم في الألعاب

للحصول على مزيد من المعلومات حول التعامل مع إدخالات وحدة التحكم في اللعبة، راجِع الدليل حول كيفية دعم وحدات التحكم في الألعاب.

الماوس أو لوحة اللمس

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

على الأجهزة التي تعمل بنظام التشغيل Android 8.0 (المستوى 26 لواجهة برمجة التطبيقات) والإصدارات الأحدث، يمكنك استخدام واجهة برمجة التطبيقات Mouse Capture API للمساعدة في عملية التقاط المؤشر. في الألعاب التي تتفاعل مع الإدخال عالي الدقة، يمكنك الحصول على الإحداثيات الحالية للمؤشر من خلال استدعاء طريقتي getX() وgetY().

للحصول على معلومات إضافية حول إتاحة إدخال الماوس وإدخال بيانات لوحة اللمس في لعبتك، يمكنك مراجعة الدليل حول طريقة تتبُّع حركات اللمس والمؤشر بالإضافة إلى دليل كيفية التعامل مع إيماءات اللمس المتعدد.

اختبار لعبتك

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

تحديث خطة الاختبار

عند التحقّق من صحة وظائف لعبتك، يُرجى تضمين حالات الاختبار التالية:

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

ننصحك أيضًا بتحديث نظام مراقبة جودة لعبتك كي تتمكّن من تحسينه للاستفادة من مجموعة متنوعة من تجارب اللاعبين.

لمعرفة أفضل الممارسات ذات الصلة باختبار لعبتك، راجِع دليل أساسيات الاختبار.

استخدام أدوات الاختبار وتصحيح الأخطاء

يمكنك إجراء اختبارات باستخدام مجموعة متنوعة من الأدوات المتوافقة مع النظام الأساسي: