Test Foro de elhacker.net SMF 2.1

Programación => Programación General => Java => Mensaje iniciado por: Maurice_Lupin en 19 Junio 2011, 21:30 PM

Título: Doble buffer - Animación "Nieve" en java
Publicado por: Maurice_Lupin en 19 Junio 2011, 21:30 PM
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
 
Código (java) [Seleccionar]

  Image buffer;
  Graphics pantallaVirtual;
 
 
  //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.

 
Código (java) [Seleccionar]
public void paint(Graphics g) {        
        g.drawImage(fondo,0,0,this); // dibujamos el fondo
        g.setColor(new Color(240, 240, 255));        
g.drawOval(10,10,200,200);    
   }
 
  public void update(Graphics g) {
       // 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
Código (java) [Seleccionar]

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
public class Nevando extends Applet implements Runnable {
   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;
   Thread hilo;
   Image buffer, fondo;  
   Graphics pantallaVirtual;
   Random aleat;      
   
   // Constructor
   public Nevando() {        
       try {
           ok = false;
           Calendar ahora = Calendar.getInstance();
           aleat = new Random(ahora.getTime().hashCode());
       }
       catch (Exception ed) {ed.printStackTrace();}                
   }
   
   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 );
       }
       catch( Exception e ) {System.out.println( e.getMessage()); }
   }
   
   
   public void stop() { hilo = null; }
   
   public void start() {
       if(hilo == null) {
           hilo=new Thread(this);
           hilo.start();
       }
   }
   
   // aquí pintamos todo la animacion
   public void paint(Graphics g) {        
        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"
   public void update(Graphics g) {
       // 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
           catch(InterruptedException e){}            
       }
       
   }
}


Aqui el proyecto en Netbeans 5.5 de la animación de nieve en java, tiene comentarios
http://www.mediafire.com/?x69b70m1s74bds3
Título: Re: Doble buffer- animación nieve en java
Publicado por: ShotgunLogic en 19 Junio 2011, 23:13 PM
Muy guapo, estaría bien subir unas recopilaciones de chorradas de estas porque se aprenden bastantes cosas!
Título: Re: Doble buffer- animación nieve en java
Publicado por: Debci en 20 Junio 2011, 07:51 AM
Cita de: ShotgunLogic en 19 Junio 2011, 23:13 PM
Muy guapo, estaría bien subir unas recopilaciones de chorradas de estas porque se aprenden bastantes cosas!
En todo caso no son chorradas, y menos si como tu dices, aprendes.

Saludos
Título: Re: Doble buffer- animación nieve en java
Publicado por: ShotgunLogic en 20 Junio 2011, 11:56 AM
Cita de: Debci en 20 Junio 2011, 07:51 AM
En todo caso no son chorradas, y menos si como tu dices, aprendes.

Saludos

Joder, era una expresión, ya que al fin y al cabo son complementos y cosillas, madre mía como saltas :¬¬
Título: Re: Doble buffer - Animación "Nieve" en java
Publicado por: Maurice_Lupin en 21 Junio 2011, 08:47 AM
Algunos más, otros menos lo importante es aprender  ;D
Título: Re: Doble buffer - Animación "Nieve" en java
Publicado por: Odai en 14 Septiembre 2014, 01:31 AM
Gracias!  :rolleyes:
Título: Re: Doble buffer - Animación "Nieve" en java
Publicado por: Maurice_Lupin en 14 Septiembre 2014, 17:41 PM
Cita de: Niara en 14 Septiembre 2014, 01:31 AM
Gracias!  :rolleyes:

Gracias por comentar, me gusta tu lema  ;D.

Saludos.