En el proceso de crear un juego sencillo con LibGDX, uno de los primeros pasos fundamentales es entender cómo dibujar elementos en pantalla de manera eficiente y clara. Para ello, partimos de la base que nos ofrece la clase ApplicationAdapter, que simplifica la implementación de los métodos necesarios para manejar el ciclo de vida del juego, como create() y render(). El método create() se ejecuta al iniciar el juego y es ideal para inicializar variables y cargar recursos, mientras que render() se llama repetidamente para actualizar y dibujar la escena.
Para mostrar imágenes, utilizamos principalmente dos clases: Texture y SpriteBatch. La clase Texture se encarga de cargar imágenes desde el disco duro y almacenarlas en la memoria de la tarjeta gráfica, lo que permite que OpenGL las dibuje rápidamente. Sin embargo, enviar cada imagen individualmente a la tarjeta gráfica puede ser lento, por lo que SpriteBatch actúa como un intermediario que agrupa múltiples dibujos para enviarlos todos juntos, mejorando significativamente el rendimiento, especialmente cuando se dibujan muchas imágenes.
El proceso básico para dibujar con SpriteBatch consiste en llamar a begin(), luego usar draw() para indicar qué imágenes y en qué posiciones queremos mostrarlas, y finalmente llamar a end() para enviar todo a la tarjeta gráfica. Además, podemos controlar el color de fondo de la pantalla usando Gdx.gl.glClearColor(), donde los valores RGB van de 0 a 1, permitiéndonos elegir cualquier color para limpiar la pantalla antes de dibujar.
Para mostrar texto en pantalla, LibGDX ofrece la clase BitmapFont. Crear una fuente básica es tan sencillo como instanciar un objeto BitmapFont y luego usar su método draw() para escribir cadenas de texto en coordenadas específicas. Es importante recordar que en LibGDX el origen de coordenadas está en la esquina inferior izquierda, por lo que la posición (10, 10) se refiere a un punto cercano a esa esquina. Para posicionar texto en la parte superior, podemos obtener la altura de la ventana con Gdx.graphics.getHeight() y ajustar la coordenada vertical en consecuencia.
Cuando queremos mostrar imágenes que no ocupan toda la textura o que forman parte de un conjunto más grande, usamos TextureRegion. Esta clase nos permite definir una región rectangular dentro de una textura para dibujar solo esa parte específica. Por ejemplo, si tenemos una imagen que incluye un coche y un espacio en blanco, podemos crear un TextureRegion que abarque únicamente el área del coche, evitando mostrar el espacio vacío. Esto es especialmente útil para trabajar con spritesheets o imágenes compuestas.
Sin embargo, manejar manualmente las posiciones, tamaños y regiones puede volverse complicado y propenso a errores. Para simplificar esta gestión, LibGDX ofrece la clase Sprite, que extiende TextureRegion y añade funcionalidades adicionales. Un Sprite no solo almacena la textura y la región que debe mostrar, sino que también mantiene su propia posición, tamaño, rotación y color. Esto nos permite manipular el sprite de forma más intuitiva y encapsulada.
Por ejemplo, podemos crear un sprite para nuestro coche y luego cambiar su posición con setPosition(x, y). Para dibujarlo, en lugar de llamar a batch.draw() con múltiples parámetros, simplemente llamamos a sprite.draw(batch). Además, podemos rotar el sprite con rotate(grados), lo que facilita crear animaciones o efectos visuales sin complicaciones adicionales.
Un aspecto crucial que no debemos olvidar es la gestión de recursos. Aunque Java cuenta con un recolector de basura para la memoria RAM, las texturas se almacenan en la memoria de la GPU, que no es gestionada automáticamente. Por ello, es fundamental liberar estos recursos cuando ya no los necesitamos, utilizando el método dispose(). Este método debe llamarse, por ejemplo, en el método dispose() de nuestra clase que extiende ApplicationAdapter, para asegurarnos de que la memoria gráfica se libera correctamente y evitar fugas de memoria que puedan afectar el rendimiento del juego.
En resumen, para dibujar en pantalla con LibGDX, contamos con varias herramientas que nos permiten desde mostrar texto simple con BitmapFont, cargar y mostrar imágenes completas con Texture, recortar partes específicas con TextureRegion, hasta manejar objetos gráficos complejos y manipulables con Sprite. Todo esto se realiza de manera eficiente gracias a SpriteBatch, que optimiza el proceso de dibujo enviando múltiples imágenes juntas a la tarjeta gráfica. Además, la correcta gestión de recursos con dispose() es esencial para mantener nuestro juego funcionando de manera óptima.
public class MiJuego extends ApplicationAdapter {
private SpriteBatch batch;
private Texture cocheTexture;
private Sprite cocheSprite;
private BitmapFont font;
private int screenWidth, screenHeight;
@Override
public void create() {
batch = new SpriteBatch();
// Cargar la textura desde la carpeta assets
cocheTexture = new Texture("coche.png");
// Crear un sprite con la textura y definir tamaño y posición
cocheSprite = new Sprite(cocheTexture);
cocheSprite.setSize(210, 83);
cocheSprite.setPosition(50, 50);
// Crear una fuente para mostrar texto
font = new BitmapFont();
// Obtener dimensiones de la pantalla
screenWidth = Gdx.graphics.getWidth();
screenHeight = Gdx.graphics.getHeight();
}
@Override
public void render() {
// Limpiar la pantalla con un color gris oscuro
Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
// Dibujar el sprite del coche
cocheSprite.draw(batch);
// Dibujar texto en la parte superior de la pantalla
font.draw(batch, "Hola mundo", 10, screenHeight - 10);
batch.end();
}
@Override
public void dispose() {
// Liberar recursos para evitar fugas de memoria
batch.dispose();
cocheTexture.dispose();
font.dispose();
}
}
Este ejemplo recoge lo esencial para empezar a dibujar en pantalla con LibGDX: cargar imágenes, mostrar texto, usar sprites para manejar objetos gráficos y liberar recursos adecuadamente. A partir de aquí, podemos avanzar hacia interactividad y dinámicas más complejas en nuestro juego.