/*********************************************/
/* Sample2Db.java
/* Target : MIDP(JSCL1.0)                    */
/*===========================================*/
/*       2Dグラフィック系サンプル
/* Desc. :                                   */
/*   第二弾
/*   duke draw by H.End
/*********************************************/
/*  Version    Date      Author              */
//  Ver. 1.00  02/04/09  K.Iguchi
/*********************************************/


//===========================================================//
//=====  インポート  ========================================//
//===========================================================//
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import com.jblend.graphics.sprite.*;
import java.util.*;


//===========================================================//
//=====  メインクラス  ======================================//
//===========================================================//
public class Sample2Db extends MIDlet
{
    private EC ec;
    private Display dp;
    private Timer tt = new Timer();
    private Random rnd = new Random( System.currentTimeMillis() );

    private int WI, HE;

    private Ball[] ball = new Ball[5];
    private Obstacle[] wood = new Obstacle[2];
    private int score;
    private int dx, dy, ax, p, cas, mode, speed;
    private int[] cloc = new int[5];


    //=====  エントリ =====//
    public void startApp()
    {
        ec = new EC();
        dp = Display.getDisplay( this );

        tt.schedule( new Runner(), 0 );
    }
    
    public void pauseApp() {}

    public void destroyApp( boolean u ) {}


    //===========================================================//
    //=====  拡張描画クラス  ====================================//
    //===========================================================//
    private class EC extends SpriteCanvas
    {
        private Image[] img = new Image[1];
        private int[][] sp_table = {
            { 0, 1, 2, 3 },
            { 2, 0, 3, 1 },
            { 3, 2, 1, 0 },
            { 1, 3, 0, 2 }
        };

        public EC()
        {
            super( sp_color.length, sp_pattern.length );

            int i;
            String[] img_name = { "/wood.png" };

            WI = getWidth();
            HE = getHeight();
            
            createFrameBuffer( WI, HE );

            //---  カーソル座標生成
            for( i=0; i<cloc.length; i++ ){
                cloc[i] = (WI>>1) + 10*(i-2);
            }

            //---  パレットデータ設定
            for( i=0; i<sp_color.length; i++ ){
                setPalette( i, sp_color[i] );
            }
            //---  スプライトデータ設定
            for( i=0; i<sp_pattern.length; i++ ){
                setPattern( i, sp_pattern[i] );
            }

            //---  背景画像読み込み
            try{
                for( i=0; i<img_name.length; i++ ){
                    img[i] = Image.createImage( img_name[i] );
                }
            } catch( Exception e ) {}
        }


        //=====  ペイント  =====//
        public void paint(Graphics g)
        {
            int i;

            //-----  画面クリア  -----//
            g.setColor( 0x00ffffff );
            g.fillRect( 0, 0, WI, HE );

            //-----  背景(仮想画面への描画)  ------//
            //---  空描画
            if( mode == 0 ) g.setColor( 0x008080ff );
            else            g.setColor( 0x00ff0000 );
            g.fillRect( 0, 0, WI, dy+8 );

            //---  木描画（表示優先：低）
            for( i=0; i<wood.length; i++ ){
                if( wood[i].pr ) continue;
                g.drawImage( img[0] , wood[i].x, wood[i].y, 1|32 );
            }

            //---  地面描画
            g.setColor( 0x00606000 );
            g.fillRect( 0, dy+8, WI, HE-(dy+8) );

            //---  木描画（表示優先：高）
            for( i=0; i<wood.length; i++ ){
                if( wood[i].pr == false ) continue;
                g.drawImage( img[0] , wood[i].x, wood[i].y, 1|32 );
            }

            //---  プレイヤー関連情報表示
            g.setColor( 0x00ffffff );
            g.drawString( "▲", cloc[cas], HE-13, 1|16 );
            g.drawString( "SCORE:"+score, 0, 0, 4|16 );

            //---  描画したものをフレームバッファへ転送
            copyArea( 0, 0, WI, HE, 0, 0 );


            //-----  スプライト（フレームバッファへの描画）  -----//
            //---  ボール
            for( i=0; i<ball.length; i++ ){
                if( ball[i].off ) continue;
                short cmd = createCharacterCommand( ball[i].attr, true, 
                    0, false, false, 8 );
                drawSpriteChar( cmd, (short)(ball[i].x-4),
                                     (short)ball[i].y  );
            }

            //---  ヅケ
            switch( mode ){
                case 0://通常時
                    for( i=0; i<4; i++ ){
                        short cmd = createCharacterCommand( 0, true, 
                            0, false, false,   i+(p<<2) );
                        drawSpriteChar( cmd, (short)( dx  + (((i&1)>0)? 0:-8) ),
                                             (short)( dy+4+    ((i >1)? 0:-8) ) );
                    }
                    break;
                case 1://ミス時回転
                    for( i=0; i<4; i++ ){
                        short cmd = createCharacterCommand( 0, true, 
                            p, false, false, sp_table[p][i] );
                        drawSpriteChar( cmd, (short)( dx  + (((i&1)>0)? 0:-8) ),
                                             (short)( dy+4+    ((i >1)? 0:-8) ) );
                    }
                    break;
            }

            //-----  背景（手前レイヤー）  -----//
            //---  プレイヤーカーソル再描画(ボールで隠されないようにするため）
            g.setColor( 0x00ffffff );
            g.drawString( "▲", cloc[cas], HE-13, 1|16 );
            copyArea( cloc[cas]-4, HE-10, 8, 10, cloc[cas]-4, HE-10 );

            //-----  L.C.D.への反映  -----//
            drawFrameBuffer( 0, 0 );
        }

        //=====  キースキャン  =====//
        public void keyPressed( int st )
        {
            switch( mode ){
                case 0://ゲーム中
                    switch( st ){
                        case LEFT:
                            if( cas > 0 ) cas -= 1;
                            break;
                        case RIGHT:
                            if( cas < 4 ) cas += 1;
                            break;
                    }
                    break;
                case 1://ゲームオーバー
                    if( st == FIRE ){
                        mode = 2;
                    }
                    break;
                case 2://再開用ダミー
                    break;
            }
        }

    }//=====  End of ExtendCampas


    //===========================================================//
    //=====  経時変化処理クラス  ================================//
    //===========================================================//
    public class Runner extends TimerTask
    {
        private boolean finish;

        //=====  フレームメイン  =====//
        public void run()
        {
            int i;
            //-----  表示開始
            dp.setCurrent( ec );
            
            //-----  全体ループ  -----//
            while( true ){

                //---  パラメータ初期化
                p = 0;
                ax = 0;
                dx = WI/2+1;
                dy = 60;
                cas = 2;
                mode = 0;
                score = 0;
                speed = 2;
                finish = false;

                //----  オブスタクルインスタンス生成
                for( i=0; i<ball.length; i++ ){
                    ball[i] = new Ball();
                }
                for( i=0; i<wood.length; i++ ){
                    wood[i] = new Obstacle();
                }
                wood[0].x = 12;
                wood[1].x = WI-12;
                wood[1].y = HE-24;

                //-----  一回目  -----//
                try{
                    wait();
                } catch( Exception e ){}

                //-----  メインループ  -----//
                while( finish == false )
                {
                    ec.repaint();

                    switch( mode ){
                        case 0://ゲーム中
                            p = (p+1) & 0x01;
                            
                            //-----  ヅケ動く
                            if( dx > cloc[cas] ){
                                if( ax >-3 && (p & 1) > 0 ) ax -= 1;
                            } else if( dx < cloc[cas] ){
                                if( ax < 3 && (p & 1) > 0 ) ax += 1;
                            }
                            dx = dx + ax;
                            
                            //-----  木処理  -----//
                            for( i=0; i<wood.length; i++ ){
                                wood[i].step();
                            }
                            //-----  ボール処理  -----//
                            for( i=0; i<ball.length; i++ ){
                                if( ball[i].off ){
                                    //---  新しく発生
                                    if( (Math.abs(rnd.nextInt())&0x8f) < 1 ){
                                        ball[i].next();
                                    }
                                } else {
                                    //---  ボール動かす
                                    ball[i].step();
                                    //---  ボールとヅケの衝突判定
                                    if( ball[i].coresion() ){
                                        ball[i].off = true;
                                        if( ball[i].attr == 0 ) mode = 1;
                                        else                    score++;
                                        if( (score&0x1f)  == 0 ){
                                            if( speed < 8 ){
                                                speed++;
                                            }
                                        }
                                    }
                                }
                            }
                            break;
                        case 1://ゲームオーバー時
                            p = (p+1) & 0x03;
                            break;
                        case 2://ループ脱出
                            finish = true;
                            break;
                    }

                    try{
                        Thread.sleep( 100 );
                    } catch( Exception e ) {}
                }

                //-----  終了処理  -----//
                ec.repaint();
                System.gc();
            }
        }
    }//===== End of Timer

    //===========================================================//
    //=====  障害物クラス  ======================================//
    //===========================================================//
    public class Obstacle
    {
        private boolean pr;
        public int x, y;

        public Obstacle()
        {
            next();
        }
        
        public void step()
        {
            if( pr ){
                y -= speed;
                if( y < dy+11 ){
                    pr = false;
                }
            } else {
                y += (speed>>1);
                if( y > dy+40 ){
                    next();
                }
            }
        }
        
        private void next()
        {
            pr = true;
            y = HE+32;
        }
    }//===== End of Obstacle

    public class Ball extends Obstacle
    {
        public int attr;
        public boolean off;

        public Ball()
        {
            off = true;
        }
    
        public void step()
        {
            y -= speed;
            //---  消滅判定
            if( y < (dy+2) ){
                off = true;
            }
        }
        
        public void next()
        {
            off = false;
            x = ((WI>>1)-22) + (Math.abs(rnd.nextInt()) % 54);
            y = HE+8;
            attr = Math.abs(rnd.nextInt())&0x01;
        }
        
        public boolean coresion()
        {
            if( off == false ){
                if( y - (dy+4) < 4 ){
                    if( Math.abs( dx-x ) < 8 ){
                        return true;
                    }
                }
            }
            return false;
        }
    }//=====  End of Ball


    //=====  便利ツール  =====//
    private void sleep( int t )
    {
        try{
            Thread.sleep( t );
        } catch( Exception e ) {}
    }

    private void log( String s ){ System.out.println( s ); }


    //=====  データ定義  =====//
    public final int[] sp_color = {
          0x212bf9, 0x0, 0xff0000, 0xff2121,
          0xffffff, 0, 0, 0, 0, 0, 0, 0,
          0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
          0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
          0, 0x00ff0000
    };
    
    public final byte[][] sp_pattern = {
        { // PATTERN 0
          0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,
          0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,
          0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
          0, 0, 0, 1, 1, 1, 1, 3, 1, 0, 0, 1, 1, 1, 2, 2
        },
        { // PATTERN 1
          0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
          1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
          1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
          2, 1, 1, 1, 1, 0, 0, 0, 2, 2, 1, 1, 1, 0, 0, 0
        },
        { // PATTERN 2
          0, 1, 0, 1, 4, 4, 2, 3, 1, 1, 1, 4, 4, 4, 4, 2,
          0, 1, 0, 1, 4, 4, 4, 4, 0, 0, 0, 1, 4, 4, 4, 4,
          0, 0, 0, 1, 4, 4, 4, 4, 0, 0, 0, 1, 4, 4, 1, 4,
          0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0
        },
        { // PATTERN 3
          3, 2, 4, 4, 1, 0, 1, 0, 2, 4, 4, 4, 4, 1, 1, 1,
          4, 4, 4, 4, 1, 0, 1, 0, 4, 4, 4, 4, 1, 0, 0, 0,
          4, 4, 4, 4, 1, 0, 0, 0, 4, 4, 4, 4, 1, 0, 0, 0,
          4, 4, 4, 4, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0
        },
        { // PATTERN 4
          0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,
          0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,
          0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
          0, 0, 0, 1, 1, 1, 1, 3, 0, 0, 0, 1, 1, 1, 2, 2
        },
        { // PATTERN 5
          0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
          1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
          1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
          2, 1, 1, 1, 1, 0, 0, 0, 2, 2, 1, 1, 1, 0, 1, 0
        },
        { // PATTERN 6
          1, 0, 0, 1, 4, 4, 2, 3, 1, 1, 1, 4, 4, 4, 4, 2,
          0, 1, 0, 1, 4, 4, 4, 4, 0, 0, 0, 1, 4, 4, 4, 4,
          0, 0, 0, 1, 4, 4, 4, 4, 0, 0, 0, 1, 4, 4, 4, 4,
          0, 0, 0, 1, 4, 4, 4, 4, 0, 0, 0, 0, 1, 1, 1, 1
        },
        { // PATTERN 7
          3, 2, 4, 4, 1, 0, 1, 1, 2, 4, 4, 4, 4, 1, 1, 0,
          4, 4, 4, 4, 1, 0, 0, 1, 4, 4, 4, 4, 1, 0, 0, 0,
          4, 4, 4, 4, 1, 0, 0, 0, 4, 1, 4, 4, 1, 0, 0, 0,
          1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
        },
    //-- ボール
        { // PATTERN 0
          0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0,
          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
          0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0
        }
    };
}
