/**********************************************************************************
 *                                                                                *
 *                     ジャンピング文字Javaアプレット                            *
 *                            ( Bounder.java )                                    *
 *                                                                                *
 *                                                        Author : Seiichi Inoue  *
 **********************************************************************************/

/****************** << インポートパッケージクラス定義 >> ********************/
import java.applet.Applet;           /* Appletパッケージ                       */
import java.awt.*;                   /* Abstract Windowing Toolkitパッケージの全て*/

/************************ << 自分のクラス定義 >> ****************************/
//   クラス名称   : Bounder
//   アクセス制御  : public(どのクラスからもアクセス可能)
//   継承クラス   : Applet
//   引継クラス   : Runnable(Threadを使用可能にする)
public  class  Bounder  extends Applet implements Runnable {

/************************ << クラス属性の定義 >> ****************************/
    Dimension   d;                              /* 表示領域            */
    String      s[];                            /* 文字配列領域          */
    String      param;                          /* パラメータ取込エリア      */
    Thread      kicker=null;                    /* スレッド制御(初期値:停止)  */
    int         xScroll;                        /* スクロール位置         */
    Font        font;                           /* フォント            */
    int         fontsize;                       /* フォントサイズ         */
    String      fontname;                       /* 文字フォントパラメータ情報   */
    int         strWidth;                       /* 文字列幅            */
    int         maxText;                        /* 文字ブロック数         */
    int         curTextCount = 0;               /* 現在の文字ブロック       */
    boolean     randomcolor;                    /* 文字色指定情報         */
    int         red,blue,green;                 /* 文字色             */
    Color       color;                          /* 文字色             */
    int         backred,backblue,backgreen;     /* 背景色             */
    Color       backcolor;                      /* 背景色             */
    int         speed;                          /* 表示速度            */
    Image       offs;                           /* オフスクリーン         */
    Graphics    grf;                            /* 描画領域            */
    int         bound_y;                        /* バウンドの高さ         */
    double      time;                           /* 経過時間(64ビット長データ)   */
    int         start_speed;                    /* 入力初速度           */
    int         start_H;                        /* 初速度             */
    int         f_Descent;                      /* 文字の参照点からの下方距離   */

/******************** << クラスのメッソード指定(実行手順) >> **************/

/*********** 初期化(init)メッソード **********/
    public void init() {
        d = size();                             /* 表示画面サイズ情報を設定     */
        xScroll = d.width;                      /* 表示開始位置を設定        */

        offs = createImage(d.width,d.height);   /* オフスクリーンエリア作成     */
        grf  = offs.getGraphics();              /* Graphicsオブジェクト取出     */

        param = getParameter("speed");          /* 入力パラメータ"speed"取込    */
        speed = (param != null)?                /* 入力判定(無指定時は1)     */
            Integer.parseInt(param): 1;
        if(speed < 1 && speed > 5) {            /* 入力異常判定( <1? , >5? )    */
            speed = 1;                          /* 異常の時は1を設定       */
        }

        param = getParameter("maxText");        /* テキストブロック数取込     */
        maxText = (param != null)?              /* 入力判定(無指定時は1)    */
            Integer.parseInt(param): 1;
        s = new String[maxText];                /* 文字配列の作成         */

        param = getParameter("fontsize");       /* フォントサイズ指定取込     */
        fontsize = (param != null)?             /* 入力判定(無指定時は30)     */
            Integer.parseInt(param): 30;
        param = getParameter("font");           /* フォント種類パラメータ取込   */
        fontname = (param != null)?             /* 入力判定(無指定時:Dialog)   */
            param: "Dialog";

        param = getParameter("randomcolor");    /* 文字色指定スイッチ取込     */
        param = (param != null)?                /* 入力判定(無指定時:true)    */
            param: "true";
        if ( "true".equals (param) )            /* ランダム指定?         */
            randomcolor = true;                 /* YES:ランダム(正)設定     */
        else
            randomcolor = false;                /* NO :ランダム(偽)設定     */
        if ( randomcolor ) {}                   /* ランダム指定?         */
        else {                                  /* NO:パラメータ指定       */
            param = getParameter("red");        /* 文字赤色の指定を取込      */
            red = (param != null)?              /* 無指定時 0          */
                Integer.parseInt(param): 0;
            param = getParameter("green");      /* 文字緑色の指定を取込      */
            green = (param != null)?            /* 無指定時 0          */
                Integer.parseInt(param): 0;
            param = getParameter("blue");       /* 文字青色の指定を取込      */
            blue = (param != null)?             /* 無指定時 0          */
                Integer.parseInt(param): 0;
            color = new Color(red,green,blue);  /* 文字表示色を設定        */
        }

        param = getParameter("backred");        /* 背景赤色指定を取込       */
        backred = (param != null)?              /* 入力判定(無指定時は255)    */
            Integer.parseInt(param): 255;
        param = getParameter("backgreen");      /* 背景緑色指定を取込       */
        backgreen = (param != null)?            /* 入力判定(無指定時は255)    */
            Integer.parseInt(param): 255;
        param = getParameter("backblue");       /* 背景青色指定を取込       */
        backblue = (param != null)?             /* 入力判定(無指定時は255)    */
            Integer.parseInt(param): 255;
        backcolor = new Color(backred,backgreen,backblue); /* 背景色設定     */

        param = getParameter("start_speed");    /* 初速度指定取込         */
        start_speed = (param != null)?          /* 入力判定(無指定時は40)     */
            Integer.parseInt(param): 40;

        param = getParameter("fonttype");       /* フォントタイプパラメータ取込  */
        if ( "BOLD".equals (param) )                            /* BOLD ?     */
            font = new Font(fontname,Font.BOLD,fontsize);       /* BOLD設定    */
        else {
            if ( "ITALIC".equals (param) )                      /* ITALIC ?    */
                font = new Font(fontname,Font.ITALIC,fontsize); /* ITALIC設定   */
            else
                font = new Font(fontname,Font.PLAIN,fontsize);  /* PLAIN その他  */
        }
        f_Descent  = (getFontMetrics(font)).getDescent(); /* 文字のディセンダ取得 */

        int i=0;                                /* ループカウント初期化      */
        do {                                    /* DOループ (文字配列作成)   */
            param = getParameter("text" + (i+1)); /* i+1番目のテキスト取込    */
            if(param != null) {                 /* テキスト有無判定        */
                s[i] = new String(param);       /* 有(テキストを配列に設定)    */
            } else {                            /* 無               */
                if( i==0 ) {                    /* テキストが1つも無い?     */
                    s[i] = "Text Erorr";        /* テキスト指定異常を設定     */
                }
                    maxText = i + 1;            /* テキストブロック数を設定    */
                }
        } while(param != null && ++i != maxText); /* DOループ終了判定      */

    }                                           /* 初期化メソッド終了       */

/*********** 繰り返し(run)メソッド ***********/
    public void run() {
        Thread.currentThread().setPriority(Thread.NORM_PRIORITY-3);
        while (kicker != null) {                /* kickerがnullになるまで繰返   */
            repaint();                          /* 描画              */
            try {                               /* 割り込み確認          */
                Thread.sleep( 20 );             /* 待ち時間を20ミリ秒設定    */
            } catch (InterruptedException e) {} /* 割り込み処理          */
        }
        kicker = null;
    }                                           /* 実行メソッド終了        */


/************ 更新(update)メソッド ***********/
    public void update(Graphics g) {            /* 画面のちらつきを無くす     */
        paint(g);                               /* 描画              */
    }                                           /* 更新メソッド終了        */


/************ 描画(paint)メソッド ************/
    public void paint(Graphics g) {
        grf.setFont(font);                      /* 表示フォントの設定       */
        grf.setColor(backcolor);                /* 表示背景色の設定        */
        grf.fillRect(0, 0, d.width, d.height);  /* 表示領域を塗る         */
        if (xScroll == d.width) {               /* 表示位置が先頭?        */
            curTextCount ++ ;
            if (curTextCount > maxText) {       /* 文字ブロックオーバー?     */
                curTextCount = 1;               /* YES:最初のブロック設定    */
            }
            strWidth = (getFontMetrics(font)).  /* 文字列の幅を取込        */
                        stringWidth(s[curTextCount - 1]);
            start_H = start_speed;              /* 入力初速度設定         */
            time = 0.1;                         /* 経過時間を初期設定       */
            if ( randomcolor ) {                    /* 文字色ランダム指定?    */
                red = (int)(Math.random() * 256);   /* ランダム赤設定       */
                green = (int)(Math.random() * 256); /* ランダム緑設定       */
                blue = (int)(Math.random() * 256);  /* ランダム青設定       */
                color = new Color(red,green,blue);  /* 文字表示色を設定      */
            }
        }

        grf.setColor(color);                    /* 表示色設定           */
        xScroll -= speed;                       /* スピード指定分位置を減算    */
        bound_y = (int)(start_H * time - 5.0 * time * time); /* 文字の高さを計算 */
        time += 0.5;                            /* 経過時間加算          */
        if ( bound_y < 0 ) {                    /* 高さがマイナス?        */
            bound_y = 0;                        /* 高さを0に設定(負にしない)   */
            time = 0.1;                         /* 経過時間を初期設定       */
            start_H -= 3;                       /* 初速度を減算          */
            if ( start_H < 0 ) {                /* 初速度がマイナス?       */
                bound_y = 0;                    /* ジャンプしない         */
            }
        }
        if(xScroll < -strWidth)  {              /* 表示終了判定          */
           xScroll = d.width;                   /* 終了時に表示位置を初期化    */
        }
        grf.drawString(s[curTextCount-1],xScroll,/* 文字を表示             */
            d.height - f_Descent - bound_y );
        g.drawImage(offs, 0, 0, this);          /* イメージ表示          */
    }                                           /* 描画メソッド終了        */

/********** スタート(start)メソッド **********/
    public void start() {
        if ( kicker == null ) {                 /* kickerがnull?(停止中?)   */
            kicker = new Thread(this);          /* YES:kickerを動作中に設定   */
            kicker.start();                     /* startを設定          */
        }
    }                                           /* スタートメソッド終了      */

/********** ストップ(stop)メソッド ***********/
    public void stop() {
        if( kicker != null ) {                  /* kickerがnullでない?(動作中?) */
            kicker.stop();                      /* kickerを停止に設定       */
            kicker = null;                      /* kickerに停止状態を設定     */
        }
    }                                           /* ストップメソッド終了      */

}                                               /* クラス設定終了         */

/**********************************************************************************
 *           ジャンピング文字アプレット終了              *
 **********************************************************************************/