Here's a really really simple runnable demo that has the basic parts: the Sprite class is the simulation of different things (squares, circles) moving about. This demos the use of a timer to run the simulation in real time, and the display technique I described above to show the sprites moving. It's totally simple, but it shows the key components and how they fit together. It's deliberately short on comments so you'll have to study it to understand it before you apply it's ideas to your own problem.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.ArrayList;
public class Animation2 extends JPanel implements ActionListener {
// Animation demo showing use of an abstract Sprite class to
// model basic behaviour for multiple moving objects.
// Sprites have two mandatory methods - update and draw
Animation2(int width, int height) {
setPreferredSize(new Dimension(width, height));
new Timer(50, this).start();
}
@Override
public void actionPerformed(ActionEvent arg0) {
// called by Timer every 50 milliseconds
for (SimpleSprite s : SimpleSprite.sprites)
s.update(); // update positions of all sprites
repaint();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g); // ensure background etc is painted
Graphics2D g2d = (Graphics2D) g;
for (SimpleSprite s : SimpleSprite.sprites)
s.draw(g2d);// draw all sprites at latest positions
}
public static void main(String[] args) {
// create and display the animation in a JFrame
final JFrame frame = new JFrame("Animation 2 (close window to exit)");
Animation2 animationPanel = new Animation2(600, 500);
frame.add(animationPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
// add some sprites...
new Square(0, 0, 3, 2, 40);
new Ball(500, 0, -3, 3, 20);
new Ball(0, 500, 2, -5, 30);
}
}
abstract class SimpleSprite {
// basic x,y movement,keeps a master list of Sprites
public static final ArrayList<SimpleSprite> sprites = new ArrayList<SimpleSprite>();
float x, y, dx, dy; // position and velocity (pixels/TIMER_MSEC)
public SimpleSprite(float x, float y, float dx, float dy) {
// initial position and velocity
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
sprites.add(this);
}
public void update() { // update position and velocity every n milliSec
// default - just move at constant velocity
x += dx; // velocity in x direction
y += dy; // velocity in y direction
}
abstract public void draw(Graphics2D g2d);
// just draw at current position, no updating.
}
class Ball extends SimpleSprite {
int diameter;
public Ball(float x, float y, float dx, float dy, int diameter) {
super(x, y, dx, dy);
this.diameter = diameter;
}
// no need to override update, constant velocity is OK
@Override
public void draw(Graphics2D g2d) {
g2d.setColor(Color.blue);
g2d.fillOval((int) x, (int) y, diameter, diameter);
}
}
class Square extends SimpleSprite {
int side;
public Square(float x, float y, float dx, float dy, int side) {
super(x, y, dx, dy);
this.side = side;
}
@Override
public void draw(Graphics2D g2d) {
g2d.setColor(Color.red);
g2d.fillRect((int) x, (int) y, side, side);
}
}