Skip to Page Content | Navigation for Module


Navigation for Module 10: Scripts/Java
Page 17 of 19

Double-Buffering in Java

When creating animated applets, it is important to double-buffer your animation to avoid flicker. Flicker can trigger seizures in certain individuals, and is caused because the human eye is fast enough to see the screen being drawn. If you are not prone to seizures, an example of an applet with bad flicker is provided. By double-buffering the animation, you can see that an applet with eliminated flicker appears to run much smoother.

There are several techniques for double-buffering, with the easiest already being built into Java. JApplets, by default, double-buffer, so extending it solves your problem (you should still avoid any blinking images in your Applet).

If, for some reason, you do not have the option of working with Swing components, you can still manually double-buffer. The algorithm behind double-buffering is:

You may be thinking that this would produce the same flickering example, but drawing an image is much quicker than drawing all of the individual lines, arcs, and whatever else.

The real nemesis here is the public void update ( ) method. This is an inherited method that clears the screen by filling a huge rectangle the same color as the background color, and then call paint.

Note: Update is almost always indirectly called before paint.

Code example approximating the inherited update method.

public void update (Graphics h) {
      Color c = this.getBackground();
      h.setColor(c);
      h.fillRect(0, 0, widthOfApplet, heightOfApplet);
      c = this.getForeground();
      h.setColor(c);
      paint (h);
}

Most of the flicker is caused by this clearing of the screen, so we can simply override (redefine) the method as follows:

public void update (Graphics h) {
      paint (h);
}

Realize now that it is necessary to 'clear the screen' in a similar fashion when drawing on the off-screen image.

Code example of the double-buffered version of a bouncing ball.

import java.awt.*;
 
// A simple Ball class
class Ball {
   double x, y, xVel, yVel, width, height;
   final static double GRAVITY = 0.1;
   final static int BALL_SIZE = 160;
 
   Ball(int x, int y, int width, int height) {
      this.width = width; this.height = height;
      this.x = x; this.y = y;
      xVel = 0.7; yVel = 0.5;
   }
   public void updateBall() {
      if ((x >= width-BALL_SIZE) || (x <= 0)) { xVel = -xVel; }
      if ((y >= height-BALL_SIZE) || (y <= 0)) { yVel = -yVel; }
      x += xVel;
      yVel += Ball.GRAVITY;
      y += yVel;
   }
}
 
public class BufferedBall extends java.applet.Applet implements Runnable {
   Thread t;
   Ball ball;
   int width, height;
   // Here is the offscreen image, and the related Graphics object
   Image image;
   Graphics offscreen;
 
   public void init() {
      width = Integer.parseInt(getParameter ("width"));
      height = Integer.parseInt(getParameter ("height"));
      ball = new Ball (100, 50, width, height);
      // Bring the offscreen image to life
      image = this.createImage (width, height);
      // Pull the Graphics object from it, so we can draw later
      offscreen = image.getGraphics ();
      this.setBackground (Color.white);
      t = new Thread (this);
      t.start();
   }
   // Override update so it *does not* clear the screen
   public void update (Graphics h) {
      paint (h);
   }
   // In paint, we draw on the screen image first
   public void paint (Graphics g) {
         offscreen.setColor (Color.black);
         offscreen.fillRect(0,0,width,height);
         offscreen.setColor (Color.white);
         offscreen.fillOval ((int)ball.x, (int)ball.y, ball.BALL_SIZE, ball.BALL_SIZE);
         // Now that image is ready to go, we can paint it using drawImage
         g.drawImage (image, 0, 0, width, height, this);
   }
   public void run() {
      while (true) {
         try {
 
            ball.updateBall();
            repaint();
            Thread.sleep(35);
         } catch (InterruptedException e) { }
      }
   }
}

The next page will discuss testing Java.

Top of Page arrow up
       Page 17


 
-- END OF PAGE