
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import java.util.Random;

public class BouncingBalls extends JFrame implements ActionListener     // main class
{
  MyCanvas gamefield;
  public ArrayList<Ball> balls;
  public Timer timer = null;

  public BouncingBalls()
  {
    setLayout(new BorderLayout());
    gamefield = new MyCanvas();
    add("Center",gamefield);
    balls = new ArrayList<Ball>();
    timer = new Timer(30, this);
    gamefield.addMouseListener(new MyMouseAdapter());
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
  }

  public void actionPerformed(ActionEvent e)
  {
    for (Ball b : this.balls)
    {
      b.move();
    }
    repaint();
  }

  class MyMouseAdapter extends MouseAdapter
  {
    public Color colors[] = {Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA};
    public int numColors = colors.length;
    Random ran = new Random();
    public void mousePressed(MouseEvent e)
    {
      Color myColor = colors[ran.nextInt(numColors)];
      balls.add(new Ball(gamefield,e.getX(),e.getY(),myColor));
    }
  }

  class MyCanvas extends JPanel
  {
    MyCanvas()
    {
      setBackground(Color.white);
      setForeground(Color.black);
    }

    public void paintComponent(Graphics g)
    {
      super.paintComponent(g);
      for (Ball b : balls)
      {
        b.draw(g);
      }                    
    }

    public Dimension getMinimumSize()
    {
      return new Dimension(500,500);
    }

    public Dimension getPreferredSize()
    {
      return getMinimumSize();
    }
  }

  public void getStarted()
  {
    balls.add(new Ball(gamefield,200,50, Color.BLACK));
    timer.start();  
  }

  public static void main(String args[])
  {
    BouncingBalls test = new BouncingBalls();
    test.setVisible(true);
    test.pack(); //JFrqame method to set all compponenets to PreferredSize
    test.getStarted();
  }        
}

class Ball
{
  JPanel display;
  int xPos,yPos;
  int dx = 5;         // Steps into direction x or y
  int dy = 5;
  Color myColor;

  Ball(JPanel c,int x,int y, Color col)  //constructor
  {
    display = c;
    xPos = x;
    yPos = y;
    this.myColor = col;
  }

  void draw(Graphics g)
  {
    g.setColor(this.myColor);
    g.fillOval(xPos, yPos, 20, 20);
  }

  void move()
  {
    int xNew, yNew;
    Dimension m;

    m = display.getSize();
    xNew = xPos + dx;
    yNew = yPos + dy;

        // Collision detection with borders, "bouncing off":

    if(xNew < 0)
    {
      xNew = 0;
      dx = -dx;
    }

    if(xNew + 20 >= m.width)
    {
      xNew = m.width - 20;
      dx = -dx;
    }

    if(yNew < 0)
    {
      yNew = 0;
      dy = -dy;      
    }

    if(yNew + 20 >= m.height)
    {
      yNew = m.height - 20;
      dy = -dy;
    }

    xPos = xNew;
    yPos = yNew;
  }
}

