Una de las características más agradables de Scene2D es la capa de interfaz de usuario construida sobre ella. Scene2D.ui proporciona una serie de widgets que facilitan la creación de una interfaz de usuario, algo que a menudo falta en las bibliotecas de desarrollo de juegos. Dicho esto, hay un obstáculo muy confuso antes de que puedas empezar a trabajar con la interfaz de usuario… Máscaras.
Una máscara es una colección de archivos que van juntos para formar su interfaz de usuario.
El primero es un archivo JSON (notación de objetos de JavaScript), que es un formato popular de almacenamiento de datos basado en JavaScript, como XML light. En el archivo JSON, describe las diversas propiedades de su máscara, como el aspecto que deben tener sus widgets.
El siguiente es un atlas de textura. Examinamos el uso de TexturePacker para crear un atlas de texturas en el tutorial de gráficos. El atlas de texturas describe el diseño de todas las imágenes que componen su interfaz de usuario. Este es un archivo de extensión .atlas.
Junto con el atlas de texturas, también tiene la imagen real que generó TexturePacker.
Finalmente tienes el fnt y la imagen asociada. Cubrimos las fuentes en el tutorial hola mundo.
Todo esto puede parecer bastante desalentador, especialmente si se comienza desde cero. Afortunadamente hay una piel incluida en las pruebas LibGDX. Los archivos que le interesan son uiskin.atlas, uiskin.json, uiskin.png, default.png y default.fnt. Simplemente descargue y coloque cada uno de estos archivos en la carpeta de activos/datos de Android de su proyecto. Si está descargando desde el enlace de Github que proporcioné, ¡asegúrese de descargar la versión RAW de cada archivo!
Echemos un vistazo rápido a algunos de los archivos anteriores para tener una mejor idea de lo que contienen. Ignoraré los archivos de fuentes, ya lo cubrimos. El atlas y el archivo png ya los hemos cubierto también, pero aquí está uiskin.png, así que tienes una idea de lo que se incluye:
Estos son los diversos gráficos que intervienen en la creación de la interfaz de usuario. Echemos un vistazo a uiskin.json:
{ com.badlogic.gdx.graphics.g2d.BitmapFont: { default-font: { file: default.fnt } }, com.badlogic.gdx.graphics.Color: { green: { a: 1, b: 0, g: 1, r: 0 }, white: { a: 1, b: 1, g: 1, r: 1 }, red: { a: 1, b: 0, g: 0, r: 1 }, black: { a: 1, b: 0, g: 0, r: 0 } }, com.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable: { dialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } } }, com.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: { default: { down: default-round-down, up: default-round }, toggle: { down: default-round-down, checked: default-round-down, up: default-round } }, com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: { default: { down: default-round-down, up: default-round, font: default-font, fontColor: white }, toggle: { down: default-round-down, up: default-round, checked: default-round-down, font: default-font, fontColor: white, downFontColor: red } }, com.badlogic.gdx.scenes.scene2d.ui.ScrollPane$ScrollPaneStyle: { default: { vScroll: default-scroll, hScrollKnob: default-round-large, background: default-rect, hScroll: default-scroll, vScrollKnob: default-round-large } }, com.badlogic.gdx.scenes.scene2d.ui.SelectBox$SelectBoxStyle: { default: { font: default-font, fontColor: white, background: default-select, scrollStyle: default, listStyle: { font: default-font, selection: default-select-selection } } }, com.badlogic.gdx.scenes.scene2d.ui.SplitPane$SplitPaneStyle: { default-vertical: { handle: default-splitpane-vertical }, default-horizontal: { handle: default-splitpane } }, com.badlogic.gdx.scenes.scene2d.ui.Window$WindowStyle: { default: { titleFont: default-font, background: default-window, titleFontColor: white }, dialog: { titleFont: default-font, background: default-window, titleFontColor: white, stageBackground: dialogDim } }, com.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle: { default-horizontal: { background: default-slider, knob: default-slider-knob } }, com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: { default: { font: default-font, fontColor: white } }, com.badlogic.gdx.scenes.scene2d.ui.TextField$TextFieldStyle: { default: { selection: selection, background: textfield, font: default-font, fontColor: white, cursor: cursor } }, com.badlogic.gdx.scenes.scene2d.ui.CheckBox$CheckBoxStyle: { default: { checkboxOn: check-on, checkboxOff: check-off, font: default-font, fontColor: white } }, com.badlogic.gdx.scenes.scene2d.ui.List$ListStyle: { default: { fontColorUnselected: white, selection: default-rect-pad, fontColorSelected: white, font: default-font } }, com.badlogic.gdx.scenes.scene2d.ui.Touchpad$TouchpadStyle: { default: { background: default-pane, knob: default-round-large } }, com.badlogic.gdx.scenes.scene2d.ui.Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: default-select-selection } } }
Si alguna vez ha usado CSS, esto debería parecerle inmediatamente familiar. Básicamente, le está diciendo a LibGDX cómo diseñar cada clase utilizando el nombre de clase Java completo. Echemos un vistazo a un ejemplo particular que usaremos en breve, TextButton.
com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: { default: { down: default-round-down, up: default-round, font: default-font, fontColor: white }, toggle: { down: default-round-down, up: default-round, checked: default-round-down, font: default-font, fontColor: white, downFontColor: red } }
fontColor: white, downFontColor: red } }
Estás configurando los valores para la clase. TextButtonStyle o una de las clases de las que se deriva. Puede notar que para fontColor, se pasa «blanco». Si miras hacia arriba en la piel, puedes ver cómo se define:
com.badlogic.gdx.graphics.Color: { green: { a: 1, b: 0, g: 1, r: 0 }, white: { a: 1, b: 1, g: 1, r: 1 }, red: { a: 1, b: 0, g: 0, r: 1 }, black: { a: 1, b: 0, g: 0, r: 0 } }
Puedes ver que «blanco» es un Color con los valores 1/1/1 para rgb y 1 para alfa… en otras palabras, blanco
La otra cosa clave es el valor de abajo. Como puede ver en TextButtonStyle, abajo es un Drawable. El valor especificado, default-round-down es una entrada en el archivo atlas:
default-round-down rotate: false xy: 99, 29 size: 12, 20 split: 5, 5, 5, 4 orig: 12, 20 offset: 0, 0 index: -1
Esto especifica el tamaño y la ubicación dentro del archivo uiskin.png. Se pueden obtener más detalles sobre las máscaras. encontrado en la wiki.
Ahora que tiene sus archivos de máscara, echemos un vistazo a una muestra usando Scene2d.ui:
package com.gamefromscratch; import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Skin; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; public class UIDemo implements ApplicationListener { private SpriteBatch batch; private Skin skin; private Stage stage; @Override public void create() { batch = new SpriteBatch(); skin = new Skin(Gdx.files.internal("data/uiskin.json")); stage = new Stage(); final TextButton button = new TextButton("Click me", skin, "default"); button.setWidth(200f); button.setHeight(20f); button.setPosition(Gdx.graphics.getWidth() /2 - 100f, Gdx.graphics.getHeight()/2 - 10f); button.addListener(new ClickListener(){ @Override public void clicked(InputEvent event, float x, float y){ button.setText("You clicked the button"); } }); stage.addActor(button); Gdx.input.setInputProcessor(stage); } @Override public void dispose() { batch.dispose(); } @Override public void render() { Gdx.gl.glClearColor(1, 1, 1, 1); Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); batch.begin(); stage.draw(); batch.end(); } @Override public void resize(int width, int height) { } @Override public void pause() { } @Override public void resume() { } }
Ejecutas esta aplicación y deberías ver:

La mayor parte de esto es bastante familiar en este punto. Creamos un objeto Skin y lo cargamos usando las típicas llamadas IO de archivo. El archivo que desea cargar es la configuración json, uiskin.json. Este archivo apunta a todos los demás archivos, la máscara los cargará automáticamente. A continuación, creamos un TextButton, los valores que se pasan al constructor son el texto que se mostrará en el botón, la máscara y el valor de la máscara que se usará. Si observa la entrada para TextButton en el archivo JSON de la máscara, verá:
com.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: { default: { down: default-round-down, up: default-round }, toggle: { down: default-round-down, checked: default-round-down, up: default-round } },
Está diciendo que desea utilizar la entrada «predeterminada». Coincidentemente, si no especifica nada, se usará el valor predeterminado. Posicionamos y ajustamos el tamaño del botón y configuramos un detector de clics que simplemente cambia el texto mostrado cuando se hace clic en el botón. Ahora lo interesante… Los widgets de la interfaz de usuario como TextButton son simplemente actores, por lo que funcionan como otros actores de Scene2D, agréguelos al escenario y estará listo para funcionar.
Scene2D ui es un tema bastante complicado, por lo que seguiré con un ejemplo más avanzado en el próximo tutorial.