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 para 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...". Puedes 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í está el applet en acción:

Abajo está el código cambiado que usa un MediaTracker para retardar el dibujado de las imágenes. Las diferencias están marcadas en negrita.

...//Where instance variables are declared:
MediaTracker tracker;

...//In the init() method:
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);
}

...//At the beginning of the run() method:
try {
    //Start downloading the images. Wait until they're loaded.
    tracker.waitForAll();
} catch (InterruptedException e) {}

...//At the beginning of the update() method:
//If not all the images are loaded, just clear the background
//and display a status string.
if (!tracker.checkAll()) {
    g.clearRect(0, 0, d.width, d.height);
    g.drawString("Please wait...", 0, d.height/2);
}

//If all images are loaded, draw.
else {
    ...//same code as before...

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 is the Image object representing the image strip.
//imageWidth is the size of an individual image in the strip.
//imageNumber is the number (from 0 to numImages) of the image to draw.
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 uno como Flic que realiza una compresión inter-marcos.

Ozito