Aumentar la Apariencia y el Rendimiento de una Animación

Podrías haber observado dos cosas en la animación de la página anterior:

El problema de la muestra de imágenes parciales tiene fácil solución, utilizando la clase MediaTracker. MediaTracker también disminuye el tiempo que tardan en cargarse las imágenes. Otra forma de tratar el problema de la carga lenta es cambiar el formato de la imagen de alguna forma; esta página le ofrece algunas sugerencias pra hacerlo.

Utilizar MediaTracker para Cargar Imágenes y Retardar el dibujo de éstas

La clase MediaTracker permite cargar fácilmente los datos de un grupo de imágenes y saber cuando se han cargado éstas completamente. Normalmente, los datos de una imagen no se cargan hasta que la imagen es dibujada por primera vez. Para pedir que que los datos de una grupo de imágenes sean precargados asíncronamente, puede utilizar las formas de checkID() y checkAll() que utilizan un argumento booleando, seleccionando el argumento a true. Para cargar los datos síncronamente (esperando a que los datos lleguen) utilice los étodos waitForID() y waitForAll(). Los métodos de MediaTracker que cargan los datos utilizan varios Threads en segundo plano para descargar los datos, resultando en un aumento de la velocidad.

Para comprobar el estado de carga de una imagen, se pueden utilizar los métodos statusID() y statusAll() de MediaTracker. Para comprobar si queda alguna imagen por cargar, puede utiliza los métodos checkID() y checkAll().

Aquí tienes la versión modificada del applet de ejemplo que utiliza los métodos waitForAll() y checkAll() de MediaTacker. Hasta que se carguen todas las imágenes, el applet sólo muestra el mensaje "Please wait...". Puede ver la documentación de la clase MediaTracker para ver un ejemplo que dibuja el fondo inmediatamente pero espera a dibujar las imágenes animadas.

Aquí tienes el applet en acción:

Abajo tienes el código modificado que utiliza MediaTracker como ayuda para retardar el dibujo de las imagenes. Las diferencias se han marcado en negrita.

...//Donde se declaren las variables de ejemplar:
MediaTracker tracker;

...//En el método init():
tracker = new MediaTracker(this);
for (int i = 1; i <= 10; i++) {
    images[i-1] = getImage(getCodeBase(),
                           "../../../images/duke/T"+i+".gif");
    tracker.addImage(images[i-1], 0);
}

...//Al principio del método run():
try {
    //Empieza la carga de imágenes. Esperar hasta que se hayan cargado
    tracker.waitForAll();
} catch (InterruptedException e) {}

...//Al principio del método update():
//Si no se han cargado todas las imágenes, borrar el fondo
//y mostrar la cadena de estado.
if (!tracker.checkAll()) {
    g.clearRect(0, 0, d.width, d.height);
    g.drawString("Please wait...", 0, d.height/2);
}

//Si las imágenes se han cargado, dibujarlas
else {
    ...//el mismo código de antes...

Acelerar la Carga de Imágenes

Tanto si use tiliza MediaTracker como si no, la carga de imágenes utilizando URLs (cómo hacen normalmente los applets) tarda mucho tiempo. La mayoría del tiempo se consume en inicializar las conexiones HTTP. Cada fichero de imagen requiere un conexión HTTP separada, y cada conexión tarda varios segundos en inicializarse. La técnica apra evitar esto es combinar las imágenes en un sólo fichero. Se puede además aumentar el rendimiento utilizando algún algoritmo de compresión, especialmente uno diseñado para imágenes móviles.

Una forma sencilla de combinar imágenes en un único fichero es crear una tira de imágenes. Aquí tienes un ejemplo de una tira de imágenes:

jack.gif:

Para dibujar una imagen de la tira, primero se debe seleccionar el área de recorte al tamaño de una imagen. Cuando se dibuje la tira de imágenes, desplazalo a la izquierda (si es necesario) para que sólo aparezca dentro del área de dibujo la imagen que se quiere. Por ejemplo:

//imageStrip es el objeto Image que representa la tira de imágenes.
//imageWidth es el tamaño individual de una imagen.
//imageNumber es el número (desde 0 a numImages) de la imagen a dibujar.
int stripWidth = imageStrip.getWidth(this);
int stripHeight = imageStrip.getHeight(this);
int imageWidth = stripWidth / numImages;
g.clipRect(0, 0, imageWidth, stripHeight);
g.drawImage(imageStrip, -imageNumber*imageWidth, 0, this);

Si se quiere que la carga de imágenes sea aún más rápida, se debería buscar un formato de compresión de imágenes, especialmente cóno Flic que realiza una compresión inter-marcos.


Ozito