import java.applet.*; import java.awt.*; /* I know a ball isn't a Rectangle, * but Rectangle provides alot of useful methods/properties :) */ class Ball extends Rectangle { public int xdir,ydir; public Color color; public Ball(int size) { xdir = 0; ydir = 0; this.width = size; this.height = size; color = Color.black; } public void collide(Ball b) { this.xdir*=-1; this.ydir*=-1; b.xdir*=-1; b.ydir*=-1; } public void check(Dimension d) { Rectangle r = new Rectangle(d.width,d.height); if (!r.contains(this)) { if (this.x < 0) this.x = 0; else if (this.x > r.width-this.width) this.x = r.width-this.width; if (this.y < 0) this.y = 0; else if (this.y > r.height-this.height) this.y = r.height-this.height; if (this.x == 0 || this.x == r.width-this.width) xdir*=-1; if (this.y == 0 || this.y == r.height-this.height) ydir*=-1; } } public void move() { this.translate(xdir,ydir); } public void paint(Graphics g) { g.setColor(color); g.fillOval(this.x,this.y,this.width,this.height); } } public class Bouncy extends Applet implements Runnable { Ball b[]; // ball for.. bouncing Dimension d; int w,h,collide; Image buffer; public void init() { d = getSize(); w = d.width; h = d.height; collide = 0; buffer = createImage(w,h); // now we have to make the balls with random properties Color c[] = new Color[] {Color.red,Color.green,Color.blue,Color.cyan,Color.magenta, Color.black,Color.pink,Color.yellow}; b = new Ball[rand(9)+1]; // at MOST 10 balls for (int j = 0;j < b.length;j++) { b[j] = new Ball(rand(20)+10); // diameter is at MOST 30 b[j].x = rand(w-b[j].width); // random x b[j].y = rand(h-b[j].height); // random y b[j].xdir = rand(3)+2; // random x direction b[j].ydir = rand(3)+2; // random y direction b[j].color = c[rand(c.length-1)]; // random color } new Thread(this).start(); } protected int rand(int r) { return (int)Math.round(Math.random()*r); } public void run() { // if you don't know about threads, // this will confuse the snot out of you. // so read up on threads!! while (true) { int j,n; // now we update each ball position for (j = 0;j < b.length;j++) { // make sure the ball is in the applet b[j].check(d); // move the ball b[j].move(); // check for collisions... for (n = 0;n < b.length;n++) { if (n != j) { // no need to check current ball if (b[j].intersects(b[n])) { collide++; b[j].collide(b[n]); // adjust x/y directions // move both balls b[j].move(); b[n].move(); } } } } Graphics g = getGraphics(); if (g != null) paint(g); // attempt active rendering else repaint(); // passive will work if active doesn't try { Thread.sleep(10); } catch (InterruptedException e) { break; } } } public void paint(Graphics g) { Graphics gfx = buffer.getGraphics(); gfx.setColor(Color.white); gfx.fillRect(0,0,w,h); for (int j = 0;j < b.length;j++) { b[j].paint(gfx); } gfx.setColor(Color.black); FontMetrics f = gfx.getFontMetrics(); gfx.drawString("Balls: "+b.length,10,h-f.getAscent()); String s = "Collisions: "+collide; gfx.drawString(s,w-(f.stringWidth(s)+10),h-f.getAscent()); gfx.drawRect(0,0,w-1,h-1); g.drawImage(buffer,0,0,null); } public void update(Graphics g) { paint(g); } }