/** [NoBuffer.java] Copyright(c) 2000-2004 WakuWaku. */
import java.awt.*;
import java.applet.Applet;
import java.util.Random;

public class NoBuffer extends Applet implements Runnable
{
        final static int MAX = 10, SZ = 38;       //左からボールの最大表示数, ボールのサイズ
        final static Color[] COL = new Color[SZ];
        Graphics g;   //画面描画のグラフィックコンテキスト
        Thread thread = null;
        int[] x, y, m;        //左からボールのX, Y座標, 移動量
        int w, h;

        static
        {
                for(int i = 0; i < SZ; i++)
                {
                        int c = 255 - i * 255 / (SZ - 1);
                        COL[i] = new Color(c, c, 255 - c);
                }
        }

        public void init()  //アプレットの初期化時呼び出される
        {
                Dimension d = getSize();      //アプレットサイズ取得
                this.w = d.width;
                this.h = d.height;
                this.g = getGraphics();       //画面描画用のグラフィックコンテキストの取得
        }

        private void drawBackImage(Graphics g)    //背景イメージ描画メソッド
        {
                Random rand = new Random(123);    //種を固定
                for(int i = 0; i < h; i++)
                {
                        g.setColor(new Color(0, 0, (int)(rand.nextFloat() * 255)));
                        g.drawLine(0, i, w, i);
                }
                g.setFont(new Font("Arial", Font.ITALIC, 48));
                g.setColor(Color.gray);
                g.drawString("No Buffer", 60, h / 2 + 16);
        }

        public void start() //アプレットが表示されると呼び出される
        {
                if(thread == null)
                {
                        thread = new Thread(this);        //スレッドの生成
                        thread.start(); //スレッドを開始させ、runメソッドを呼び出す
                }
        }

        public void run()   //メインルーチン
        {
                //ボール初期化
                Ball[] ball = new Ball[MAX];
                for(int i = 0; i < MAX; i++)
                        ball[i] = new Ball(-99, 0, 0);

                int wait = 0;
                Random rand = new Random(456);    //種を固定

                while(thread != null)
                {
                        wait--;
                        drawBackImage(g);

                        for(int i = 0; i < MAX; i++)
                        {
                                Ball target = ball[i];
                                if(target.x == -99 && wait < 0)
                                {
                                        target.x = -SZ;
                                        target.y = (int)(rand.nextFloat() * (h - SZ));
                                        target.move = (int)(rand.nextFloat() * 7) + 2;
                                        wait = (int)(rand.nextFloat() * 20) + 4;
                                }else
                                {
                                        target.move();  //ボールを移動
                                        if(target.x > w)
                                                target.x =- 99;
                                        for(int r = SZ - 1; r >= 0; r--)
                                        {
                                                g.setColor(COL[r]);     //ボールの色設定
                                                g.fillOval(target.x + (SZ - r) / 2,
                                                        target.y + (SZ - r) / 2, r, r); //ボールを画面に描画
                                        }
                                }
                        }
                        try
                        {
                                Thread.sleep(50);     //0.05秒間スリープ。これを忘れるとハングアップする
                        }catch(InterruptedException e) {}
                }
        }

        public void stop()  //アプレットが画面から消えると呼び出される
        {
                if(thread != null)
                        thread = null;
        }
}

//一つのボールを表すクラス
class Ball
{
        int x;        //x座標
        int y;        //y座標
        int move;     //x方向への移動量

        public Ball(int x, int y, int move)
        {
                this.x = x;
                this.y = y;
                this.move = move;
        }

        //ボールを移動
        public void move()
        {
                this.x += this.move;
        }
}