Archivos e Interfaz de Usuario

UI para nuestro RPG: Parte 3

En esta tercera parte de la serie sobre la UI para nuestro RPG, continuamos desarrollando la interfaz gráfica utilizando Java Swing, añadiendo más componentes y funcionalidades para mejorar la experiencia del usuario.

Continuando con la UI para nuestro RPG

En esta tercera parte de la serie sobre la UI para nuestro RPG, continuamos desarrollando la interfaz gráfica utilizando Java Swing. En las partes anteriores, hemos creado una ventana básica y añadido algunos componentes iniciales. Ahora, vamos a añadir más componentes y funcionalidades para mejorar la experiencia del usuario.

El campo de texto para el nombre del personaje

Una de las funcionalidades que queremos añadir es un campo de texto donde el jugador pueda ingresar el nombre de su personaje. Para esto, utilizaremos la clase JTextField de Swing. Aquí te muestro cómo hacerlo:

app/game/rpg/ui/components/inputs/RPGInputText.java
package app.game.rpg.ui.components.inputs;

import app.game.rpg.ui.components.borders.RPGRoundedBorder;
import app.game.rpg.utils.FontCache;

import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.io.IOException;
import java.util.Objects;

public class RPGInputText extends JTextField {

    public RPGInputText() {

        super();
        Font font;
        try {
            font = Font.createFont(Font.TRUETYPE_FONT, Objects.requireNonNull(getClass().getResourceAsStream("/fonts/BoldPixels.ttf"))).deriveFont(Font.PLAIN, 22f);
        } catch (FontFormatException | IOException e) {
            throw new RuntimeException(e);
        }
        setFont(font);
        setBorder(new CompoundBorder(new RPGRoundedBorder(3, 10),
                new EmptyBorder(5, 5, 5, 5)));
        setOpaque(false);
    }

    @Override
    public void paint(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(getBackground());
        g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 10, 10);
        super.paint(g);
        g2d.dispose();
    }
}

Como puedes ver, hemos creado una clase RPGInputText que extiende de JTextField. En el constructor, configuramos la fuente personalizada y el borde redondeado utilizando una clase RPGRoundedBorder que hemos creado previamente. Además, sobrescribimos el método paint para dibujar un fondo redondeado detrás del campo de texto.

Algo importante en este caso es que estamos utilizando una fuente personalizada, por lo que es necesario cargarla desde un archivo de recursos. Para esto, utilizamos el método getResourceAsStream para obtener un InputStream de la fuente y luego la cargamos utilizando Font.createFont. Si ocurre algún error al cargar la fuente, lanzamos una excepción.

Barra de progreso para la salud del personaje

Otra funcionalidad que queremos añadir es una barra de progreso para mostrar la salud del personaje. Para esto, utilizaremos la clase JProgressBar de Swing. Aquí te muestro cómo hacerlo:

app/game/rpg/ui/components/bars/RPGProgressBar.java
package app.game.rpg.ui.components.bars;

import app.game.rpg.ui.components.borders.RPGRoundedBorder;
import app.game.rpg.ui.components.delegates.RPGProgressBarUI;

import javax.swing.*;
import java.awt.*;

public abstract class RPGProgressBar extends JProgressBar {

    protected Color startColor;
    protected Color endColor;
    protected int radius=5;

    public RPGProgressBar(int min, int max) {
        super(min, max);

        setOpaque(false);
        setBorder(new RPGRoundedBorder(3, radius));
        setStringPainted(true);
        setFont(new Font("Arial", Font.BOLD, 18));
        setForeground(Color.white);

        // 🔥 Asignamos UI personalizada
        setUI(new RPGProgressBarUI());
    }

    public void setBarColor(Color start, Color end) {
        this.startColor = start;
        this.endColor = end;
        repaint();
    }

    public Color getStartColor() {
        return startColor;
    }

    public Color getEndColor() {
        return endColor;
    }

    public int getRadius() {
        return radius;
    }
}

En esta clase RPGProgressBar, extendemos de JProgressBar y añadimos propiedades para los colores de inicio y fin de la barra, así como un radio para las esquinas redondeadas. En el constructor, configuramos la apariencia de la barra, incluyendo un borde redondeado y una fuente personalizada para el texto que muestra el porcentaje. Además, asignamos una UI personalizada utilizando la clase RPGProgressBarUI, que se encargará de dibujar la barra con un degradado de colores que veremos a continuación.

app/game/rpg/ui/components/delegates/RPGProgressBarUI.java
package app.game.rpg.ui.components.delegates;

import app.game.rpg.ui.components.bars.RPGProgressBar;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.plaf.basic.BasicProgressBarUI;
import java.awt.*;

public class RPGProgressBarUI extends BasicProgressBarUI {

    @Override
    protected void paintDeterminate(Graphics g, JComponent c) {

        Graphics2D g2 = (Graphics2D) g.create();

        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        RPGProgressBar bar = (RPGProgressBar) c;

        int width = bar.getWidth();
        int height = bar.getHeight();

        int value = bar.getValue();
        int max = bar.getMaximum();

        int progressWidth = (int) (width * (value / (double) max));

        int radius = bar.getRadius();

        // 🔲 Fondo
        g2.setColor(new Color(30, 30, 30));
        g2.fillRoundRect(0, 0, width, height, radius, radius);

        // ❤️ Progreso con degradado
        Point startPoint = new Point(0, 0);
        Point endPoint = new Point(width, 0);
        float[] fractions = {0f, 0.45f, 1f};
        Color[] colors = {bar.getStartColor(), bar.getEndColor(), bar.getStartColor()};
        LinearGradientPaint gradient = new LinearGradientPaint(startPoint, endPoint, fractions, colors);
        g2.setPaint(gradient);
        g2.fillRoundRect(0, 0, progressWidth, height, radius, radius);

        // 🟡 Borde reutilizable
        Border border = bar.getBorder();
        if (border != null) {
            border.paintBorder(bar, g2, 0, 0, width, height);
        }

        // 🔤 Texto centrado
        String text = "%s/%s".formatted(value, max);
        FontMetrics fm = g2.getFontMetrics();
        int textWidth = fm.stringWidth(text);
        int textHeight = fm.getAscent();
        int textX = (width - textWidth) / 2;
        int textY = (height + textHeight) / 2 - 2;
        g2.setFont(bar.getFont());
        g2.setColor(bar.getForeground());
        g2.drawString(text, textX, textY);

        g2.dispose();
    }
}

En la clase RPGProgressBarUI, extendemos de BasicProgressBarUI y sobrescribimos el método paintDeterminate para personalizar la forma en que se dibuja la barra de progreso. Utilizamos un degradado de colores para el progreso y dibujamos un fondo oscuro para el resto de la barra. Además, centramos el texto que muestra el valor actual y el máximo.

Recuerda que puedes hacer uso de cualquier tipo de degradado, no solo lineales. Experimenta con RadialGradientPaint o ConicalGradientPaint para obtener efectos más interesantes y adapta la clase RPGProgressBar según tus necesidades para dicho degradado.

Creando las barras de salud y maná

Ahora que tenemos nuestra clase RPGProgressBar, podemos crear instancias específicas para la salud y el maná de nuestro personaje. Aquí te muestro cómo hacerlo:

app/game/rpg/ui/components/bars/RPGLifeBar.java
package app.game.rpg.ui.components.bars;

import java.awt.*;

public class RPGLifeBar extends RPGProgressBar{

    public RPGLifeBar() {
        super(75, 125);
        this.startColor = new Color(255, 0, 0);
        this.endColor = new Color(145, 1, 1);
    }
}
app/game/rpg/ui/components/bars/RPGManaBar.java
package app.game.rpg.ui.components.bars;

import java.awt.*;

public class RPGManaBar extends RPGProgressBar {

    public RPGManaBar() {
        super(25, 100);
        setBarColor(new Color(0, 0, 255), new Color(1, 1, 145));
    }
}

En estas clases RPGLifeBar y RPGManaBar, extendemos de RPGProgressBar y configuramos los colores específicos para cada barra. La barra de vida utiliza tonos rojos, mientras que la barra de maná utiliza tonos azules. Puedes ajustar los valores máximos y mínimos según las necesidades de tu juego y crear las barras que necesites para otros recursos como la experiencia, la energía, etc.

Integrando los componentes en el panel de personaje

Finalmente, podemos integrar estos componentes en el panel de personaje para mostrar la información relevante del personaje. Aquí te muestro un ejemplo de cómo hacerlo:

app/game/rpg/ui/panels/RPGCharacterPanel.java
package app.game.rpg.ui.panels;

import app.game.rpg.ui.components.bars.RPGLifeBar;
import app.game.rpg.ui.components.bars.RPGManaBar;
import app.game.rpg.ui.components.textfields.RPGInputText;
import javax.swing.*;
import java.awt.*;

public class RPGCharacterPanel extends JPanel {

    private RPGLifeBar lifeBar;
    private RPGManaBar manaBar;
    private RPGInputText nameField;

    public RPGCharacterPanel() {
        setLayout(new BorderLayout());
        setBackground(new Color(20, 20, 20));

        // 🧑‍🦲 Campo de texto para el nombre del personaje
        nameField = new RPGInputText();
        nameField.setPreferredSize(new Dimension(200, 40));
        add(nameField, BorderLayout.NORTH);

        // ❤️ Barra de vida
        lifeBar = new RPGLifeBar();
        lifeBar.setPreferredSize(new Dimension(300, 30));
        add(lifeBar, BorderLayout.CENTER);

        // 🔵 Barra de maná
        manaBar = new RPGManaBar();
        manaBar.setPreferredSize(new Dimension(300, 30));
        add(manaBar, BorderLayout.SOUTH);
    }

    public void updateCharacterStats(int health, int mana) {
        lifeBar.setValue(health);
        manaBar.setValue(mana);
    }
}

Este es un ejemplo de cómo integrar las barras de vida y maná en un panel de personaje. En este panel, también hemos añadido un campo de texto para el nombre del personaje. Puedes personalizar el diseño y la disposición de los componentes según tus necesidades, utilizando diferentes layouts o añadiendo más elementos como iconos, habilidades, etc. La función updateCharacterStats te permite actualizar los valores de salud y maná en tiempo real, lo que es útil para reflejar los cambios durante el juego.

Recuerda que al final, tu interfaz de usuario debe ser intuitiva y fácil de entender para los jugadores, así que no dudes en experimentar con diferentes diseños y estilos para encontrar el que mejor se adapte a tu juego.

Conclusión

En esta sección, hemos creado un sistema de barras de progreso personalizadas para representar la salud y el maná de un personaje en un juego RPG. Hemos utilizado Java Swing para diseñar estas barras con un estilo único, utilizando degradados de colores y bordes redondeados para mejorar su apariencia. Además, hemos integrado estas barras en un panel de personaje que también incluye un campo de texto para el nombre del personaje. Este enfoque modular te permite reutilizar los componentes y personalizarlos según las necesidades de tu juego, lo que facilita la creación de una interfaz de usuario atractiva y funcional para tus jugadores.

Copyright Jesús Aurelio Castro Magaña © 2026