Here's the "challenge":
Below are two complete Java classes that, when run, paint a never-ending cascade of boxes down the screen ( Yay!

Your mission is to come up with some interesting modifications to it - or simply to use it as a model to come up with something completely different. Indulge your ego! Impress us!
...and, most importantly: Have Fun!
FallingBox class
Spoiler
import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Point; import java.util.Random; import javax.swing.JComponent; @SuppressWarnings("serial") public class FallingBox extends JComponent{ private Point xy; private Dimension widHt; private Color borderColor; private Color fillColor; private int speed; private boolean onScreen; private Container parent; private static Random rand = new Random(); private final static int MAX_SPEED = 5; public FallingBox(Container p){ parent = p; onScreen = false; } public void initialize(){ // this gives each box a unique set of characteristics speed = rand.nextInt(MAX_SPEED)+1; int colorShift; // this makes faster boxes brighter and slower boxes darker switch(speed){ case 1: colorShift = 0; break; case 2: colorShift = 20; break; case 3: colorShift = 40; break; case 4: colorShift = 60; break; case 5: colorShift = 80; break; default: colorShift = 100; break; } // define the box's dimensions widHt = new Dimension(rand.nextInt(200)+1,rand.nextInt(150)+1); // define the boxes starting position on the screen // -widHt.height for the y coordinate means the box starts just // offscreen a bit and then moves into frame xy = new Point(rand.nextInt(parent.getWidth()),-widHt.height); // define the box's outline color borderColor = Color.red; // define the box's fill color fillColor = new Color(rand.nextInt(100)+colorShift,0,0); // now that it exists, make it visible onScreen = true; } public Graphics paintBox(Graphics g){ g.setColor(fillColor); g.fillRect(xy.x, xy.y, widHt.width, widHt.height); g.setColor(borderColor); g.drawRect(xy.x, xy.y, widHt.width, widHt.height); if(onScreen) update(); else initialize(); return g; } public int getSpeed(){ return speed; } private void update(){ // the box isn't moving sideways - just down - so we only need // to increment its y value to move it down the screen xy.y += speed; // if the box has moved beyond the edge of the screen // indicate that it's offscreen (which will cause it to // be re-initialized to the top of the screen) if(xy.y > parent.getHeight()) onScreen = false; } public boolean isOnScreen(){ return onScreen; } public static int getMaxSpeed(){ return MAX_SPEED; } }
BoxDropper class
Spoiler
import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.Timer; @SuppressWarnings("serial") public class BoxDropper extends JPanel { private Timer animation; private BufferedImage offScrImg; private Graphics buffer; private final int NUM_BOXES = 500; private FallingBox[] arrayOfBoxes; private int currBox; private Container parent; public BoxDropper(Container p){ // we pass in the container so we can know what it's dimensions are parent = p; this.setSize(parent.getSize()); offScrImg = new BufferedImage(parent.getWidth(),parent.getHeight(),BufferedImage.TYPE_INT_RGB); buffer = offScrImg.createGraphics(); // every 16 milliseconds we're going to call go() animation = new Timer(16, new ActionListener(){ public void actionPerformed(ActionEvent e){ go(); } }); currBox = 0; // Now that the container is set up and we defined what we're going // to do each time animation timer fires an event, lets fill // the arrayOfBoxes array with boxes! this.getBoxes(); } private void go(){ // repaint is what makes this animated repaint(); // keep adding boxes until we reach the max // this is just so we don't start with all the boxes // ... I just think it looks better this way =) if(currBox < NUM_BOXES-1) currBox++; for(int i = 0; i < NUM_BOXES; i++){ if(!arrayOfBoxes[i].isOnScreen()){ arrayOfBoxes[i] = new FallingBox(this); arrayOfBoxes[i].initialize(); } } } public void getBoxes(){ arrayOfBoxes = new FallingBox[NUM_BOXES]; for(int i = 0; i < arrayOfBoxes.length; i++){ arrayOfBoxes[i] = new FallingBox(this); arrayOfBoxes[i].initialize(); } // once we have all the boxes, let's start things up! animation.start(); } public void paintComponent(Graphics g){ super.paintComponent(g); // call JPanels paintComponent method // paint the background black buffer.setColor(Color.black); buffer.fillRect(0, 0, this.getWidth(), this.getHeight()); // draw each FallingBox from the array of boxes // begin with the slow ones so they are in the back // end with the fast ones so they are in front for(int s = 1; s <= FallingBox.getMaxSpeed(); s++){ for(int i = 0; i <= currBox; i++){ if(arrayOfBoxes[i].getSpeed() == s) // paint the box to the graphics context buffer = arrayOfBoxes[i].paintBox(buffer); } } // this just writes the number of boxes being displayed in the // top left corner - it's optional buffer.setColor(Color.red); buffer.drawString(Integer.toString(currBox), 10, 10); // draw the off-screen image to the components graphics context // remember - buffer is the graphics context of offScrImg // that means we have to then paint offScrImg to the component g.drawImage(offScrImg, 0, 0, this); } public static void main(String[] args) { JFrame frame = new JFrame("Falling Boxes"); Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); frame.setSize(dim); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); BoxDropper bd = new BoxDropper(frame); frame.add(bd); frame.setVisible(true); } }