ShipSimulation.java Illustrates the basic approach of multithreaded graphics whereas a thread adjusts parameters affecting the appearance of the graphics and then calls repaint to schedule an update of the display.
import java.applet.Applet;
import java.awt.*;
public class ShipSimulation extends Applet implements Runnable {
...
public void run() {
Ship s;
for(int i=0; i
* 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) {
// Erase any circles from previous run.
getGraphics().clearRect(0, 0, getSize().width,
getSize().height);
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));
} else if (event.getSource() == stopButton) {
if (animationThread != null) {
animationThread = null;
circles.removeAllElements();
}
}
repaint();
}
/** Each time around the loop, call paint and then take a
* short pause. The paint method will move the circles and
* draw them.
*/
public void run() {
Thread myThread = Thread.currentThread();
// Really while animationThread not null
while(animationThread==myThread) {
repaint();
pause(100);
}
}
/** Skip the usual screen-clearing step of update so that
* there is no flicker between each drawing step.
*/
public void update(Graphics g) {
paint(g);
}
/** Erase each circle's old position, move it, then draw it
* in new location.
*/
public void paint(Graphics g) {
MovingCircle circle;
for(int i=0; i windowWidth) && (deltaX > 0)) {
setDeltaX(-deltaX);
}
if ((y -radius < 0) && (deltaY < 0)) {
setDeltaY(-deltaY);
} else if((y + radius > windowHeight) && (deltaY > 0)) {
setDeltaY(-deltaY);
}
}
public int getDeltaX() {
return(deltaX);
}
public void setDeltaX(int deltaX) {
this.deltaX = deltaX;
}
public int getDeltaY() {
return(deltaY);
}
public void setDeltaY(int deltaY) {
this.deltaY = deltaY;
}
}
*//
SimpleCircle.java A class to store the x, y, and radius of a circle. Also, provides a draw method to paint the circle on the graphics object.
import java.awt.*;
/** A class to store an x, y, and radius, plus a draw method.
*
*/
public class SimpleCircle {
private int x, y, radius;
public SimpleCircle(int x, int y, int radius) {
setX(x);
setY(y);
setRadius(radius);
}
/** Given a Graphics, draw the SimpleCircle
* centered around its current position.
*/
public void draw(Graphics g) {
g.fillOval(x - radius, y - radius,
radius * 2, radius * 2);
}
public int getX() { return(x); }
public void setX(int x) { this.x = x; }
public int getY() { return(y); }
public void setY(int y) { this.y = y; }
public int getRadius() { return(radius); }
public void setRadius(int radius) {
this.radius = radius;
}
}
*//
DoubleBufferBounce.java An enhancement to the previous applet containing bouncing circles. In this case, double buffering is used to improve the animation; all incremental updating is done in an off-screen image and then the image is drawn to the screen.
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 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= NUMIMAGES) {
index = 0;
}
parent.repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break; // Break while loop.
}
}
}
}
*//
TimedAnimation.java An applet that demonstrates animation of an image by using a Timer. Note that Timer is located in the javax.swing package.
import java.awt.*;
import javax.swing.*;
/** An example of performing animation through Swing timers.
* Two timed Dukes are created with different timer periods.
*
*/
public class TimedAnimation extends JApplet {
private static final int NUMDUKES = 2;
private TimedDuke[] dukes;
private int i, index;
public void init() {
dukes = new TimedDuke[NUMDUKES];
setBackground(Color.white);
dukes[0] = new TimedDuke( 1, 100, this);
dukes[1] = new TimedDuke(-1, 500, this);
}
// Start each Duke timer.
public void start() {
for (int i=0; i= NUMIMAGES) {
index = 0;
}
parent.repaint();
}
// Public service to start the timer.
public void startTimer() {
timer.start();
}
// Public service to stop the timer.
public void stopTimer() {
timer.stop();
}
}
**//
