Admite el cambio de tamaño de pantallas grandes

Expandir tu juego de teléfonos a diferentes factores de forma de pantalla grande implica considerar cómo tu juego maneja la administración de ventanas. En Googlebook, ChromeOS y Google Play Juegos para PC, tu juego puede ejecutarse en modo de ventana sobre una interfaz de escritorio principal. En las nuevas tablets y dispositivos plegables Android que ejecutan Android 12L (nivel de API 32) o versiones posteriores con un ancho de pantalla superior a 600 dp, tu 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 de configuración para el tamaño de la ventana y, en algunos dispositivos, la orientación.

Ajuste de tamaño en juegos de Unity

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 puedes admitir el cambio de tamaño, asegúrate de que el manifiesto del juego defina de forma explícita 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 la relación de aspecto de 16:9 si la orientación principal es horizontal y la relación de aspecto de 9:16 si el juego está en modo vertical. Para obtener la mejor experiencia, admite de forma explícita las relaciones de aspecto 21:9, 16:10 y 3:2 para un juego en orientación horizontal. Aquí no se requiere el cambio de tamaño de la ventana, pero sigue siendo bueno tenerlo para la compatibilidad con otros factores de forma.

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

Pantallas grandes

Para maximizar el área visible de tu juego en pantalla completa en tablets de pantalla grande, plegables, Googlebook, ChromeOS y pantallas conectadas, admite el modo inmersivo de pantalla completa y oculta las barras del sistema configurando marcas en decorView, la visibilidad de la IU del sistema o a través de la API de WindowInsetsCompat. También deberás controlar con elegancia los eventos de configuración de rotación y cambio de tamaño, o bien evitar que se produzcan.

Ten en cuenta que, en los dispositivos Android con pantallas grandes, tu juego puede ejecutarse en configuraciones que tal vez aún no admitas. Si tu juego no admite todas las configuraciones de tamaño y orientación de la ventana, la plataforma lo mostrará en formato de modo de compatibilidad y, si es necesario, le mostrará un mensaje al jugador antes de cambiar a una configuración no admitida.

Figura 1: Cuadro de diálogo de compatibilidad de la configuración.

En algunos dispositivos, cuando un jugador cambia a una configuración no admitida, es posible que se le solicite que vuelva a cargar el juego y recree la actividad para que se ajuste 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 de 2/3, 1/2 y 1/3) y verifica que no se corten ni se vuelvan inaccesibles los elementos de la IU o del juego. Además, prueba cómo responde tu juego a la continuidad de plegables cuando se cambia entre la pantalla interior y la exterior en dispositivos plegables. Si ves problemas, controla de forma explícita estos eventos de configuración y agrega compatibilidad avanzada con el cambio de tamaño para pantallas grandes.

Capacidad avanzada de cambio de tamaño de pantallas grandes

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

Para salir del modo de compatibilidad y evitar la recreación de la actividad, 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 de tu juego para recibir todos los eventos de configuración de la pantalla grande:

    <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 de la ventana, el ancho y la altura:

    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 WindowManager para verificar la rotación actual del dispositivo. Con estos metadatos, verifica las dimensiones de la ventana nueva y renderiza el contenido 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 que, como alternativa, puedes anclar la IU del juego al nuevo tamaño de la ventana y agregarle un formato de pantalla ancha al contenido principal del juego. Si hay limitaciones técnicas o de diseño que impiden cualquiera de los dos enfoques, haz tu propio letterboxing en el motor para conservar la relación de aspecto y escalar a las mejores dimensiones posibles mientras declaras resizeableActivity = false y evitas el modo de configuración.

Independientemente del enfoque que adoptes, prueba tu juego en varias configuraciones (plegado y desplegado, diferentes cambios de rotación, modo de pantalla dividida) y asegúrate de que no haya elementos de la IU del juego cortados o superpuestos, problemas con la accesibilidad de los objetivos táctiles o problemas de relación de aspecto que hagan que el juego se estire, se comprima o se distorsione de alguna otra manera.

Además, las pantallas más grandes suelen tener píxeles más grandes, ya que tienes la misma cantidad de píxeles para un área mucho más grande. Esto puede provocar pixelación en los búferes de renderización reducidos o en los recursos de menor resolución. Usa tus recursos de mayor calidad en dispositivos con pantallas grandes y crea 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 de 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 según la versión de Android (consulta Ciclo de vida de la actividad en el modo multiventana en Compatibilidad con el modo multiventana).

Cuando el jugador pone una app o un juego en modo multiventana, el sistema notifica a la actividad un cambio de configuración, como se especifica en la sección Capacidad avanzada de cambio de tamaño para pantallas grandes. También se produce un cambio de configuración cuando el jugador cambia el tamaño del juego o lo vuelve a poner en modo de pantalla completa.

No se garantiza que la aplicación recupere el enfoque cuando se coloque en modo multiventana. Por lo tanto, si usas alguno de los eventos de estado de la app para pausar el juego, no confíes en el evento de adquisición de enfoque (onWindowFocusChanged() con el valor de enfoque como verdadero) para reanudar el juego. En su lugar, usa otros controladores de eventos o controladores de cambios 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 las ventanas de escritorio en Googlebook, ChromeOS y tablets y plegables de pantalla grande, las dimensiones iniciales de la ventana se convierten en un factor importante. Un juego no tiene que ser de pantalla completa, y querrás declarar cuál debería ser el tamaño de la ventana en ese caso. Hay dos formas recomendadas de abordar este problema.

La primera opción funciona usando atributos específicos en la etiqueta <layout> de tu manifiesto de Android. Los atributos defaultHeight y defaultWidth controlan las dimensiones iniciales. También ten en cuenta los atributos minHeight y minWidth para evitar que los jugadores cambien el tamaño de la ventana del juego a dimensiones que no admites. Por último, está el atributo gravity, que determina en qué parte de la pantalla aparece la ventana cuando se inicia. A continuación, se muestra 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 establecer el tamaño de la ventana funciona a través de los límites de inicio dinámicos. Con setLaunchBounds(Rect)⁠⁠, puedes definir las dimensiones iniciales de la ventana. 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 versiones posteriores) que brinde una buena compatibilidad con el modo multiventana.

Soporte de postura plegable

Usa la biblioteca de diseño de WindowManager de Jetpack para admitir posturas plegables, como la de mesa, y aumentar la inmersión y la interacción de los jugadores:

Figura 3: Juego en posición de mesa con la vista principal en la parte vertical de la pantalla y los 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);
}