/* ----------------------------------------------------------- */
/*   matrixmsg( マトリックス風メッセージ )                     */
/*   ( HTMLより読み込んだメッセージ10行分までをマトリックス風  */
/*     に表示します。効果音OFF(HTMLkouka=1)の指定ができます。) */
/*                                                             */
/*  開発環境  ：Java2 SDK SE 1.4(「-target 1.1」でコンパイル)  */
/*  作成年月日：2004/10/23作成                                 */
/*  作成者名  ：片庭幹夫                                       */
/* ----------------------------------------------------------- */

import java.applet.*;
import java.awt.*;
import java.util.*;


/**
 *   matrixmsg( マトリックス風メッセージ )
 *  ( HTMLより読み込んだメッセージ10行分までをマトリックス風
 *    に表示します。効果音OFF(HTMLkouka=1)の指定ができます。)
 *
 *    @version  1.0  2004/10/23(「-target 1.1」でコンパイル) 
 *    @author   片庭幹夫
 */
public class matrixmsg extends Applet implements Runnable
 { 
    int	      r,  g,  b, sz, gs, oto, itix, itiy, gy, count;
    int       wmax, hmax, dmy, idx, idy, rdm;
    int       wcmax = 20;                // 横に表示する背景文字数
    int       vcmax = 12;                // 縦に表示する背景文字数
    int       len[] = new int[10];       // メッセージ文字長
    int       wcnt1[]= new int[wcmax];   // 背景白文字位置コントロール(20列分)
    String    hmg[] = new String[10];    // HTML指定メッセージ
    String    backgd, red,  green,  blue, fsize, gyo, kouka, yyy, msg;
    String    mg[], mg1[], mg2[], mg3[], mg4[], mg5[], mg6[], mg7[], mg8[], mg9[], mg10[];
    boolean   wwFg[]= new boolean[wcmax]; // 背景白文字位置コントロール(20列分)
    boolean   fsFg[]= new boolean[wcmax]; // 背景白文字位置コントロール(20列分)
    boolean   w1Fg[][]= new boolean[wcmax][vcmax]; // 背景白文字位置コントロール(行列)
    boolean   w2Fg[][]= new boolean[wcmax][vcmax]; // 背景白文字位置コントロール(行列)
    Font      fnt;
    Color     bgcolor, mjcolor;
    Image     buff;
    Random   random1;
    Graphics  g1;
    AudioClip sound1;
    Dimension d;
    Thread    thr;
    
     // 列毎(20列分)の縦方向配列検索初期値
     // (20列縦方向に40文字よりランダムに選択させる) 
    int vadd[][] = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,
                     20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39 },
                    { 5, 6, 7, 2, 3, 4, 8, 9,10,11,12,16,17,18,19,20,21,13,14,15,
                     28,29,30,31,22,23,24,25,26,27,32,33,34,35,36,37,38,39, 0, 1 },
                    { 4, 5, 6, 10,11,12,7, 8, 9,13,14,15,16,17,18,19,22,23,20,21,
                     24,25,26,31,32,33,27,28,29,30,34,35,38,39, 0, 36,37,1, 2, 3 },
                    { 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,
                     26,27,28,29,30,31,32,33,34,35,36,37,38,39, 0, 1, 2, 3, 4, 5 },
                    { 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
                      5, 6, 7,28,29,30,31,32,33,34,35,36,37,38,39, 0, 1, 2, 3, 4 },
                    {10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26, 7, 8, 9,
                     34,35,30,31,32,33,36,37,38,39, 0, 1, 2, 3, 4, 5, 6,27,28,29 },
                    {12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
                     32,33,34,35,36,37,38,39, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 },
                    {22,23,24,14,15,16,17,18,19,20,21,25,26,27,28,29,30,31,32,33,
                      6, 7, 8, 9,10,34,35,36,37,38,39, 0, 1, 2, 3, 4, 5, 11,12,13 },
                    {16,17,18,19,30,29,28,27,26,25,24,31,32,33,34,35,20,21,22,23,
                     36,37,38,39, 5, 6, 7, 4, 3, 2, 1, 0, 8, 9,10,14,15,11,12,13 },
                    {18,19,20,21,22,23,24, 5, 6, 7, 8, 9,30,31,32,33,34,35,36,37,
                     38,39, 0, 1, 2, 3, 4,25,26,27,28,29,10,11,12,13,14,15,16,17 },
                    {20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39, 
                      0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19 },
                    {22,23,11,12,13,14,15,29,30,31,32,33,34,35,36,37,38,39, 0, 1,
                      2, 3, 4, 24,25,26,27,28,5, 6, 7, 8, 9,10,16,17,18,19,20,21 },
                    {24,25,26,27,28,29,30,31,32,33,34,35,16,17,18,19,20,21,22,23, 
                      4, 5, 6, 7, 8, 9,10,11,12,13,14,15,36,37,38,39, 0, 1, 2, 3 },
                    {26,27,28,29,30,31,32,33,34,35,36,37,38,39, 0, 1, 2, 3, 4, 5, 
                      6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25 },
                    {28,29,30,31,32,33,34,35,36, 5, 6, 7,37,38,39, 0, 1, 2, 3, 4,  
                      8, 9,10,11,20,21,22,23,12,13,14,15,16,17,18,19,24,25,26,27 },
                    {18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,
                     38,39, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17 },
                    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,30,31,32,33,34,35,36,37,38,39, 
                     10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29 },
                    {32,33,34,35,36,37,38,39, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,
                     12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 },
                    {35,36,37,38,39, 4, 3, 2, 1, 0, 5, 6, 7, 8, 9,10,11,12,13,14,
                     25,26,27,28,29,30,31,32,33,34,15,16,17,18,19,20,21,22,23,24 },
                    {39,38,37, 0, 1, 2, 3, 4, 5, 6, 9, 8, 7,10,11,12,13,16,15,14,
                     19,18,17,20,21,22,23,24,25,26,27,30,29,28,31,32,33,36,35,34 }};

     // 背景用文字(ランダム表示用40種類)
    String bkgcr[] = {"0","1","2","3","4","5","6","7","8","9",
                      "A","B","C","D","E","F","G","H","I","J",
                      "K","L","M","N","O","P","Q","R","S","T",
                      "U","V","W","X","Y","Z","*","#","$","%"};
    
   /**
    *   初期化
    */  
  public void init ()
   {    
    showStatus( "matrixmsg Java Applet Loading ....." );  // ﾌﾞﾗｳｻﾞのｽﾃｰﾀｽﾊﾞｰに表示
     
     // 効果音auファイルの読み込み
    sound1 = getAudioClip( getDocumentBase(), "matrixmsgau/sound1.au" );

    backgd  = getParameter( "HTMLmoji" );   //  文字色
    red     = backgd.substring( 0, 2 );
    green   = backgd.substring( 2, 4 );
    blue    = backgd.substring( 4 );
    r       = Integer.valueOf( red,16 ).intValue();
    g       = Integer.valueOf( green,16 ).intValue();
    b       = Integer.valueOf( blue,16 ).intValue();
    mjcolor = new Color( r,  g,  b );       //  文字色

     //  HTMLよりフォントサイズ
    fsize = getParameter( "HTMLfsize" );              // フォントサイズ
    sz    = Integer.valueOf( fsize, 10 ).intValue();  // フォントサイズを整数に変換
    fnt   = new Font( "Dialog", Font.PLAIN, sz );

     //  HTMLより最大表示行数
    gyo = getParameter( "HTMLgoyou" );                // 最大表示行数
    gs  = Integer.valueOf( gyo, 10 ).intValue();      // 最大表示行数を整数に変換    
     
     //  HTMLより効果音 OFF( HTMLkouka = 1 ... 効果音オフ )
    kouka = getParameter( "HTMLkouka" );              // 効果音指定
    oto   = Integer.valueOf( kouka, 10 ).intValue();  // 効果音指定を整数に変換
     
     //  HTMLよりメッセージ縦方向表示位置
    yyy  = getParameter( "HTMLitiy" );                // メッセージ縦方向 y 位置
    itiy = Integer.valueOf( yyy, 10 ).intValue();     // メッセージ縦方向 y 位置を整数に変換  

     //  HTMLよりメッセージ、長さ
    for(int i = 0; i < 10; i++)
       {
        hmg[i] = getParameter( "HTMLmsg" + (i+1) );   // i+1行目のメッセージ
        len[i] = hmg[i].length();                     // メッセージの長さ
       } 

    mg1 = new String[len[0]];           // 1行目を表示させる文字の記憶用配列     
    mg2 = new String[len[1]];           // 2行目を表示させる文字の記憶用配列    
    mg3 = new String[len[2]];           // 3行目を表示させる文字の記憶用配列    
    mg4 = new String[len[3]];           // 4行目を表示させる文字の記憶用配列    
    mg5 = new String[len[4]];           // 5行目を表示させる文字の記憶用配列    
    mg6 = new String[len[5]];           // 6行目を表示させる文字の記憶用配列     
    mg7 = new String[len[6]];           // 7行目を表示させる文字の記憶用配列    
    mg8 = new String[len[7]];           // 8行目を表示させる文字の記憶用配列    
    mg9 = new String[len[8]];           // 9行目を表示させる文字の記憶用配列    
    mg10= new String[len[9]];           // 10行目を表示させる文字の記憶用配列 

    itix = 20;           // メッセージ表示位置横 x
    gy   =  0;           // メッセージ表示行数

     // アプレットの領域サイズを取得
    d    = getSize();
    wmax = d.width;      // 横幅を取得
    hmax = d.height;     // 高さを取得

    // 1行目を白文字にする
    for( int i=0 ; i<wcmax; i++ )
       {
        for( int ii=0 ; ii<vcmax; ii++ )
           {
            w1Fg[i][ii] = false;
            w2Fg[i][ii] = false;
            if( i == 0 && ii == 0 )  // 1行1列目白色にセット
              {
               w1Fg[i][ii] = true;   // 1行目
               w2Fg[i][ii] = true;   // 1行目
              }
           }
       }
     
     // ちらつきを抑える為のGraphics オブジェクトg1の描画領域を確保
    buff = createImage( wmax, hmax );
    g1   = buff.getGraphics();    
   }

 
    /**
     *   paint()を直接呼び出す。
     *   これを入れないとコンポーネントの背景をクリアーするため画面がちらつく。
     *
     */
   public void update( Graphics g )
    {
     paint(g);
    }           
    
     
    /**
     *    描画
     *
     *    @param  buff  描画領域
     */
   public void paint( Graphics g )
    {
      g1.setColor( Color.black );
      g1.fillRect( 0, 0, wmax, hmax );    // 描画域クリア

      haikei();                           // マトリックス風背景描画

      // 表示させない文字を指定して表示させる。 
      count = ++count;                    //  非表示桁        
      mg[0] = msg.substring( 0, count );  // 1桁目より表示、count桁より非表示
      g1.setColor( mjcolor );             // フォントカラー
      g1.setFont( fnt );                  // フォントサイズ

      if( itiy == 50 )
        {
         mg[0]  = mg[0] + "■";           // カーソル表示
        }      
      g1.drawString( mg[0], itix, itiy ); // 右より１文字づつ表示

       // 効果音( HTMLkouka=1 OFF )
      if( count < 3 && oto != 1 )
        {
         sound1.play();       // ノイズ音再生 
        }
      
      // 非表示桁が無くなった場合の処理
      if( count >= len[gy] )
        {
         count = count - 1;
         itiy  = itiy + 3;
         if( itiy > hmax+30 ) // 下に移動
           {               
            count =  0;
            itiy  = 50;
            gy    = ++gy;    // HTML読み込み行移動
            
            if( gy > (gs-1) )
              {
               gy   = 0;
              }
           }
         }   // 非表示桁が無くなった場合の処理 終わり ----- 
      
     g.drawImage( buff, 0, 0, null );      //  buffをオブジェクトgに渡す
    }
       
     
    /**
     *     スレッドを起動
     */
   public void start()
    {
     if( thr == null )
        {
         thr = new Thread( this );
         thr.start();
        }
    }
    
    
    /**
     *     スレッドを停止
     */
   public void stop()
    {
     if( thr != null )
        {
     //  thr.stop();
         thr = null;
        }
    }
    
    
     /**
      *    マルチスレッド処理(自動的に動かす)
      */
    public void run()
      {
        Thread thrc = Thread.currentThread();  // Java2より変更
        while( thr == thrc )
           {
            jyunbi();      // 描画準備
            repaint();     // 描画
           
            try
               {                  
                thrc.sleep(80);    // 0.08秒                  
               }
            catch(InterruptedException e){}
           }
     }

        
  /**
   *    作者情報(ブラウザ上で表示)
   */
    public String getAppletInfo()
      {
       return "matrixmsg Java Applet Copyright (c) 2004 Mikio Kataniwa";
      }     


 /* ------------------------------------------------------------------------ */
  /*  ********************  run メソッドの実行内容  ********************   */

  /**
   *  描画準備
   *  (表示用配列にコピーする)
   */
  void jyunbi()
        {
          // HTML指定行数
         if( gy < gs )
           {
            msg = hmg[gy];                // HTML指定メッセージ
            mg  = new String[len[gy]];    // 表示させる文字配列
           }
        }  // 描画準備 終わり -----


  /**
   *  マトリックス風背景描画
   *  (マトリックス風文字が縦に表示される背景描画)
   */
  void haikei()
       {
        // 初期値セット
        idx =  0;
        idy = 10;

        // マトリックス風文字背景作成
        for( int i=0 ; i<wcmax; i++ )            // 横方向背景文字
           {
            idx     = idx+10;

            // 縦方向配列検索値を変更する(40文字)
            for( int ii=0 ; ii<40; ii++ )
               {
                dmy = ii%2;               // 配列検索をランダムにするため
                vadd[i][ii]=vadd[i][ii]+1+dmy;
                if( vadd[i][ii] >= 40 )
                  {
                   vadd[i][ii] = 0;
                  }
               }

            // 縦方向背景文字
            for( int ii=0 ; ii<vcmax; ii++ )
               {
                 g1.setFont( new Font( "Dialog", Font.PLAIN, 9 ));
                if( w1Fg[i][ii] == true ) // 白文字が落下状態で表示
                  {
                   if( ii-5 > 0 && vcmax != 8 )
                     {
                      g1.setColor( new Color( 255, 255, 255 ));                    // 白色
                      g1.drawString( bkgcr[vadd[i][ii-5]], idx, idy+(ii*10-50) );  // 文字描画
                     }
                   if( ii-5 > 0 && vcmax == 8 )
                     {
                      g1.setColor( new Color( 255, 255, 255 ));                    // 白色
                      g1.drawString( bkgcr[vadd[i][ii-5]], idx, idy+(ii*10-50) );  // 文字描画
                     }
                   if( ii-4 > 0 && vcmax != 9 )
                     {
                      g1.setColor( new Color( 0, 0, 0 ));                          // 黒色
                      g1.drawString( bkgcr[vadd[i][ii-4]], idx, idy+(ii*10-40) );  // 文字描画
                     }
                   if( ii-4 > 0 && vcmax == 9 )
                     {
                      g1.setColor( new Color( 255, 255, 255 ));                    // 白色
                      g1.drawString( bkgcr[vadd[i][ii-4]], idx, idy+(ii*10-40) );  // 文字描画
                     }
                   if( ii-3 > 0 && vcmax != 10 )
                     {
                      g1.setColor( new Color( 0, 0, 0 ));                          // 黒色
                      g1.drawString( bkgcr[vadd[i][ii-3]], idx, idy+(ii*10-30) );  // 文字描画
                     }
                   if( ii-3 > 0 && vcmax == 10 )
                     {
                      g1.setColor( new Color( 255, 255, 255 ));                    // 白色
                      g1.drawString( bkgcr[vadd[i][ii-3]], idx, idy+(ii*10-30) );  // 文字描画
                     }
                   if( ii-2 > 0 && vcmax != 11 )
                     {
                      g1.setColor( new Color( 0, 0, 0 ));                          // 黒色
                      g1.drawString( bkgcr[vadd[i][ii-2]], idx, idy+(ii*10-20) );  // 文字描画
                     }
                   if( ii-2 > 0 && vcmax == 11 )
                     {
                      g1.setColor( new Color( 255, 255, 255 ));                    // 白色
                      g1.drawString( bkgcr[vadd[i][ii-2]], idx, idy+(ii*10-20) );  // 文字描画
                     }
                   if( ii-1 > 0 && vcmax != 12 )
                     {
                      g1.setColor( new Color( 0, 0, 0 ));                          // 黒色
                      g1.drawString( bkgcr[vadd[i][ii-1]], idx, idy+(ii*10-10) );  // 文字描画
                     }
                   if( ii-1 > 0 && vcmax == 12 )
                     {
                      g1.setColor( new Color( 255, 255, 255 ));                    // 白色
                      g1.drawString( bkgcr[vadd[i][ii-1]], idx, idy+(ii*10-10) );  // 文字描画
                     }
                  }
                else    // 薄いグリーン色で１行目はカーソル付で表示
                     {
                      g1.setColor( new Color( 102, 204, 0 ));           // 薄いグリーン色
                      g1.drawString( bkgcr[vadd[i][ii]], idx, idy+(ii*10) );  // 文字描画
                     }

                // 縦方向背景文字を白色に変更させる
                if( w1Fg[i][ii] == true )
                  {
                   if( ii+1 < vcmax && wwFg[i] == false )
                     {
                      w2Fg[i][ii]  = false;   // 現在白色をリセット
                      w2Fg[i][ii+1]= true;    // 次回1行下を白色にする
                      wwFg[i]      = true;    // 1行下を白色にセット済み
                     }
                   if( ii+1 >= vcmax && wwFg[i] == false )
                     {
                      w2Fg[i][vcmax-1]= false;  // 現在白色をリセット
                      w2Fg[i][0]      = true;   // 最初の状態に戻す
                      wwFg[i]         = true;   // 1行下を白色にセット済み
                     }
                  }
               }

            // 白色文字は２回毎に下に移動して表示させる
            wcnt1[i] = ++wcnt1[i];
            if( wcnt1[i] > 2 )
              {
               wcnt1[i] = 0;
               wwFg[i]  = false;
               for( int iii=0 ; iii<vcmax; iii++ )
                  {
                   w1Fg[i][iii] = w2Fg[i][iii];  // 移動位置を下にする。

                    // ランダムに白色文字を表示させる
                   if( w1Fg[0][4] == true && fsFg[3] == false )  // １度だけ処理
                     {
                      w1Fg[3][0] = true;
                      w2Fg[3][0] = true;
                      fsFg[3]    = true;
                     }
                   if( w1Fg[0][11] == true && fsFg[7] == false )  // １度だけ処理
                     {
                      w1Fg[7][0] = true;
                      w2Fg[7][0] = true;
                      fsFg[7]    = true;
                     }
                   if( w1Fg[0][7] == true && fsFg[15] == false )  // １度だけ処理
                     {
                      w1Fg[15][0] = true;
                      w2Fg[15][0] = true;
                      fsFg[15]    = true;
                     }
                   if( w1Fg[0][3] == true && fsFg[18] == false )  // １度だけ処理
                     {
                      w1Fg[18][0] = true;
                      w2Fg[18][0] = true;
                      fsFg[18]    = true;
                     }

                   // 以下はランダム表示
                   random1= new Random();
                   rdm    = Math.abs( random1.nextInt() ) % 5 + 1; //  1-5の範囲の乱数作成
                   if( rdm == 1 )
                     {
                      if( w1Fg[0][6] == true && fsFg[8] == false ) // １度だけ処理
                        {
                         w1Fg[8][0] = true;
                         w2Fg[8][0] = true;
                         fsFg[8]    = true;
                        }
                     }
                   if( rdm == 2 )
                     {
                      if( w1Fg[0][9] == true && fsFg[13] == false ) // １度だけ処理
                        {
                         w1Fg[13][0] = true;
                         w2Fg[13][0] = true;
                         fsFg[13]    = true;
                        }
                     }
                   if( rdm == 3 )
                     {
                      if( w1Fg[0][4] == true && fsFg[11] == false ) // １度だけ処理
                        {
                         w1Fg[11][0] = true;
                         w2Fg[11][0] = true;
                         fsFg[11]    = true;
                        }
                     }
                   if( rdm == 4 )
                     {
                      if( w1Fg[0][10] == true && fsFg[19] == false ) // １度だけ処理
                        {
                         w1Fg[19][0] = true;
                         w2Fg[19][0] = true;
                         fsFg[19]    = true;
                        }
                     }
                   if( rdm == 5 )
                     {
                      if( w1Fg[0][2] == true && fsFg[17] == false ) // １度だけ処理
                        {
                         w1Fg[17][0] = true;
                         w2Fg[17][0] = true;
                         fsFg[17]    = true;
                        }
                     }
                  }
              }    // 白色文字は２回毎に下に移動して表示させる 終わり -----

           }       // 横方向背景文字 終わり -----

       }           // マトリックス風背景描画 終わり -----
     
}

