La tecnica doble buffer nos permite hacer una animación libre de parpadeos, cuando llamas al método
repaint() en un applet, este llama a
update() el cual borra toda la pantalla y redibuja llamando al método
paint(), esto lo hace directamente en la pantalla, por lo que se nota un feo parpadeo
Para realizar el Doble Buffer, sobrescribimos el método
update(), así relizaremos todo el pintado en una pantalla virtual asi no se visualizara hasta que nosotros volquemos esta pantalla virtual a la pantalla real.
ejemplo
//creamos una imagen
buffer = createImage(Ancho, Alto);
// creamos la pantalla virtual para el Doble Buffer
pantallaVirtual = buffer.getGraphics();
Ahora todo lo que hagamos en la pantallaVirtual se verá reflejado en la imagen buffer, podemos pintar un círculo, rectangulo
o una imagen previamente cargada en la pantallaVirtual.
g.drawImage(fondo,0,0,this); // dibujamos el fondo
g.
setColor(new Color(240,
240,
255)); g.drawOval(10,10,200,200);
}
// dibujamos en la pantalla virtual, esto se hace en memoria
// no se visualizara
paint(pantallaVirtual);
// se vuelca la imagen "buffer" en la pantalla real
g.drawImage(buffer, 0, 0,640,400, this);
}
Animación nieve: Nevando.java
import java.awt.*;
import java.util.Random;
import java.util.Calendar;
import java.applet.Applet;
//Clase Nieve
class Nieve {
// coordenadas del copo de nieve
int x, y;
// indica la dirección
// derecha = 1 ó izquierda = -1
int jock;
//Constructor
public Nieve(int a, int b, int c) {
x = a;
y = b;
jock = c;
}
}//fin clase Nieve
// Clase Nevando
int Ancho=320, Alto = 200;
public static final int MAX_COPOS = 250;
Nieve copo[] = new Nieve[MAX_COPOS];
// matriz que representa a la pantalla virtual
// para comprobar la posición de un copo
int Tabla[][] = new int[Ancho][Alto];
boolean ok;
// Constructor
public Nevando() {
try {
ok = false;
aleat
= new Random(ahora.
getTime().
hashCode()); }
}
public void iniciarTabla() {
// inicializa la matriz con Ceros, porque esta vacia
for(int j=0; j<Alto; j++)
for(int i=0; i < Ancho; i++)
Tabla[i][j] = 0;
}
// devuelve un numero entre "i" e "f" aletoriamente
int aleatorio(int i, int f) {
double random = aleat.nextDouble();
return ((int)((random*(f-i))+i));
}
// devuelve 0 si la posicion esta libre
// si la posicion esta ocupada devuelve 1
boolean comprobarTabla(int h, int k) {
if(h>0 && k>0 && h<Ancho && k<Alto)
if( Tabla[h][k] == 0) return true;
return false;
}
//metodo init() propio del applet
public void init() {
iniciarTabla();
int k;
// inicializamos los copos
for(int j=0; j< MAX_COPOS; j++) {
k = aleatorio(0,2);
if(k==0) k = -1;
// contruimos un nuevo copo
copo[j] = new Nieve( aleatorio(0,Ancho),aleatorio(0,Alto) , k);
Tabla[ copo[j].x ][ copo[j].y ] = 1; // representamos el copo en la matriz
}
try {
// cargamos la imagen de fondo
fondo = getImage(getCodeBase(),"imagenes/fondo.jpg");
//creamos una imagen de 320x200 pixels
buffer = createImage(Ancho, Alto);
// creamos la pantalla virtual para el Doble Buffer
pantallaVirtual = buffer.getGraphics();
//tamaño del Applet 640x400 pixels
resize(Ancho*2,Alto*2 );
}
}
public void stop() { hilo = null; }
public void start() {
if(hilo == null) {
hilo.start();
}
}
// aquí pintamos todo la animacion
g.drawImage(fondo,0,0,this); // dibujamos el fondo
g.
setColor(new Color(240,
240,
255)); // dibuja la nieve
for(int i = 0; i < MAX_COPOS; i++) {
g.fillOval(copo[i].x, copo[i].y, 2, 2);
}
}
// todo lo que hagamos en "pantallaVirtual" se vera reflejado en
// la imagen "buffer"
// dibujamos en la pantalla virtual, esto se hace en memoria
// no se visualizara
paint(pantallaVirtual);
// se vuelca la imagen "buffer" en la pantalla real
g.drawImage(buffer, 0, 0,640,400, this);
}
// aqui realizamos todo el proceso de animacion
public void run() {
while(hilo != null) {
// la logico de los copos
for(int i=0; i<MAX_COPOS; i++) {
// Si el copo aun no llega al suelo lo borramos
if(copo[i].y < Alto-1)
Tabla[copo[i].x][copo[i].y++] = 0;
if(aleatorio(0,2)==0) // si es 0 movemos x
copo[i].x += copo[i].jock*(-1);
// Si el copo se sale de la pantalla, se crea uno nuevo
if((copo[i].x <= 0) || (copo[i].x >= Ancho-1)) {
copo[i].x = aleatorio(0,Ancho);
copo[i].y = 0;
Tabla[copo[i].x][copo[i].y] = 1;
copo[i].jock = aleatorio(0,2);
if (copo[i].jock == 0) copo[i].jock = -1;
}
// Si ok=1 significara que el copo aun esta dentro de la pantalla
ok=((copo[i].x>=0) && (copo[i].x<Ancho) && (copo[i].y>=0) &&(copo[i].y<Alto));
// "Esto es para que el copo caiga si esta en algun objeto"
// Vemos el punto central
if(comprobarTabla( copo[i].x , copo[i].y ) && ok)
Tabla[ copo[i].x ][ copo[i].y ] = 1;
// Vemos el punto derecha-abajo
else if(comprobarTabla(copo[i].x+1, copo[i].y+1) && ok)
Tabla[copo[i].x++][copo[i].y++] = 1;
// Vemos el punto izquierda-abajo
else if(comprobarTabla(copo[i].x-1,copo[i].y+1) && ok)
Tabla[copo[i].x--][copo[i].y++] = 1;
// Vemos el punto central-abajo
else if(comprobarTabla(copo[i].x,copo[i].y+1) && ok)
Tabla[copo[i].x][copo[i].y++] = 1;
else // Si no esta en ningun borde, lo dejamos en ese sitio
{ // y creamos nuevo copo
if(ok) {
Tabla[copo[i].x][copo[i].y-1] = 1;
copo[i].x = aleatorio(0,Ancho);
copo[i].y = 0;
Tabla[copo[i].x][copo[i].y] = 1;
copo[i].jock = aleatorio(0,2);
if(copo[i].jock == 0) copo[i].jock = -1;
}
}
}
repaint(); // llama al metodo Update
try{hilo.sleep(20);} // para el proceso por 20/1000 segundos
}
}
}
Aqui el proyecto en Netbeans 5.5 de la animación de nieve en java, tiene comentarios
http://www.mediafire.com/?x69b70m1s74bds3