פיתוח משחקים לכל המסכים

כשמפתחים משחק ל-Android, חשוב לצפות את מגוון חוויות המשחק האפשריות ולהתאים את המשחק לצרכים של השחקנים בזמן אמת. תמיכה בחוויות שונות לשחקנים מגדילה את הגמישות של המשחק, ועוזרת לכם להרחיב את קהל השחקנים.

ההבדלים הספציפיים בחוויית הצפייה כוללים את הדברים הבאים:

  • גורמי צורה של מכשירים: טלפונים מספקים את חוויית השימוש המסורתית במכשירי Android, אבל אפשר לקיים אינטראקציה עם משחקים גם בגורמי צורה אחרים. במכשירי ChromeOS אפשר להריץ קונטיינר של Android שמציג את המשחק. טאבלטים עם Android תומכים בכמה רמות שונות של נאמנות. מכשירי Android TV תומכים בחוויות עשירות בפרטים וסוחפות יותר. השחקנים יכולים לדמות סביבה מרובת חלונות באמצעות כלי להרחבת התצוגה. בנוסף, כשמשתמשים במכשירים מתקפלים, השחקנים יכולים לשנות את גודל המסך במהלך סשן משחק.
  • שיטות אינטראקציה: השחקנים יכולים להזין קלט באמצעות מגע במסך המכשיר, אבל הם יכולים גם להשתמש בעכבר, בלוח מגע, במקלדת או בבקר. בנוסף, הזמינות של כלים להרחבת התצוגה ומכשירים מתקפלים מאפשרת לשחקנים ליהנות מהמשחק שלכם במסך גדול יותר, מה שהופך הפעלות ארוכות יותר של המשחק וממשקים מורכבים יותר לאפשריים.
  • תמיכה בחומרה: בחלק מהמכשירים שמבוססים על Android אין חומרה שמאפיינת מכשיר שניתן להחזיק ביד, כמו מצלמה אחורית, GPS וקישוריות לרשת. המשחק צריך להתאים את עצמו לחומרה הזמינה ולטפל בצורה חלקה במצבים שבהם תכונות מסוימות לא זמינות.

במדריך הזה מפורטות שיטות מומלצות שקשורות לפיתוח המשחק עבור סוגים שונים של מסכים ואינטראקציות עם משתמשים. במדריך הזה יש גם הצעות לעיצוב המשחק ולפיתוח אסטרטגיית בדיקות יעילה.

שיטות מומלצות לעיצוב משחקים

כשמתכננים את העיצוב והארכיטקטורה של המשחק, כדאי לפעול לפי השיטות המומלצות שמתוארות בקטעים הבאים.

מענה ידני לשינויים בהגדרות

כשמערכת Android מזהה שינוי בהגדרות, כמו שינוי בגודל המסך, בכיוון המסך או בשיטת הקלט, המערכת מפעילה מחדש את הפעילות הנוכחית כברירת מחדל. כדי לשמור את המצב באפליקציה או במשחק, הפעילות קוראת כברירת מחדל ל-onSaveInstanceState() לפני שהיא מופעלת מחדש ול-onRestoreInstanceState() אחרי שהיא מופעלת מחדש. עם זאת, כדי שהתהליך הזה יפעל, צריך לטעון מחדש את כל השירותים והמשאבים שמשויכים לפעילות. כדי לקבל מידע נוסף על התנהגות ברירת המחדל הזו, אפשר לעיין במדריך לטיפול בשינויים בהגדרות.

במהלך סשן משחק טיפוסי מתבצעים כמה שינויים בהגדרות. אם המשחק מאפשר למערכת לטפל בכל שינוי בהגדרה, הסצנה של המשחק נהרסת ומופעלת מחדש שוב ושוב, מה שמפחית את הביצועים של המשחק. לכן, אנחנו ממליצים מאוד לטפל בשינויים בהגדרות בעצמכם במשחק.

כדי ללמוד איך להוסיף את הלוגיקה של שינוי ההגדרה למשחק, אפשר לעיין בקטע בנושא יצירת רכיבי handler מותאמים אישית לשינוי הגדרות.

יצירת ארכיטקטורה גמישה

כדי להוסיף תמיכה במשחק שלכם בכמה שיותר מכשירים, מומלץ לפעול לפי השיטות המומלצות הבאות:

  • פריסת קובצי Android App Bundle במקום חבילות APK נפרדות. קובצי Android App Bundle מאפשרים לארוז ארטיפקטים ברזולוציות שונות ובמודלים שונים של ארכיטקטורה, כמו x86 ו-ARM, בארטיפקט יחיד. בנוסף, קובצי Android App Bundle תומכים במגבלות גודל גבוהות יותר למשחק שלכם. כל קובץ APK בסיסי יכול להיות בגודל של עד 150MB, וה-App Bundle עצמו יכול להיות בגודל של כמה גיגה-בייט.
  • הוספנו תמיכה בארכיטקטורות x86. השלב הזה משפר את הביצועים של המשחק במכשירים שלא תומכים ב-ARM, כי עכשיו המכשירים האלה יכולים להריץ הוראות בלי לתרגם אותן קודם.

הוספת תמיכה ב-Vulkan

תמיכה ב-Vulkan מאפשרת למשחק להשיג ביצועים גרפיים טובים יותר. רוב המכשירים תומכים בממשק ה-API הזה לגרפיקה.

יצירת handlers מותאמים אישית לשינויים בהגדרות

כדי להצהיר על סוגי שינויי ההגדרה שהמשחק מטפל בהם בעצמו, מוסיפים את המאפיין android:configChanges לכל רכיב <activity> במניפסט שמייצג מסך או ממשק מורכב.

בקטע הקוד הבא מוצג איך להצהיר שהמשחק מטפל בשינויים בגודל המסך, בכיוון המסך ובשיטת הקלט:

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

כשמתרחשים שינויים בהגדרות המוצהרות, המערכת מפעילה עכשיו שיטה אחרת, onConfigurationChanged(). בתוך ה-method הזה, מוסיפים לוגיקה לעדכון ממשק המשתמש של המשחק:

טיפול בשינויים בהגדרת תצורה של מסך

המשחק מטפל באופן ידני בשינויים של גודל המסך וכיוון המסך בכל פעם שכוללים את הערכים 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 כשהם במצב מקופל. כדי להתמודד עם האפשרות של יחסי גובה-רוחב שונים, אפשר לבצע לפחות אחת מהפעולות הבאות:

  • טירגוט ל-Android 8.0 (רמת API‏ 26) ומעלה.
  • הגדרת אפשרות לשינוי הגודל של הסצנה והממשק של המשחק. מגדירים את Set android:resizeableActivity לערך true במכשירים עם Android בגרסה 7.0 ומעלה (רמת API‏ 24).
  • מציינים יחס גובה-רוחב מקסימלי נתמך. במאפיין <meta-data> שמשויך למשחק, מגדירים את android.max_aspect לערך 2.4, כמו שמוצג בקטע הקוד הבא. עם זאת, חשוב לזכור שאם יחסי הגובה-רוחב גדולים יותר מהיחס שציינתם, המשחק יוצג בפורמט Letterbox במסך.

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

כמה פעילויות מוצגות בו-זמנית

מכשירים מודרניים רבים תומכים במגוון פריסות מסך, כולל מסך מפוצל, תמונה בתוך תמונה ואזורי תצוגה גדולים. כשמשתמשים באחד מהפריסות האלה, המערכת יכולה להציג כמה פעילויות בו-זמנית.

במכשירים שמותקנת בהם גרסת Android 9 (רמת API‏ 28) ומעלה, אפשר להפעיל מחדש את כל הפעילויות העליונות שגלויות בו-זמנית. עם זאת, כדי שההתנהגות הזו תפעל, גם המשחק וגם יצרן המכשיר צריכים להצטרף לפונקציונליות. כדי להוסיף תמיכה במשחק, צריך להגדיר את android.allow_multiple_resumed_activities לערך true במניפסט של המשחק, כמו שמוצג בקטע הקוד הבא:

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

אחר כך אפשר לבדוק את המשחק במכשירים שונים כדי לראות באילו מהם יש תמיכה של יצרן הציוד המקורי (OEM) שנדרשת כדי שהפעילות המקבילה תפעל בצורה תקינה.

למידע נוסף על הגדרת המשחק כך שיוצג כחלק מתצוגה מרובת חלונות, אפשר לעיין במדריך להוספת תמיכה בריבוי חלונות.

טיפול בסוגים שונים של מודלים לאינטראקציה

המשחק מטפל בנוכחות המקלדת ובזמינות המקלדת באופן ידני בכל פעם שכוללים את הערכים keyboard ו-keyboardHidden, בהתאמה, במאפיין android:configChanges. אתם יכולים להשתמש בערכים החדשים האלה כדי לעדכן את שיטת הקלט העיקרית של המשחק.

כשמגדירים את המשחק כך שיתמוך בכמה סוגים של קלט של משתמשים, חשוב לזכור את הנקודות הבאות:

  • מזהה שיטות קלט ולא מכשירים ספציפיים. הגישה הזו מאפשרת לשפר את חוויית השחקן בלי להתמקד יותר מדי במכשיר הספציפי שבו השחקן משתמש.
  • כוללים את מאפיין keyboardHidden ברשימת שינויי ההגדרות שמטופלים באופן ידני. כך המשחק יכול לעקוב אחרי מקרים שבהם המקלדת מחוברת פיזית למכשיר אבל אי אפשר להשתמש בה.
  • קביעת שיטות הקלט שזמינות כרגע. כדי לעשות זאת, צריך להתקשר אל getInputDeviceIds() בזמן הפעלת המשחק ואחרי כל שינוי בהגדרות.

    לרוב אפשר להבין איך השחקן מתכנן לקיים אינטראקציה עם המשחק לפי מכשיר הקלט המועדף שלו:

    • בדרך כלל, השחקנים משתמשים במקלדת או בשלט משחק כדי לבצע רצפים מהירים של לחיצות על לחצנים.
    • בדרך כלל השחקנים משתמשים במסך מגע או במשטח מגע כדי לבצע תנועות מורכבות יותר.
    • בדרך כלל, שחקנים משתמשים בעכבר כדי להזין קלט ברמת דיוק גבוהה יותר.

בקטעים הבאים מפורטות שיטות מומלצות לסוגים ספציפיים של מכשירי קלט.

מקלדת

כשיוצרים פריסת מקלדת למשחק, צריך לחשוב על האופן שבו השחקן מתנהל בסצנה מסוימת ועל האופן שבו הוא מבצע אינטראקציה עם הגדרות המשחק.

בדרך כלל הכי טוב להשתמש במקשים WASD או במקשי החיצים כדי לשלוט בתנועת הדמות. מומלץ גם להקצות מקש מסוים לכל פעולה או מיומנות חשובה שהדמות שניתן לשלוט בה יכולה לבצע במשחק. כדי למקסם את חוויית המשחק, כדאי להוסיף תמיכה בהגדרות מקשים מותאמות אישית במשחק.

השחקנים צריכים גם להיות מסוגלים לפתוח את התפריטים של המשחק ולנווט בהם באמצעות המקלדת. המקש Esc הוא מיפוי נפוץ להשהיית סצנה ולהצגת התפריט של המשחק.

מידע נוסף על תמיכה בהזנת מקלדת במשחק זמין במדריך לתמיכה בניווט באמצעות מקלדת ובמדריך לטיפול בפעולות באמצעות מקלדת.

בקר משחקים

מידע נוסף על טיפול בקלט של שלט במשחק זמין במדריך לתמיכה בשלטים למשחקים.

עכבר או לוח מגע

אם המשחק שלכם תומך בקלט מהשחקן באמצעות עכבר או משטח מגע, חשוב לזכור שהשחקנים מבצעים אינטראקציה עם המכשיר בדרכים אחרות מלבד משחק. חשוב לדעת: כשמבקשים ללכוד את מצביע העכבר, כל קלט העכבר מופנה אל המשחק. לכן, אחרי שהמשחק מקבל את המידע שהוא צריך, צריך לבטל את לכידת מצביע העכבר כדי שהשחקנים יוכלו לשלוט במכשיר באמצעות העכבר בצורה רגילה.

במכשירים עם Android 8.0 (רמת API‏ 26) ומעלה, אפשר להשתמש ב-Mouse Capture API כדי לסייע בתהליך של לכידת מצביע. במשחקים שמגיבים לקלט ברמת דיוק גבוהה, אפשר לקבל את הקואורדינטות הנוכחיות של מצביע העכבר על ידי הפעלת השיטות getX() ו-getY().

מידע נוסף על הוספת תמיכה בקלט של עכבר ושל משטח מגע במשחק זמין במדריך למעקב אחרי תנועות של מגע ושל מצביע ובמדריך לטיפול במחוות מולטי-טאץ'.

בדיקה של המשחק

לפני שמשיקים את המשחק, כדאי לבדוק איך הוא מגיב לשינויים בהגדרות. לשם כך, מבצעים את השלבים שמתוארים בקטעים הבאים.

עדכון תוכנית הבדיקה

כשבודקים את הפונקציונליות של המשחק, חשוב לכלול את תרחישי הבדיקה הבאים:

  • מזעור והגדלה של החלון שבו המשחק פועל. (לא רלוונטי אם המשחק תמיד במצב מסך מלא).
  • שינוי גודל המסך.
  • שינוי כיוון המסך. (לא רלוונטי אם למשחק יש כיוון קבוע).
  • חיבור וניתוק של מכשירי קלט, כמו מקלדות ועכברים.
  • להפעיל פעילות מקבילה אם המשחק תומך בה.

כדאי גם לשקול לעדכן את מערכת בקרת האיכות של המשחק כדי שתוכלו לבצע אופטימיזציה למגוון רחב יותר של חוויות שחקנים.

שיטות מומלצות לבדיקת המשחק מפורטות במדריך בנושא יסודות הבדיקה.

שימוש בכלי בדיקה וניפוי באגים

אפשר לבצע בדיקות באמצעות מגוון כלים שהפלטפורמה תומכת בהם: