sábado, 30 de junio de 2012

Animaciones en Java


Las animaciones tienen un gran interés desde diversos puntos de vista. Una imagen vale más quemil palabras y una imagen en movimiento es todavía mucho más útil. Para presentar o describir ciertos conceptos el movimiento animado es fundamental. Además, las animaciones o mejor dicho, la forma de hacer animaciones en Java ilustran mucho la forma en que dicho lenguaje realiza los gráficos. En estos apartados se va a seguir el esquema del Tutorial de Sun sobre el AWT.
Se pueden hacer animaciones de una forma muy sencilla: se define el método paint() de forma que cada vez que sea llamado dibuje algo diferente de lo que ha dibujado la vez anterior. De todas formas, recuérdese que el programador no llama directamente a este método. El programador llama al método repaint(), quizás dentro de un bucle while que incluya una llamada al método sleep() de la clase Thread , para esperar un cierto número de milisegundos entre dibujo y dibujo (entre frame y frame, utilizando la terminología de las animaciones). Recuérdese que repaint() llama a update() lo antes posible, y que update() borra todo redibujando con el color de fondo y llama a paint().
La forma de proceder descrita da buenos resultados para animaciones muy sencillas, pero produce parpadeo o flicker cuando los gráficos son un poco más complicados. La razón está en el propio proceso descrito anteriormente, combinado con la velocidad de refresco del monitor. La velocidad de refresco vertical de un monitor suele estar entre 60 y 75 herzios. Eso quiere decir que la imagen se actualiza unas 60 ó 75 veces por segundo. Cuando el refresco se realiza después de haber borrado la imagen anterior pintando con el color de fondo y antes de que se termine de dibujar de nuevo toda la imagen, se obtiene una imagen incompleta, que sólo aparecerá terminada en uno de los siguientes pasos de refresco del monitor. Ésta es la causa del flicker. A continuación se verán dos formas de reducirlo o eliminarlo.

Eliminación del parpadeo o flicker redefiniendo el método update()

El problema del flicker se localiza en la llamada al método update(), que borra todo pintando con el color de fondo y después llama a paint(). Una forma de resolver esta dificultad es re-definir el método update(), de forma que se adapte mejor al problema que se trata de resolver.
Una posibilidad es no re-pintar todo con el color de fondo, no llamar a paint() e introducir en update() el código encargado de realizar los dibujos, cambiando sólo aquello que haya que cambiar.
A pesar de esto, es necesario re-definir paint() pues es el método que se llama de forma automática cuando la ventana de Java es tapada por otra que luego se retira. Una posible solución es hacer que paint() llame a update(), terminando por establecer un orden de llamadas opuesto al de defecto. Hay que tener en cuenta que, al no borrar todo pintando con el color de fondo, el programador tiene que preocuparse de borrar de forma selectiva entre frame y frame lo que sea necesario. Los métodos setClip() y clipRect() de la clase Graphics permiten hacer que las operaciones gráficas no surtan efecto fuera de un área rectangular previamente determinada. Al ser dependiente del tipo de gráficos concretos de que se trate, este método no siempre proporciona soluciones adecuadas.

Técnica del doble buffer

La técnica del doble buffer proporciona la mejor solución para el problema de las animaciones, aunque requiere una programación algo más complicada. La idea básica del doble buffer es realizar los dibujos en una imagen invisible, distinta de la que se está viendo en la pantalla, y hacerla visible cuando se ha terminado de dibujar, de forma que aparezca instantáneamente.
Para crear el segundo buffer o imagen invisible hay que crear un objeto de la clase Image del mismo tamaño que la imagen que se está viendo y crear un contexto gráfico u objeto de la clase Graphics que permita dibujar sobre la imagen invisible. Esto se hace con las sentencias,
Image imgInv;
Graphics graphInv;
Dimension dimInv;
Dimension d = size();    // se obtiene la dimensión del panel
en la clase que controle el dibujo (por ejemplo en una clase que derive de Panel). En el método update() se modifica el código de modo que primero se dibuje en la imagen invisible y luego ésta se haga visible:
Los gráficos y las animaciones son particularmente útiles en las applets. El Tutorial de Sun tiene un ejemplo (un applet) completamente explicado y desarrollado sobre las animaciones y los distintos métodos de eliminar el flicker o parpadeo.

No hay comentarios:

Publicar un comentario