Home E-Books Special Effects and Game Development in Java Double buffering

Special Effects and Game Development in Java(TM) - Double buffering

by Anibal Wainstein

4.2 Double buffering 

Double buffering is a technique used in almost any programming languages by game and special effect developers. When you draw lines, rectangles, texts and images directly to the screen, then you can in principle see when every object is drawn. This is not good if you only want the spectator to see the end result and nothing more. As we have seen with the textscroller and slideshow examples, this can cause flimmering. To avoid this, you draw first on a buffer (that is why it is called "double buffering"). The buffer is an image that you draw on "in secret" and do not show it to the spectator until it is finished. In Java you do this by creating an image as large as the applet, and then you get a Graphics object connected to this image. When you have finished drawing then you call the paint() method that displays the buffer image on the screen.

4.2.1 SlideShow II, now without flimmering

To add double buffering to the slideshow applet in the last section, me must first declare a global Image variable and a Graphics variable that we initialize in the init() method. Add the following variables to the global applet variables (add them under the declaration of the "nextimagepositiony" variable):

//"bufferimage" is used as the buffer and
//"bufferg" is used to draw on this buffer.
Image bufferimage;
Graphics bufferg;
//"delay" will be used instead of "sleeptime" to
//delay the each animation. "sleeptime" will be used to
//add a configurable delay between each image instead.
int delay=0;

Now that we are in the process of changing the applet, we can take the opportunity to add a new parameter, "delay". This variable will be used instead of "sleeptime" as a delay in the animation. The variable "sleeptime" will be used as the pause between each next image instead. Now the user of this applet will be able to specify a delay before the next image is animated. To create the graphics buffer we write the following lines and add them last in the init() method:

//Fetch the size for the applet.
Dimension d=size();
//createImage() creates an empty image
//that has the same dimensions as the
//applet screen.
bufferimage=createImage(d.width,d.height);
//"bufferg" is now associated with the
//buffer image.
bufferg=bufferimage.getGraphics();
delay=getIntegerParameter("delay",10);

The only thing we have to do now is to see to that the two images are drawn in the buffer first and not directly on the screen. This is done in the paint() method:

public synchronized void paint(Graphics g)
{
    //First we should check that "bufferg"
    //is initialized, it is not always sure that it
    //is.
if (bufferg!=null)
    {
    //We draw the two images into the buffer first.
        bufferg.drawImage(images[currentimage],0,0,this);
        bufferg.drawImage(images[nextimage]
             ,nextimagexposition,nextimageyposition,this);
    //Now we draw the buffer image into the applet
        //screen.
        g.drawImage(bufferimage,0,0,this);
    }
}

There are some changes that must be done in the run() method too, now that we have changed the parameters:

public void run()
{
    Dimension d=size();
   int displacementx=0;
   int displacementy=0;
   int pathsize=0;
    currentimage=0;
    nextimage=1;
   while (true)
    {
     int directionx=(int) (Math.random()*3.0)-1;
     int directiony=(int) (Math.random()*3.0)-1;
      if (directionx==0 && directiony==0) directiony=1;
      if (d.width<d.height) pathsize=d.width;
      else pathsize=d.height;
        displacementx=directionx*d.width;
        displacementy=directiony*d.height;
        if (nextimage>maxitems-1) nextimage=0;
        for (int i=0; i<=pathsize; i++)
        {
            nextimagexposition=displacementx
                -directionx*(i*d.width)/pathsize;
            nextimageyposition=displacementy
                -directiony*(i*d.height)/pathsize;
            update(getGraphics());
        //Now "delay" is the delay in the loop.
          try {Thread.sleep(delay);}
          catch(InterruptedException e) {}
        }
         //"sleeptime" is used outside the loop.
         try {Thread.sleep(sleeptime);}
        catch(InterruptedException e) {}
        currentimage=nextimage;
        nextimage++;
       if (nextimage>maxitems-1) nextimage=0;
    }
}

We add a new delay outside the for loop and use the "sleeptime" variable there instead. Now the applet user can specify a delay before the next image starts rolling in. Now the applet should be completely finished. Do not forget to add the HTML parameter "delay" and set this to 20 before testing the applet. Set the parameter "sleeptime" to 1000 milliseconds or more. Click here to look at the applet. Is it not beautiful?

 

 

 

 

 


Next Page >>