Compatibilidad con el cambio de tamaño de pantalla grande

La expansión de teléfonos a diferentes factores de forma de pantalla grande presenta consideraciones sobre la forma en que el juego maneja la administración de ventanas. En ChromeOS y Google Play Juegos para PC, tu juego puede ejecutarse en modo con ventanas mediante una interfaz principal de escritorio. En las nuevas tablets y dispositivos plegables Android que ejecuten Android 12L (nivel de API 32) o versiones posteriores con un ancho de pantalla superior a 600 dp, el juego puede ejecutarse en paralelo en el modo de pantalla dividida con otras aplicaciones, cambiar de tamaño y hasta moverse entre la pantalla interior y exterior en dispositivos plegables, lo que genera un cambio en la configuración del tamaño de la ventana y, en algunos dispositivos, la orientación.

Configuración básica de pantallas grandes

Declara si tu juego puede controlar el cambio de tamaño:

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

Si no admites el cambio de tamaño, asegúrate de que el manifiesto del juego defina explícitamente las relaciones de aspecto mínimas y máximas admitidas:

<!-- 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 Juegos para PC

En el caso de Google Play Juegos para PC, la plataforma controla el cambio de tamaño de la ventana y respeta la relación de aspecto especificada. El tamaño de la ventana se bloquea automáticamente en las dimensiones óptimas. Debes admitir, al menos, una relación de aspecto de 16:9 si la orientación principal es horizontal y una de 9:16 si el juego está en modo vertical. Para obtener la mejor experiencia, admite explícitamente las relaciones de aspecto de 21:9, 16:10 y 3:2 para un juego horizontal. En este caso, no es necesario cambiar el tamaño de la ventana, pero sigue siendo útil para admitir otros factores de forma.

Para obtener más información y las prácticas recomendadas, consulta Cómo configurar gráficos para Google Play Juegos para PC.

Pantallas grandes de ChromeOS y Android

Para maximizar el área visible de tu juego en pantalla completa en ChromeOS y en dispositivos Android con pantalla grande, debes admitir el modo envolvente de pantalla completa y ocultar las barras del sistema. Para ello, configura marcas en decorView, la visibilidad de la IU del sistema o la API de WindowInsetsCompat. También es recomendable que manejes correctamente la rotación y el cambio de tamaño de los eventos de configuración, o bien evitar que ocurran en dispositivos ChromeOS.

Ten en cuenta que, en dispositivos Android de pantalla grande, tu juego puede ejecutarse en configuraciones que quizás aún no controles. Si tu juego no admite todas las configuraciones de tamaño y orientación de ventana, la plataforma lo envía en formato letterbox en modo de compatibilidad y, si es necesario, le muestra un mensaje al jugador antes de cambiar a una configuración no compatible.

Figura 1: Diálogo de compatibilidad de configuración.

En algunos dispositivos, cuando un jugador cambia a una configuración no compatible, es posible que se le solicite una opción para volver a cargar el juego y recrear la actividad de modo que se adapte mejor al nuevo diseño de la ventana, lo que interrumpe la experiencia de juego. Prueba tu juego en varias configuraciones del modo multiventana (tamaño de ventana 2/3, 1/2, 1/3) y verifica que ningún juego o elementos de la IU se corten o queden inaccesibles. Además, prueba cómo responde tu juego a la continuidad de los dispositivos plegables cuando te mueves entre la pantalla interior y exterior en dispositivos plegables. Si detectas problemas, controla de forma explícita estos eventos de configuración y agrega compatibilidad avanzada con el cambio de tamaño de pantallas grandes.

Opción avanzada de cambio de tamaño en pantallas grandes

Figura 2: Diferentes IUs en computadoras y dispositivos plegables en posición de mesa.

Para salir del modo de compatibilidad y evitar la recreación de actividades, haz lo siguiente:

  1. Declara tu actividad principal como redimensionable:

    <android:resizeableActivity="true" />
    
  2. Declara la compatibilidad explícita con "orientation", "screenSize", "smallestScreenSize", "screenLayout" y "density" en el atributo android:configChanges del elemento <activity> del manifiesto del juego para recibir todos los eventos de configuración de pantallas grandes:

    <android:configChanges="screenSize | smallestScreenSize | screenLayout | orientation | keyboard |
                            keyboardHidden | density" />
    
  3. Anula onConfigurationChanged() y controla el evento de configuración, incluida la orientación actual, el tamaño, el ancho y la altura de la ventana:

    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();
    }
    

También puedes consultar el objeto WindowManager para verificar la rotación actual del dispositivo. Con estos metadatos, verifica las nuevas dimensiones de la ventana y renderiza al tamaño completo de la ventana. Es posible que esto no funcione en todos los casos debido a las diferencias en la relación de aspecto. Por lo tanto, ancla la IU del juego al nuevo tamaño de ventana y en formato letterbox al contenido principal del juego. Si hay limitaciones técnicas o de diseño que impiden cualquiera de los enfoques, aplica tu propio formato letterbox en el motor para preservar la relación de aspecto y escala a las mejores dimensiones posibles mientras declaras resizeableActivity = false y evitas el modo de configuración.

Sin importar el enfoque que adoptes, prueba tu juego en varias configuraciones (pliegue y despliega, diferentes cambios de rotación, modo de pantalla dividida) y asegúrate de que no haya elementos de IU cortes o superpuestos, problemas de accesibilidad con objetivos táctiles o problemas de relación de aspecto que provoquen que el juego se estire, se aplaste o se distorsione de alguna otra manera.

Además, las pantallas más grandes generalmente significan píxeles más grandes, porque tienes la misma cantidad de píxeles para un área mucho más grande. Esto puede provocar que se pixelen los búferes de renderización reducidos o los recursos de menor resolución. Usa tus recursos de la más alta calidad en dispositivos con pantallas grandes y genera un perfil de rendimiento de tu juego para asegurarte de que no haya problemas. Si tu juego admite varios niveles de calidad, asegúrate de que tenga en cuenta los dispositivos con pantalla grande.

Modo multiventana

El modo multiventana permite que varias apps compartan la misma pantalla al mismo tiempo. El modo multiventana no cambia el ciclo de vida de la actividad. Sin embargo, el estado reanudado de las apps en varias ventanas difiere en las diferentes versiones de Android (consulta Ciclo de vida de la actividad en el modo multiventana en Compatibilidad con el modo multiventana).

Cuando el jugador coloca una app o un juego en el modo multiventana, el sistema notifica a la actividad sobre un cambio de configuración, como se especifica en la sección Configuración avanzada de cambio de tamaño en pantallas grandes. Un cambio de configuración también ocurre cuando el jugador cambia el tamaño del juego o lo coloca nuevamente en el modo de pantalla completa.

No hay garantía de que la aplicación recupere el foco cuando se ponga en el modo multiventana. Por lo tanto, si usas cualquiera de los eventos de estado de la app para pausar el juego, no dependas del evento de adquisición de enfoque (onWindowFocusChanged() con el valor de enfoque verdadero) para reanudar el juego. En su lugar, usa otros controladores de eventos o controladores de cambio de estado, como onConfigurationChanged() o onResume(). Ten en cuenta que siempre puedes usar el método isInMultiWindowMode() para detectar si la actividad actual se ejecuta en el modo multiventana.

Con el modo multiventana en ChromeOS, las dimensiones de la ventana inicial se convierten en una consideración importante. No es necesario que un juego esté en pantalla completa. En ese caso, deberás declarar el tamaño de la ventana. Hay dos formas recomendadas de abordar esto.

La primera opción funciona con atributos específicos de la etiqueta <layout> de tu manifiesto de Android. Los atributos defaultHeight y defaultWidth controlan las dimensiones iniciales. Ten en cuenta también los atributos minHeight y minWidth para evitar que los jugadores cambien el tamaño de la ventana del juego a dimensiones que no admitas. Por último, está el atributo gravity, que determina en qué lugar de la pantalla aparece la ventana cuando se inicia. A continuación, verás un ejemplo de etiqueta de diseño que usa estos atributos:

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

La segunda opción para configurar el tamaño de la ventana puede usarse con límites de inicio dinámicos. Si usas setLaunchBounds(Rect)⁠⁠, puedes definir las dimensiones de la ventana de inicio. Si se especifica un rectángulo vacío, la actividad se inicia en un estado maximizado.

Además, si usas los motores de juegos Unity o Unreal, asegúrate de usar una versión reciente (Unity 2019.4.40 y Unreal 5.3 o posterior) que proporcione una buena compatibilidad con el modo multiventana.

Compatibilidad con posición plegable

Usa la biblioteca de diseño de WindowManager de Jetpack para admitir posiciones plegables, como de mesa, a fin de aumentar la inmersión y participación de los jugadores:

Figura 3: Juego en posición de mesa con vista principal en la parte vertical de la pantalla y controles en la parte horizontal.

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);
}