Scene2D UI es una herramienta muy útil para crear interfaces gráficas en nuestros proyectos, especialmente cuando trabajamos con libGDX. Nos permite aprovechar la potencia de Scene2D para añadir botones, etiquetas, campos de texto y otros widgets que ya vienen implementados como actores, facilitando mucho el trabajo a la hora de construir interfaces de usuario.
Al empezar a usar Scene2D UI, uno de los primeros conceptos que nos encontramos es el de la Skin. La Skin es fundamental porque contiene toda la información visual que necesita la librería para dibujar los elementos de la interfaz: imágenes, colores, tipografías, estilos de botones, checkboxes, y más. Sin una Skin, aunque creemos un botón con texto, no podremos mostrarlo correctamente y nos encontraremos con errores. Por suerte, no tenemos que crear una Skin desde cero, ya que libGDX nos proporciona un conjunto de archivos que forman una Skin lista para usar.
Estos archivos son cinco en total: una imagen PNG que actúa como un texture atlas con todos los recursos gráficos, un archivo .atlas que define las regiones dentro de esa imagen, un archivo .json que relaciona las imágenes con las clases y estilos de Scene2D UI, y dos archivos relacionados con las fuentes Bitmap Font (.fnt y .png) que definen cómo se muestran los textos. Al descargar estos archivos y colocarlos en la carpeta adecuada dentro de nuestro proyecto, podemos cargar la Skin fácilmente pasando el archivo .json al constructor de la clase Skin. Esto nos permite tener una Skin funcional sin complicaciones.
Una vez que tenemos la Skin, podemos crear widgets como botones (TextButton), etiquetas (Label) o campos de texto (TextField) simplemente instanciándolos y pasándoles la Skin. Por ejemplo, para crear un botón con texto Menú, haríamos algo así:
TextButton button = new TextButton("Menú", skin);
stage.addActor(button);
button.setPosition(50, 50);
Sin embargo, colocar manualmente cada widget con setPosition puede ser tedioso y propenso a errores, especialmente cuando queremos añadir varios elementos y mantener una disposición ordenada. Para solucionar esto, Scene2D UI nos ofrece contenedores, siendo el más importante y utilizado el Table.
Las tablas funcionan como contenedores que organizan automáticamente los widgets en filas y columnas, facilitando la creación de interfaces limpias y adaptables. Para usar una tabla, simplemente la creamos, la añadimos al escenario y luego vamos añadiendo widgets a ella. Además, podemos hacer que la tabla ocupe todo el espacio disponible con table.setFillParent(true), lo que nos permite controlar mejor la disposición de los elementos.
Un ejemplo típico es crear una tabla para pedir al usuario su nombre y puntuación, con etiquetas y campos de texto organizados en dos filas y dos columnas:
Table table = new Table();
table.setFillParent(true);
table.debug(); // Para ver los bordes de las celdas durante el desarrollo
stage.addActor(table);
Label labelNombre = new Label("Nombre", skin);
Label labelPuntuacion = new Label("Puntuacion", skin);
TextField fieldNombre = new TextField("", skin);
TextField fieldPuntuacion = new TextField("500", skin);
table.add(labelNombre);
table.add(fieldNombre);
table.row();
table.add(labelPuntuacion);
table.add(fieldPuntuacion);
Al añadir widgets con table.add(), obtenemos un objeto Cell que representa la celda donde se coloca el widget. Este objeto nos permite modificar propiedades como la alineación, tamaño, expansión, relleno (padding) y más, mediante métodos encadenables. Por ejemplo, para ajustar el tamaño de un campo de texto, podemos hacer:
table.add(fieldNombre).width(300).height(100);
Esto hace que el campo tenga un ancho de 300 píxeles y una altura de 100 píxeles. También podemos usar métodos como prefWidth o prefHeight para indicar tamaños preferidos que la tabla intentará respetar si es posible.
El padding es útil para añadir márgenes dentro de las celdas y evitar que los elementos estén demasiado juntos. Por ejemplo, para añadir un margen a la derecha de 20 píxeles:
table.add(labelPuntuacion).padRight(20);
La alineación dentro de las celdas también es configurable con métodos como left(), right(), center(), top() y bottom(). Por ejemplo, para alinear un label a la derecha:
table.add(labelNombre).right();
Cuando queremos que un widget ocupe varias columnas, usamos el método colspan. Por ejemplo, si añadimos un botón para enviar la puntuación y queremos que ocupe dos columnas:
TextButton sendButton = new TextButton("Enviar", skin);
table.row();
table.add(sendButton).colspan(2);
Para controlar cómo se distribuye el espacio extra en la tabla, podemos usar expand(), expandX() y expandY(). Estos métodos hacen que la celda se expanda para ocupar el espacio disponible, repartiendo el espacio entre todas las celdas que tengan esta propiedad activada. Por ejemplo, para que el botón Enviar se expanda horizontal y verticalmente:
table.add(sendButton).colspan(2).expand().fill();
El método fill() hace que el widget ocupe todo el espacio de la celda, ajustando su tamaño para que no queden espacios vacíos.
Además de modificar celdas individuales, también podemos alinear la tabla completa dentro del escenario con métodos como center(), left(), right(), top() y bottom(). Por ejemplo, para alinear toda la tabla abajo a la izquierda:
table.bottom().left();
Y podemos añadir padding a la tabla para que no ocupe todo el espacio disponible, dejando márgenes alrededor:
table.pad(30);
En resumen, Scene2D UI nos ofrece una forma potente y flexible de construir interfaces gráficas mediante widgets ya implementados y contenedores como las tablas, que nos permiten organizar los elementos de forma sencilla y personalizable. Aunque la librería tiene sus peculiaridades, como la necesidad de manejar skins externos, una vez que entendemos estos conceptos básicos podemos crear interfaces limpias y funcionales con relativa facilidad.