Controlar la resolución y el escalado en un juego desarrollado con LibGDX es fundamental para garantizar que la experiencia visual sea óptima, sin importar el tamaño o la proporción de la ventana. Para ello, debemos entender primero cómo manejar el tamaño de la ventana y luego cómo utilizar cámaras ortográficas para mantener la calidad y proporción del contenido.
En plataformas móviles, la resolución está limitada a la pantalla física del dispositivo, por lo que no podemos cambiarla directamente. Sin embargo, en escritorio, al tratarse de una ventana, sí podemos modificar su tamaño. Esto se logra ajustando los parámetros width y height en la configuración de la aplicación, específicamente en la clase LwjglApplicationConfiguration. Por ejemplo, podemos establecer una ventana de 960 píxeles de ancho por 540 de alto modificando estos valores antes de iniciar el juego.
Aunque cambiar el tamaño de la ventana es sencillo, surge un problema común: al redimensionar la ventana, los elementos del juego pueden verse distorsionados o pixelados. Para solucionar esto, debemos aprovechar el método resize, que se ejecuta cada vez que cambia el tamaño de la ventana y recibe las nuevas dimensiones. Aquí es donde entra en juego el concepto de cámara.
Las cámaras en LibGDX son herramientas poderosas que nos permiten controlar qué parte del mundo del juego se muestra en pantalla y cómo se escala. Existen dos tipos principales: cámaras ortográficas, usadas para juegos 2D, y cámaras de perspectiva, para juegos 3D. La diferencia radica en cómo representan la profundidad: la cámara de perspectiva muestra objetos más cercanos más grandes, mientras que la cámara ortográfica mantiene el tamaño constante sin importar la distancia.
Para nuestro juego 2D, utilizaremos una cámara ortográfica. La creamos pasando el ancho y alto del viewport, que podemos obtener con Gdx.graphics.getWidth() y Gdx.graphics.getHeight(). Una vez creada, debemos indicarle a nuestro SpriteBatch y a nuestro ShapeRenderer que usen esta cámara para renderizar, mediante el método setProjectionMatrix(cam.combined).
Para visualizar mejor cómo funciona la cámara, podemos dibujar los ejes de coordenadas usando ShapeRenderer. Esta clase nos permite dibujar líneas, puntos y figuras geométricas directamente con OpenGL, fuera del contexto del SpriteBatch. Por ejemplo, para dibujar una línea horizontal en el eje X desde -1000 a 1000 en Y=0, y una línea vertical en el eje Y desde -1000 a 1000 en X=0, podemos usar:
shaper.begin(ShapeRenderer.ShapeType.Line);
shaper.line(-1000, 0, 1000, 0); // Eje X
shaper.line(0, -1000, 0, 1000); // Eje Y
shaper.end();
Además, podemos añadir marcas cada 50 píxeles para simular las divisiones de un eje, dibujando pequeñas líneas perpendiculares a los ejes principales en un bucle.
Cuando cambiamos el tamaño de la ventana, debemos actualizar la cámara para que su viewport coincida con las nuevas dimensiones. Esto se hace en el método resize con:
cam.setToOrtho(false, width, height);
El parámetro false indica que el origen de coordenadas estará en la esquina inferior izquierda, que es el sistema más común en juegos 2D.
Una vez configurada la cámara, podemos manipularla para mover la vista o hacer zoom. Para mover la cámara, usamos el método translate con los desplazamientos deseados en X e Y, y luego llamamos a update para aplicar los cambios:
cam.translate(10, 0); // Mueve la cámara 10 píxeles a la derecha
cam.update();
Para implementar un control básico de cámara con teclado, podemos detectar las teclas de dirección y mover la cámara en consecuencia.
El zoom se controla modificando la propiedad zoom de la cámara, sumando o restando valores pequeños para acercar o alejar la vista:
cam.zoom += 0.01f; // Acercar
cam.zoom -= 0.01f; // Alejar
cam.update();
Este control de zoom, junto con el movimiento de la cámara, nos permite crear efectos como scrollers o acercamientos dinámicos en el juego.
En resumen, al combinar la configuración adecuada de la ventana con el uso de cámaras ortográficas y ShapeRenderer, podemos controlar eficazmente la resolución, el escalado y la vista de nuestro juego en LibGDX, asegurando que los elementos se muestren correctamente sin distorsiones, independientemente del tamaño o proporción de la ventana.