This is an example of a multithreaded Java applet, with source. Click in the applet area below to start a ball bouncing. Each time you click the mouse below, it starts another thread bouncing another ball, whose color, diameter, velocity, and direction are random.
I wrote this for a class, but because it's kind of a fun, I thought people might appreciate seeing how to write such an applet.
Click here to go back to my main page.
Here's the source. When you figure out how to make a successful
IPO based on this code :-),
feel free to throw a few thousand shares my way.
// This applet waits for the user to click the mouse. When the mouse is clicked, // it starts a thread that bounces a ball around the inside edges of the applet's // displayable area. Each time you click the mouse, the applet starts a new // thread that randomly picks the color of the ball, and starts bouncing it. // // How does it do this? Well, an example would have been nice. But it looks // like the proper way to do this is to define a JPanel that contains the image // of bouncing balls. Then, we pick a starting point for the ball (picked at // random). Then we randomly pick a velocity (x and y change). Then the // JPanel's paintComponent paints the rectangle its background color and // draws the ball. // // For the first ball this is easy; you just draw the ball on the background. The // second time you redraw the background, move the starting point by velocity, // and draw the ball again. (If the starting point plus velocity puts the ball // outside the bounds of the JPanel, however, you have to reflect the ball // back again. How am I going to do this? I don't know yet.) import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; import java.io.*; import java.net.*; public class PongOnSpeed extends JApplet implements MouseListener, Runnable { // Maximum speed the ball can move. private final int MAX_SPEED = 200; // Dimensions of the panel on which we bounce the balls. Dimension panelDimensions; // How many balls are we juggling simultaneously? final private static int MAX_BALL_COUNT = 40; int ballCount; private Thread[] ballThreads = new Thread[MAX_BALL_COUNT]; Graphics g; JPanel panel; // What direction and speed does the ball move? Dimension[] vector = new Dimension[MAX_BALL_COUNT]; // Where does the ball get displayed next? Dimension[] next = new Dimension[MAX_BALL_COUNT]; // What color is the ball? private Color[] color = new Color[MAX_BALL_COUNT]; // What is the name of this thread? private String[] name = new String[MAX_BALL_COUNT]; // Diameter of the ball? private int[] diameter = new int[MAX_BALL_COUNT]; public void init () { ballCount = 0; Container contentPane = getContentPane(); // Add a JPanel to the contentPane of the applet. JPanel panel = new JPanel(); panel.setOpaque(true); contentPane.add(panel); // Get the dimensions so that we know where to start bouncing // balls when they hit the edges. panelDimensions = getSize(); // We start with zero balls in the air. ballCount = 0; // This lets us known when the user has hit the mouse button. addMouseListener(this); } public void start () { for(int i = 0; i < ballThreads.length; i++) if(ballThreads[i] != null) ballThreads[i].start(); } public void stop () { // Kill all the threads currently running. for(int i = 0; i < ballThreads.length; i++) ballThreads[i] = null; } public void mousePressed (MouseEvent e) { // Each time we get a mouse button pressed event, we need to // start a ball thread to create a ball and start it running. if(ballCount < MAX_BALL_COUNT) { int width = (int)panelDimensions.getWidth(); int height = (int)panelDimensions.getHeight(); // Calculate a random direction and speed. vector[ballCount] = new Dimension((int)((Math.random() * MAX_SPEED) - (MAX_SPEED/2)), (int)((Math.random() * MAX_SPEED) - (MAX_SPEED/2))); color[ballCount] = randomColor(); // Select a random location for the ball. next[ballCount] = new Dimension((int)(Math.random() * panelDimensions.getWidth()), (int)(Math.random() * panelDimensions.getHeight())); // Pick a random diameter. diameter[ballCount] = Math.max(20, (int)(Math.random() * 40)); ballThreads[ballCount] = new Thread(this); ballThreads[ballCount].start(); ballCount++; } } public Color randomColor () { return(new Color((int)(Math.max(10, Math.random()*255)), (int)(Math.max(10, Math.random()*255)), (int)(Math.max(10, Math.random()*255)))); } public void run () { // Find out which is the current Thread we are running. Thread currentThread = Thread.currentThread(); // Get the index number of this thread. int index = getIndex(currentThread); while(ballThreads[index] == currentThread) { repaint(); try { Thread.sleep(1000); } catch (InterruptedException e) {}; } } private int getIndex (Thread current) { for(int i = 0; i < ballThreads.length; i++) if(current == ballThreads[i]) return(i); return(-1); } public void mouseClicked (MouseEvent e) { } public void mouseReleased (MouseEvent e) { } public void mouseExited (MouseEvent e) { } public void mouseEntered (MouseEvent e) { } public void paint (Graphics g) { // Find out which is the current Thread we are running. for(int index = 0; index < ballThreads.length; index++) { if(ballThreads[index] != null) { if(index == 0) { // Set the background color. g.setColor(Color.black); g.fillRect(0, 0, (int)panelDimensions.getWidth(), (int)panelDimensions.getHeight()); } g.setColor(color[index]); // Draw the ball at the next location. g.fillOval((int)next[index].getWidth(), (int)next[index].getHeight(), diameter[index], diameter[index]); repaint(); // Now move the ball. // See if the ball's next location is outside the boundaries of the JPanel or not. int nextX = (int)(next[index].getWidth() + vector[index].getWidth()); int vectorX = (int)vector[index].getWidth(); // See if the X coordinate moves us off the visible area to the left. // If so, we have to bounce back in by inverting the sign of the // X part of vector. if((nextX < 0) || ((nextX + diameter[index]) > panelDimensions.getWidth())) { vectorX = (int)(-vector[index].getWidth()); nextX = (int)next[index].getWidth() + vectorX; } // See if the Y coordinate moves us off the visible area to the left. // If so, we have to bounce back in by inverting the sign of the // Y part of vector. int nextY = (int)(next[index].getHeight() + vector[index].getHeight()); int vectorY = (int)vector[index].getHeight(); if((nextY < 0) || ((nextY + diameter[index]) > panelDimensions.getHeight())) { vectorY = (int)(-vector[index].getHeight()); nextY = (int)next[index].getHeight() + vectorY; } // Save the new values for direction. vector[index] = new Dimension(vectorX, vectorY); // New position for the ball. next[index] = new Dimension(nextX, nextY); try { Thread.sleep(100/ballCount); } catch (InterruptedException e) {}; } } } }Click here to go back to my main page.