Foro de elhacker.net

Programación => 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
  1.   Image buffer;
  2.   Graphics pantallaVirtual;
  3.  
  4.  
  5.   //creamos una imagen
  6.   buffer = createImage(Ancho, Alto);
  7.  
  8.   // creamos la pantalla virtual para el Doble Buffer
  9.   pantallaVirtual = buffer.getGraphics();
  10.  

  
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
  1. public void paint(Graphics g) {        
  2.         g.drawImage(fondo,0,0,this); // dibujamos el fondo
  3.         g.setColor(new Color(240, 240, 255));        
  4. g.drawOval(10,10,200,200);    
  5.    }
  6.  
  7.   public void update(Graphics g) {
  8.        // dibujamos en la pantalla virtual, esto se hace en memoria
  9.        // no se visualizara
  10.        paint(pantallaVirtual);        
  11.        // se vuelca la imagen "buffer" en la pantalla real
  12.        g.drawImage(buffer, 0, 0,640,400, this);          
  13.    }  

Animación nieve: Nevando.java
Código
  1. import java.awt.*;
  2. import java.util.Random;
  3. import java.util.Calendar;
  4. import java.applet.Applet;
  5. //Clase Nieve
  6. class Nieve {
  7.    // coordenadas del copo de nieve
  8.    int x, y;
  9.    // indica la dirección
  10.    // derecha = 1 ó izquierda = -1
  11.    int jock;
  12.    //Constructor
  13.    public Nieve(int a, int b, int c) {
  14.        x = a;
  15.        y = b;
  16.        jock = c;
  17.    }
  18. }//fin clase Nieve
  19.  
  20. // Clase Nevando
  21. public class Nevando extends Applet implements Runnable {
  22.    int Ancho=320, Alto = 200;
  23.    public static final int MAX_COPOS = 250;
  24.    Nieve copo[] = new Nieve[MAX_COPOS];
  25.    // matriz que representa a la pantalla virtual
  26.    // para comprobar la posición de un copo
  27.    int Tabla[][] = new int[Ancho][Alto];
  28.    boolean ok;
  29.    Thread hilo;
  30.    Image buffer, fondo;  
  31.    Graphics pantallaVirtual;
  32.    Random aleat;      
  33.  
  34.    // Constructor
  35.    public Nevando() {        
  36.        try {
  37.            ok = false;
  38.            Calendar ahora = Calendar.getInstance();
  39.            aleat = new Random(ahora.getTime().hashCode());
  40.        }
  41.        catch (Exception ed) {ed.printStackTrace();}                
  42.    }
  43.  
  44.    public void iniciarTabla() {
  45.        // inicializa la matriz con Ceros, porque esta vacia
  46.        for(int j=0; j<Alto; j++)
  47.            for(int i=0; i < Ancho; i++)
  48.                Tabla[i][j] = 0;
  49.    }
  50.  
  51.    // devuelve un numero entre "i" e "f" aletoriamente
  52.    int aleatorio(int i, int f) {
  53.        double random = aleat.nextDouble();
  54.        return ((int)((random*(f-i))+i));
  55.    }
  56.  
  57.    // devuelve 0 si la posicion esta libre
  58.    // si la posicion esta ocupada devuelve 1
  59.    boolean comprobarTabla(int h, int k) {                
  60.        if(h>0 && k>0 && h<Ancho && k<Alto)
  61.            if( Tabla[h][k] == 0) return true;        
  62.        return false;
  63.    }
  64.  
  65.    //metodo init() propio del applet
  66.    public void init() {
  67.        iniciarTabla();
  68.        int k;
  69.        // inicializamos los copos
  70.        for(int j=0; j< MAX_COPOS; j++) {
  71.            k = aleatorio(0,2);
  72.            if(k==0) k = -1;
  73.            // contruimos un nuevo copo
  74.            copo[j] = new Nieve( aleatorio(0,Ancho),aleatorio(0,Alto) , k);
  75.            Tabla[ copo[j].x ][ copo[j].y ] = 1; // representamos el copo en la matriz
  76.        }
  77.        try {
  78.            // cargamos la imagen de fondo
  79.            fondo = getImage(getCodeBase(),"imagenes/fondo.jpg");
  80.  
  81.            //creamos una imagen de 320x200 pixels
  82.            buffer = createImage(Ancho, Alto);
  83.            // creamos la pantalla virtual para el Doble Buffer
  84.            pantallaVirtual = buffer.getGraphics();
  85.  
  86.            //tamaño del Applet 640x400 pixels
  87.            resize(Ancho*2,Alto*2 );
  88.        }
  89.        catch( Exception e ) {System.out.println( e.getMessage()); }
  90.    }
  91.  
  92.  
  93.    public void stop() { hilo = null; }
  94.  
  95.    public void start() {
  96.        if(hilo == null) {
  97.            hilo=new Thread(this);
  98.            hilo.start();
  99.        }
  100.    }
  101.  
  102.    // aquí pintamos todo la animacion
  103.    public void paint(Graphics g) {        
  104.         g.drawImage(fondo,0,0,this); // dibujamos el fondo
  105.         g.setColor(new Color(240, 240, 255));        
  106.         // dibuja la nieve
  107.         for(int i = 0; i < MAX_COPOS; i++) {
  108.             g.fillOval(copo[i].x, copo[i].y, 2, 2);
  109.         }        
  110.    }
  111.  
  112.    // todo lo que hagamos en "pantallaVirtual" se vera reflejado en
  113.    // la imagen "buffer"
  114.    public void update(Graphics g) {
  115.        // dibujamos en la pantalla virtual, esto se hace en memoria
  116.        // no se visualizara
  117.        paint(pantallaVirtual);        
  118.        // se vuelca la imagen "buffer" en la pantalla real
  119.        g.drawImage(buffer, 0, 0,640,400, this);          
  120.    }        
  121.  
  122. // aqui realizamos todo el proceso de animacion  
  123. public void run() {
  124.        while(hilo != null) {
  125.            // la logico de los copos
  126.            for(int i=0; i<MAX_COPOS; i++) {
  127.                // Si el copo aun no llega al suelo lo borramos
  128.                if(copo[i].y < Alto-1)
  129.                    Tabla[copo[i].x][copo[i].y++] = 0;
  130.  
  131.                if(aleatorio(0,2)==0) // si es 0 movemos x
  132.                    copo[i].x += copo[i].jock*(-1);
  133.  
  134.                // Si el copo se sale de la pantalla, se crea uno nuevo
  135.                if((copo[i].x <= 0) || (copo[i].x >= Ancho-1)) {
  136.                    copo[i].x = aleatorio(0,Ancho);
  137.                    copo[i].y = 0;
  138.                    Tabla[copo[i].x][copo[i].y] = 1;
  139.                    copo[i].jock = aleatorio(0,2);
  140.                    if (copo[i].jock == 0) copo[i].jock = -1;
  141.                }
  142.  
  143.                // Si ok=1 significara que el copo aun esta dentro de la pantalla
  144.                ok=((copo[i].x>=0) && (copo[i].x<Ancho) && (copo[i].y>=0) &&(copo[i].y<Alto));
  145.  
  146.                // "Esto es para que el copo caiga si esta en algun objeto"
  147.                // Vemos el punto central                
  148.                if(comprobarTabla( copo[i].x , copo[i].y ) && ok)
  149.                    Tabla[ copo[i].x ][ copo[i].y ] = 1;
  150.  
  151.                // Vemos el punto derecha-abajo
  152.                else if(comprobarTabla(copo[i].x+1, copo[i].y+1) && ok)
  153.                    Tabla[copo[i].x++][copo[i].y++] = 1;
  154.  
  155.                // Vemos el punto izquierda-abajo
  156.                else if(comprobarTabla(copo[i].x-1,copo[i].y+1) && ok)
  157.                    Tabla[copo[i].x--][copo[i].y++] = 1;
  158.  
  159.                // Vemos el punto central-abajo
  160.                else if(comprobarTabla(copo[i].x,copo[i].y+1) && ok)
  161.                    Tabla[copo[i].x][copo[i].y++] = 1;
  162.  
  163.                else // Si no esta en ningun borde, lo dejamos en ese sitio
  164.                {    // y creamos nuevo copo
  165.                    if(ok) {
  166.                        Tabla[copo[i].x][copo[i].y-1] = 1;
  167.                        copo[i].x = aleatorio(0,Ancho);
  168.                        copo[i].y = 0;
  169.                        Tabla[copo[i].x][copo[i].y] = 1;
  170.                        copo[i].jock = aleatorio(0,2);
  171.                        if(copo[i].jock == 0) copo[i].jock = -1;
  172.                    }
  173.                }
  174.  
  175.            }
  176.            repaint(); // llama al metodo Update
  177.            try{hilo.sleep(20);} // para el proceso por 20/1000 segundos
  178.            catch(InterruptedException e){}            
  179.        }
  180.  
  181.    }
  182. }
  183.  

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
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
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
Gracias!  :rolleyes:

Gracias por comentar, me gusta tu lema  ;D.

Saludos.