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 >>
|