UI para nuestro RPG: Parte 5
¿Qué es una caché?
La caché es un mecanismo que almacena datos en memoria para su acceso rápido. En el contexto de la programación, la caché se utiliza para mejorar el rendimiento al almacenar datos que se acceden con frecuencia, evitando así el acceso constante a la base de datos o el disco duro.
¿Cómo implementar una caché?
Para efectos de nuestro curso, usaremos una tabla hash para implementar la caché, ya que es un mecanismo eficiente y rápido para acceder a datos.
Veamos entonces una implementación básica de una caché.
package app.game.rpg.utils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Objects;
public class ImageCache {
public static final HashMap<String, BufferedImage> IMAGES = new HashMap<>();
public static void addImage(String name, String path) {
if (!IMAGES.containsKey(name))
IMAGES.putIfAbsent(name, load(path));
}
public static BufferedImage getImage(String name) {
return IMAGES.get(name);
}
private static BufferedImage load(String path) {
try {
return ImageIO.read(
Objects.requireNonNull(ImageCache.class.getResource("/img/" + path))
);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Como puedes ver, la caché es una clase simple que contiene un HashMap para almacenar las imágenes. Dicha clase cuenta
con dos métodos principales: addImage y getImage.
Por un ladó addImage se encarga de agregar una imagen a la caché, y por otro getImage se encarga de obtener una
imagen de la caché.
Por otro lado, el método load se encarga de cargar las imágenes desde el disco, esto mediante el uso de ImageIO.read
y el bloque try-with-resources.
Así mismo quizás te preguntes sobre Objects.requireNonNull y class.getResource, así que aclaremos estos puntos.
Objects.requireNonNull
Objects.requireNonNull es un método que se encarga de verificar que un objeto no sea nulo, si es nulo, lanza una
excepción NullPointerException. Esto es de vital importancia para el manejo de archivos, ya que permite controlar
cuando un archivo está corrupto o no se encuentra.
class.getResource
Por su parte, class.getResource es un método que se encarga de obtener el URL de un archivo en el classpath. En este
caso, estamos obteniendo el URL de la propia clase estática ImageCache.
Y aquí se presenta un punto importante, el uso de getResource es posible siempre que nuestro proyecto esté configurado
correctamente, es decir, que dentro del classpath del proyecto se agrega y define un directorio resources.
Para lograr esto podemos usar varios caminos de acuerdo a nuestro editor. Por ejemplo en IntelliJ basta con crear una
carpeta en raíz del proyecto y seleccionarla como resources al dar clic derecho sobre ella.
Una vez hecho esto, el directorio resources se encuentra disponible para el uso de getResource y por consiguiente
podremos crear subcarpetas y archivos dentro de él, los cuales podremos cargar con ImageIO.read o el stream necesario,
según la naturaleza de tus archivos.
¿Cómo dibujo algo?
Para Swing, el proceso de dibujo es parte de la clase Graphics2D. Por lo que si queremos dibujar algo, deberemos de
crear un objeto de esta clase y usar sus métodos para dibujar.
Tomemos el siguiente fragmento como ejemplo:
@Override
public ImageIcon getImage() {
if (image == null) {
ImageCache.addImage("Slime", "characters/Slime.png");
image = new ImageIcon(ImageCache.getImage("Slime"));
}
return image;
}
En esta función, puedes ver que usamos ImageCache para cargar la imagen, y ImageIcon para dibujarla. Esto se dbe a
que ImageIcon es un componente de Swing que se encarga de dibujar la imagen en la interfaz y requiere de un archivo
valido para poder dibujarlo.
@Override
public void paint(Graphics g, JComponent c) {
Graphics2D g2d = (Graphics2D) g.create();
Icon icon = ((JLabel) c).getIcon();
if (icon != null) {
icon.paintIcon(c, g2d, ((c.getWidth() - icon.getIconWidth()) / 2) - 2,
c.getHeight() - icon.getIconHeight() - 5);
}
g2d.dispose();
}
Por su parte ya en la función paint lo que debemos hacer es cargar él ImageIcon y dibujarlo en la interfaz. Aunque
de igual manera puedes crear un ImageIcon y dibujarlo en la interfaz.
Conclusión
Como puedes ver, Swing es un framework poderoso para crear interfaces de usuario, y con él puedes crear interfaces atractivas y funcionales. Y mediante el uso de las Cachés y de las funciones adecuadas, puedes hacer uso de imágenes de manera eficiente y rápida.
UI para nuestro RPG: Parte 4
En esta cuarta parte de la serie sobre la creación de una interfaz de usuario para nuestro RPG, se profundiza en la implementación de características avanzadas y mejoras en la experiencia del usuario.
UI para nuestro RPG: Parte 6
En esta quinta entrega hablaremos del uso de imágenes en Swing