Prendre en charge le redimensionnement des grands écrans

Passer des téléphones aux différents facteurs de forme pour grand écran implique de prendre en compte la façon dont votre jeu gère la gestion des fenêtres. Sur ChromeOS et Google Play Jeux sur PC, votre jeu peut s'exécuter en mode fenêtre sur une interface de bureau principale. Sur les nouvelles tablettes et appareils pliables Android équipés d'Android 12L (niveau d'API 32) ou version ultérieure et dont la largeur d'écran est supérieure à 600 dp, votre jeu peut s'exécuter côte à côte en mode Écran partagé avec d'autres applications, être redimensionné et même déplacé entre l'écran intérieur et l'écran extérieur sur les appareils pliables, ce qui entraîne une modification de la configuration de la taille de la fenêtre et, sur certains appareils, de l'orientation.

Redimensionnement avec les jeux Unity

Configuration de base pour les grands écrans

Indiquez si votre jeu est capable de gérer le redimensionnement:

<android:resizeableActivity="true" or "false" />

Si le redimensionnement n'est pas possible, assurez-vous que le fichier manifeste du jeu définit explicitement les formats minimal et maximal compatibles:

<!-- Render full screen between 3:2 and 21:9 aspect ratio -->
<!-- Let the platform letterbox otherwise -->
<activity android:minAspectRatio="1.5">
<activity android:maxAspectRatio="2.33">

Google Play Jeux sur PC

Pour Google Play Jeux sur PC, la plate-forme gère le redimensionnement de la fenêtre tout en respectant le format spécifié. La taille de la fenêtre est automatiquement verrouillée sur les dimensions optimales. Vous devez être compatible avec un format d'au moins 16:9 si votre orientation principale est le mode paysage, et au format 9:16 si votre jeu est en mode portrait. Pour une expérience optimale, acceptez explicitement les formats 21:9, 16:10 et 3:2 pour les jeux en mode paysage. Le redimensionnement de la fenêtre n'est pas obligatoire ici, mais il est utile pour la compatibilité avec d'autres facteurs de forme.

Pour en savoir plus et connaître les bonnes pratiques, consultez Configurer les éléments graphiques pour Google Play Jeux sur PC.

Grands écrans ChromeOS et Android

Pour maximiser la zone d'affichage de votre jeu en plein écran sur les appareils ChromeOS et Android à grand écran, activez le mode immersif en plein écran et masquez les barres système en définissant des indicateurs sur decorView, la visibilité de l'UI du système ou via l'API WindowInsetsCompat. Vous devez également gérer correctement les événements de configuration de rotation et de redimensionnement, ou les empêcher de se produire sur les appareils ChromeOS.

Notez que sur les appareils Android à grand écran, votre jeu peut s'exécuter dans des configurations que vous ne gérez peut-être pas encore. Si votre jeu n'est pas compatible avec toutes les configurations de taille et d'orientation de la fenêtre, la plate-forme affiche le jeu au format letterbox en mode de compatibilité et, si nécessaire, invite le joueur avant de passer à une configuration non compatible.

Figure 1 : Boîte de dialogue de compatibilité de la configuration.

Sur certains appareils, lorsqu'un joueur passe à une configuration non compatible, il peut être invité à actualiser le jeu et à recréer l'activité pour l'adapter au mieux à la nouvelle mise en page de la fenêtre, ce qui perturbe l'expérience de jeu. Testez votre jeu dans différentes configurations du mode multifenêtre (taille de fenêtre 2/3, 1/2, 1/3), et vérifiez qu'aucun élément de jeu ou d'interface utilisateur n'est tronqué ni inaccessible. Testez également la réaction de votre jeu à la continuité des appareils pliables lorsqu'ils passent de l'écran intérieur à l'écran extérieur sur les appareils pliables. Si vous rencontrez des problèmes, gérez explicitement ces événements de configuration et ajoutez la prise en charge avancée du redimensionnement des grands écrans.

Redimensionnement avancé des grands écrans

Figure 2 : Différentes interfaces utilisateur sur ordinateur et appareil pliable en position à plat

Pour quitter le mode de compatibilité et éviter la recréation d'activités, procédez comme suit:

  1. Déclarez votre activité principale comme redimensionnable:

    <android:resizeableActivity="true" />
    
  2. Déclarez la prise en charge explicite des attributs "orientation", "screenSize", "smallestScreenSize", "screenLayout" et "densité" dans l'attribut android:configChanges de l'élément <activity> de votre fichier manifeste de jeu pour recevoir tous les événements de configuration d'écran:

    <android:configChanges="screenSize | smallestScreenSize | screenLayout | orientation | keyboard |
                            keyboardHidden | density" />
    
  3. Ignorez onConfigurationChanged() et gérez l'événement de configuration, y compris l'orientation, la taille, la largeur et la hauteur de la fenêtre:

    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()
    
       // Configuration.ORIENTATION_PORTRAIT or ORIENTATION_LANDSCAPE
       val newScreenOrientation: Int = newConfig.orientation
    
       // 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);
    
       // Configuration.ORIENTATION_PORTRAIT or ORIENTATION_LANDSCAPE
       int newScreenOrientation = newConfig.orientation;
    
       // ROTATION_0, ROTATION_90, ROTATION_180, or ROTATION_270
       int newScreenRotation = getWindowManager().getDefaultDisplay()
               .getRotation();
    }
    

Vous pouvez également interroger la WindowManager pour vérifier la rotation actuelle de l'appareil. À l'aide de ces métadonnées, vérifiez les nouvelles dimensions de la fenêtre et affichez la fenêtre en plein écran. Cela peut ne pas fonctionner dans tous les cas en raison de différences de format. Par conséquent, ancrez l'UI de votre jeu à la nouvelle taille de la fenêtre et au format letterbox pour le contenu principal de votre jeu. Si des limites techniques ou de conception empêchent l'une ou l'autre approche, créez votre propre format letterbox dans le moteur pour préserver le format et adapter la mise à l'échelle aux meilleures dimensions possibles tout en déclarant resizeableActivity = false et en évitant le mode de configuration.

Quelle que soit l'approche que vous adoptez, testez votre jeu dans différentes configurations (pliez et dépliez différentes rotations, mode Écran partagé) et assurez-vous qu'il n'y a pas d'éléments d'interface utilisateur tronqués ni de chevauchement, de problèmes d'accessibilité de la cible tactile ou de problèmes de format entraînant l'étirement, l'écrasement ou toute autre distorsion du jeu.

De plus, les écrans plus grands signifient généralement des pixels plus grands, car vous avez le même nombre de pixels pour une zone beaucoup plus grande. Cela peut entraîner la pixellisation des tampons de rendu de taille réduite ou des éléments de résolution inférieure. Utilisez vos assets de la plus haute qualité sur les appareils à grand écran et profilz les performances de votre jeu pour éviter tout problème. Si votre jeu est compatible avec plusieurs niveaux de qualité, assurez-vous qu'il prend en compte les appareils à grand écran.

Mode multifenêtre

Le mode multifenêtre permet à plusieurs applications de partager le même écran simultanément. Le mode multifenêtre ne modifie pas le cycle de vie de l'activité. Toutefois, l'état de reprise des applications dans plusieurs fenêtres varie selon les versions d'Android (consultez Cycle de vie de l'activité en mode multifenêtre dans Compatibilité avec le mode multifenêtre).

Lorsque le joueur met une application ou un jeu en mode multifenêtre, le système notifie l'activité d'un changement de configuration, comme spécifié dans la section Redimensionnement avancé des grands écrans. Un changement de configuration se produit également lorsque le joueur redimensionne le jeu ou le remet en mode plein écran.

Rien ne garantit que l'application retrouvera son focus lorsqu'elle passera en mode multifenêtre. Par conséquent, si vous utilisez l'un des événements d'état de l'application pour mettre en pause votre jeu, ne comptez pas sur l'événement de focus d'acquisition (onWindowFocusChanged() avec la valeur de ciblage définie sur "true") pour reprendre le jeu. Utilisez plutôt d'autres gestionnaires d'événements ou de gestionnaires de changement d'état, tels que onConfigurationChanged() ou onResume(). Notez que vous pouvez toujours utiliser la méthode isInMultiWindowMode() pour détecter si l'activité en cours s'exécute en mode multifenêtre.

Avec le mode multifenêtre sur ChromeOS, les dimensions de la fenêtre initiale deviennent un élément important à prendre en compte. Un jeu n'a pas besoin d'être en plein écran et vous devez déclarer la taille de la fenêtre pour ce cas. Deux méthodes sont recommandées.

La première option fonctionne avec l'utilisation d'attributs spécifiques sur la balise <layout> dans votre fichier manifeste Android. Les attributs defaultHeight et defaultWidth contrôlent les dimensions initiales. Tenez également compte des attributs minHeight et minWidth pour empêcher vos joueurs de redimensionner la fenêtre de jeu en des dimensions non compatibles. Enfin, l'attribut gravity détermine l'emplacement de la fenêtre lorsqu'elle est lancée. Voici un exemple de balise de mise en page utilisant ces attributs:

<layout android:defaultHeight="500dp"
        android:defaultWidth="600dp"
        android:gravity="top|end"
        android:minHeight="450dp"
        android:minWidth="300dp" />

La deuxième option permettant de définir la taille de la fenêtre consiste à utiliser des limites de lancement dynamiques. Vous pouvez définir les dimensions de la fenêtre de départ à l'aide de setLaunchBounds(Rect)⁠⁠. Si un rectangle vide est spécifié, l'activité démarre dans un état agrandi.

De plus, si vous utilisez les moteurs de jeu Unity ou Unreal, assurez-vous d'utiliser une version récente (Unity 2019.4.40 et Unreal 5.3 ou version ultérieure) compatible avec le mode multifenêtre.

Prise en charge de la position des appareils pliables

Utilisez la bibliothèque de mises en page WindowManager Jetpack pour prendre en charge les positions des appareils pliables (à plat, par exemple) afin d'améliorer l'immersion et l'engagement des joueurs:

Figure 3 : Jeu en position à plat avec la vue principale sur la partie verticale de l'écran et les commandes sur la partie horizontale.

Kotlin

fun isTableTopPosture(foldFeature : FoldingFeature?) : Boolean {
    contract { returns(true) implies (foldFeature != null) }
    return foldFeature?.state == FoldingFeature.State.HALF_OPENED &&
            foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL
}

Java

boolean isTableTopPosture(FoldingFeature foldFeature) {
    return (foldFeature != null) &&
           (foldFeature.getState() == FoldingFeature.State.HALF_OPENED) &&
           (foldFeature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL);
}