Multiple Falling Balls


 

 

Complete Source Code

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;


public class MultipleFalling {


   private static MultipleListener listener;
   private static JFrame myFrame;
   private static MultiplePanel myPanel;
   private static Ball[] ball;
   private static int index = -1;

   public static class MultiplePanel extends JPanel {

      public void drawRules(Graphics g, int panelHeight) {

         Font plainFont = new Font("TimesRoman",Font.PLAIN,14);
         Font boldFont = new Font("TimesRoman",Font.BOLD,14);

         g.setColor(Color.BLACK);
         g.setFont(boldFont);
         g.drawString("To Create a ball:",5,panelHeight-40);
         g.setFont(plainFont);
         g.drawString("Right-Click anywhere on the panel.",120,panelHeight-40);
         g.setFont(boldFont);
         g.drawString("To Start/Stop a ball:",5,panelHeight-25);
         g.setFont(plainFont);
         g.drawString("Left-Click on the ball.",140,panelHeight-25);
         g.setFont(boldFont);
         g.drawString("To Destroy a ball:",5,panelHeight-10);
         g.setFont(plainFont);
         g.drawString("CTRL + Left-Click on the ball while it is not moving.",125,panelHeight-10);

      }

      public void paintComponent(Graphics g) {

         super.paintComponent(g);

         for (int i = 0; i <= index; i++) ball[i].draw(g);

         g.setColor(Color.LIGHT_GRAY);
         g.fillRect(0,getHeight()-60,getWidth(),60);
         drawRules(g,getHeight());

         if (index + 1 < 10) g.setColor(Color.BLACK);
         else g.setColor(Color.RED);

         g.setFont(new Font("Courier",Font.BOLD,30));
         g.drawString(Integer.toString(index+1),getWidth()-40,getHeight()-20);

      }

   }

   public static class MultipleListener implements MouseListener, ActionListener {

      public void mousePressed(MouseEvent e) {

         if (!e.isMetaDown() && !e.isControlDown() && e.getY() < myPanel.getHeight()-60) {

            for (int i = index; i >= 0; i--) {

               if (e.getX() > ball[i].x && e.getX() < ball[i].x+50 &&
               e.getY() > ball[i].y && e.getY() < ball[i].y+50) {

                  if (ball[i].falling) ball[i].freeze();
                  else ball[i].fall();

                  break;

               }

            }

         }

         if (e.isMetaDown() && index < ball.length-1 && e.getY() < myPanel.getHeight()-60) {

            index++;
            ball[index] = new Ball(e.getX(),e.getY(),myPanel.getWidth(),myPanel.getHeight());
            myPanel.repaint();

         }

         if (!e.isMetaDown() && e.isControlDown() && e.getY() < myPanel.getHeight()-60) {

            for (int i = index; i >= 0; i--) {

               if (e.getX() > ball[i].x && e.getX() < ball[i].x+50 &&
                   e.getY() > ball[i].y && e.getY() < ball[i].y+50) {

                  if (!ball[i].falling) {

                     ball[i] = null;
                     for (int k = i; k < index; k++) ball[k] = ball[k+1];
                     ball[index] = null;
                     index--;

                  }

                  break;

               }

            }

            myPanel.repaint();

         }

      }

      public void mouseReleased(MouseEvent e) {}
      public void mouseClicked(MouseEvent e) {}
      public void mouseEntered(MouseEvent e) {}
      public void mouseExited(MouseEvent e) {}

      public void actionPerformed(ActionEvent e) {

         for (int i = 0; i <= index; i++) {

            if (ball[i].falling) ball[i].motion();

         }

         myPanel.repaint();

      }

   }

   public static class Ball {

      Timer timer;
      Color color;
      int x, y, r, g, b, panelWidth, panelHeight;
      boolean falling;

      public Ball(int x, int y, int panelWidth, int panelHeight) {

         timer = new Timer(100, listener);
         r = (int)(255*Math.random());
         g = (int)(255*Math.random());
         b = (int)(255*Math.random());
         color = new Color(r,g,b);
         this.x = x;
         this.y = y;
         this.panelWidth = panelWidth;
         this.panelHeight = panelHeight;
         falling = false;

      }

      public void motion() {

         if (y < panelHeight-60) y++;
         else y = -50;

      }

      public void draw(Graphics g) {

         g.setColor(color);
         g.fillOval(x,y,50,50);
         g.setColor(Color.BLACK);
         g.drawString(Integer.toString(y),x+17,y+30);

      }

      public void freeze() {

         timer.stop();
         falling = false;

      }

      public void fall() {

         timer.start();
         falling = true;

      }

   }

   public static void main(String[] args) {

      listener = new MultipleListener();
      myPanel = new MultiplePanel();
      myFrame = new JFrame("Multiple Falling Balls");
      ball = new Ball[10];

      myPanel.setBackground(Color.WHITE);
      myPanel.addMouseListener(listener);

      myFrame.add(myPanel);
      myFrame.setSize(516,538);
      myFrame.setLocation(100,100);
      myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      myFrame.setVisible(true);

   }


}