import java.applet.Applet; import java.awt.*; import java.awt.event.*; import java.util.Vector; /** Bounce circles around on the screen, using * double buffering for speed and to avoid problems * with overlapping circles. Overrides update to * to avoid flicker problems. */ public class DoubleBufferBounce extends Applet implements Runnable, ActionListener { private Vector circles; private int width, height; private Image offScreenImage; private Graphics offScreenGraphics; private Button startButton, stopButton; private Thread animationThread = null; public void init() { setBackground(Color.white); width = getSize().width; height = getSize().height; offScreenImage = createImage(width, height); offScreenGraphics = offScreenImage.getGraphics(); // Automatic in some systems, not in others offScreenGraphics.setColor(Color.black); circles = new Vector(); startButton = new Button("Start a circle"); startButton.addActionListener(this); add(startButton); stopButton = new Button("Stop all circles"); stopButton.addActionListener(this); add(stopButton); } //---------------------------------------------------- /** When the "start" button is pressed, start the * animation thread if it is not already started. * Either way, add a circle to the Vector of * circles that are being bounced. * * When the "stop" button is pressed, stop * the thread and clear the Vector of circles. */ public void actionPerformed(ActionEvent event) { if (event.getSource() == startButton) { if (circles.size() == 0) { animationThread = new Thread(this); animationThread.start(); } int radius = 25; int x = radius + randomInt(width - 2 * radius); int y = radius + randomInt(height - 2 * radius); int deltaX = 1 + randomInt(10); int deltaY = 1 + randomInt(10); circles.addElement(new MovingCircle(x, y, radius, deltaX, deltaY)); repaint(); } else if (event.getSource() == stopButton) { if (animationThread != null) { animationThread = null; circles.removeAllElements(); } } } //---------------------------------------------------- /** Each time around the loop, move each circle * based on its current position and deltaX/deltaY * values. These values reverse when the circles * reach the edge of the window. */ public void run() { MovingCircle circle; Thread myThread = Thread.currentThread(); // Really while animationThread not null while(animationThread==myThread) { for(int j=0; j