001:// パネルの端で跳ね返るボール
002:import java.awt.*;
003:import java.awt.event.*;
004:import javax.swing.*;
005:import java.util.*;
006:
007:class Ball {
008:   public int x, y;    // ボールの位置
009:   public int d;       // ボールの直径
010:   int dx, dy;         // ボールの移動速度
011:   public Color c;     // ボールの色
012:  
013:  Ball(int xx, int yy, int dd, int dxx, int dyy, Color cc) {    // Ball の生成
014:   x = xx;             // x座標
015:   y = yy;             // y座標
016:   d = dd;             // ボールの直径
017:   dx = dxx;           // x方向への移動ドット数
018:   dy = dyy;           // y方向への移動ドット数
019:   c = cc;             // ボールの色
020:  }
021:
022:  void move(int w1, int w2, int h1, int h2){                    // Ball の移動
023:   if(dy>0 && y+d > h2) dy = -dy;     // 下側の縁に接触、上向きに方向転換
024:   if(dy<0 && y   < h1) dy = -dy;     // 上側の縁に接触、下向きに方向転換
025:   y += dy;                           // 上下方向の移動
026:   if(dx>0 && x+d > w2) dx = -dx;     // 右側の縁に接触、左向きに方向転換
027:   if(dx<0 && x   < w1) dx = -dx;     // 左側の縁に接触、右向きに方向転換
028:   x += dx;                           // 左右方向の移動
029:  }
030: } // class Ball
031:
032:class BallPanel extends JPanel implements Runnable {            // BallPanel クラス
033:   final int psize=300;               // パネルの大きさ
034:   final int bwid = 5;                // パネルの縁の厚さ
035:   final Color[] cs = { Color.red, Color.orange, Color.yellow, Color.green,
036:                        Color.lightGray,
037:                        Color.cyan, Color.blue, Color.magenta, Color.pink, 
038:                        Color.gray };
039:   Thread th;                         // スレッド
040:   int w, h;                          // パネルの幅と高さ
041:   int num;                           // ボールの個数
042:   Ball[] b = new Ball[40];           // ボール
043:   Random ran;                        // 乱数の初期値
044:
045:   BallPanel(int i){                                  // BallPanel の生成
046:      if(i>40) num = 40;
047:      else     num = i;                               // ボールの個数
048:      setBackground(Color.white);                     // パネルの背景色
049:      setForeground(Color.red);                       //     描画色
050:      setBorder(BorderFactory.createLineBorder(Color.lightGray, bwid));
051:      setMinimumSize(new Dimension(psize, psize));    // パネルの最小サイズ
052:      setPreferredSize(new Dimension(psize, psize));  // パネルの希望サイズ
053:      w=psize;                                        // パネルの幅
054:      h=psize;                                        // パネルの高さ
055:
056:      ran = new Random();
057:      for(int j=0; j<num; j++) {                      // Ball の生成
058:         b[j] = new Ball(w/2, h/2, 25-4*(j % 5), myRandom(), myRandom(), cs[j % cs.length]);
059:      }
060:   }  // constructor BallPanel
061:
062:   public void paintComponent(Graphics g){            //
063:      super.paintComponent(g);                        // JPanel の描画
064:      for(int i=0; i<num; i++) {                      // すべてのボールについて
065:         b[i].move(bwid, w-bwid, bwid, h-bwid);       //   Ball の移動
066:         g.setColor(b[i].c);                          //   Ball の色を設定
067:         g.fillOval(b[i].x, b[i].y, b[i].d, b[i].d);  //   ボールの描画
068:      }
069:   }  // method paintComponent
070:
071:   public void run(){                                 // スレッドの実行
072:      while(true){                                    // 永久ループ
073:         try{     
074:            Thread.sleep(25);                         // 表示間隔
075:         }catch(InterruptedException e){}
076:         repaint();                                   // 描画
077:      }
078:   }  // method run
079:
080:   int myRandom(){                                    // 5〜-2, 2〜5 の乱数
081:     int n = ran.nextInt()%6;
082:     while(n>=-1 && n<=1) {
083:       n = ran.nextInt()%6;
084:     }
085:     return n;
086:   }  // method myRandom
087:
088:   public static void main(String args[]){
089:      int num;
090:      if(args.length < 1) num = 10;                         // デフォルトのボール個数10
091:      else                num = Integer.parseInt(args[0]);  // ボールの個数
092:      JFrame f = new JFrame("Ball Sample");                 // ウィンドウの生成
093:      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);     // クローズ時の処理の指定
094:
095:      BallPanel example = new BallPanel(num);               // 描画領域パネル
096:      f.getContentPane().add(example, BorderLayout.CENTER); // パネルをウィンドウに張付け
097:      f.pack();                                             // ウィンドウの大きさの調整
098:      f.setVisible(true);                                   // ウィンドウの表示
099:      Thread th = new Thread(example);                      // 描画表示パネルの表示スレッド
100:      th.start();                                           // 描画開始
101:   }  // method main
102:}  // class BallPanel