天天看點

JAVA遊戲程式設計之三----j2me 手機遊戲入門開發--俄羅斯方塊_4_增加消除行聲音

<a target="_blank" href="http://blog.51cto.com/attachment/201105/172006109.jpg"></a>

之前的遊戲代碼中都未加聲音,不少網友在做别業設計時要求增加聲音,其實聲音還是比較好做的!但手機真機上可能會有不同的問題,但在模拟器上一般都沒什麼問題,是以真機上的問題就具體問題具體分析吧!這裡給出一個很簡單的聲音應用。

在原 俄羅斯方塊_3的代碼基礎上增加一個聲音類!

示例代碼如下

view plaincopy to clipboardprint?  

package code;     

import java.io.*;     

import javax.microedition.media.Manager;     

import javax.microedition.media.MediaException;     

import javax.microedition.media.Player;     

public class Sound     

{     

    public static Player            m_sounds;     

    public static int               m_currentSoundID        = -1;     

    public static boolean           s_sound_bg_On           = false;     

    private static final String SOUND_FILENAME  ="/pics/newmsg.wav";        //0.背景聲音     

    public static final void initSound()     

    {     

        if( m_sounds != null )     

            return;     

        try    

        {     

            DataInputStream dis= new DataInputStream("".getClass().getResourceAsStream(SOUND_FILENAME));     

            byte[] soundBuffer = new byte[dis.available()];     

            dis.read( soundBuffer );     

            InputStream is = new ByteArrayInputStream(soundBuffer);     

            m_sounds = Manager.createPlayer(is, "audio/x-wav" );     

            m_sounds.realize();     

            m_sounds.prefetch();     

        }catch( Exception e )     

            e.printStackTrace();     

        }     

    }     

    public static void playSound( int soundID )     

        playSound( soundID, 1 );     

    public static void playSound( int soundID, int loopCount )     

            if( m_sounds == null )     

                return;     

            if( m_sounds.getState() == javax.microedition.media.Player.STARTED )     

            m_currentSoundID = soundID;     

            m_sounds.setMediaTime( 0 );     

            m_sounds.setLoopCount( loopCount );     

            m_sounds.start();     

            Thread.sleep( 50 ); // maybe this can help for sound problems     

    private static void stopSound() throws Exception     

                m_sounds.stop();     

            if( m_sounds.getState() == javax.microedition.media.Player.PREFETCHED )     

                m_sounds.deallocate();     

            m_currentSoundID = -1;     

    public static int readFileToMemory( String fileName, byte[] buffer )     

        java.io.InputStream file = null;     

        int size;     

            file = fileName.getClass().getResourceAsStream( fileName );     

            size = file.read( buffer );     

            file.close();     

            file = null;     

            return -1;     

        return size;     

}   

使用方法 是在主Canvas類的初始化或者遊戲初始化的地方調用 Sound類的initSound()方法,來初始化聲音檔案,

然後在想要播放的地方調用Sound類的playSound()方法,目前這個簡單的例子裡隻有一個聲音,是以參數給啥都一樣,如果以後聲音多了!就可以用這個參數來區分使用者要調用的是那個聲音了!這裡的使用者是相對這個Sound類的使用者,就是程式員,Sound類都是靜态方法,這裡相對于一個公共的工具類!

如果上述使用方法您沒看明白,那就看一下代碼

主Canvas類代碼如下

//import java.awt.*;     

//import java.awt.Canvas;     

//import java.awt.event.*;     

//import javax.swing.*;     

import java.util.Random;     

import javax.microedition.lcdui.*;          //寫界面所需要的包     

/**    

 * 俄羅斯方塊    

 * 高雷    

 * 2007年11月30日    

 */    

public class cGame240x320 extends Canvas implements Runnable      

    private Random rand;     

    private Thread thread;     

    private Graphics    gb;     

    private Image       buffer;     

    private Image       gameOverImg;                    //遊戲結束     

    private static final int s_width    = 240;     

    private static final int s_height   = 320;     

    private static final int s_box_w    = 16;     

    private static final int s_box_h    = 16;     

    private static final int s_box_w_sum    = 10;       //操作區域寬 格子數     

    private static final int s_box_h_sum    = 20;       //操作區域高 格子數     

    private static final int s_line_between_x = s_box_w * s_box_w_sum;//分割線x位置     

    public static final int  UP     = -1;     

    public static final int  DOWN   = -2;     

    public static final int  LEFT   = -3;     

    public static final int  RIGHT  = -4;     

    public static final int  init_x         = 3;        //目前方塊初始化坐标X     

    public static final int  init_y         = 0;        //目前方塊初始化坐标y     

    public static int   s_box_x             = init_x;   //目前方塊坐标X     

    public static int   s_box_y             = init_y;   //目前方塊坐标Y     

    private static int  level               = 1;        //等級     

    private static int  success             = 0;        //得分     

    private static long goDownDelayTime[]   = //1800;   //下降延遲時間     

        1000,   900,    800,    700,     

        600,    500,    400,     

        300,    200,    100    

    };     

    private static int  level_up            = (int)(goDownDelayTime[0]-goDownDelayTime[level]);     //更新成績     

    private static boolean isShowReseau     = true;     //是否現實網格     

    private static short s_next_box         = 0;        //下一個方塊編号     

    private static short boxColor;                      //目前box的顔色     

//  private static final Color gameBG       = new Color( 0x333333 );    //遊戲區域背景顔色     

    private static final int gameBG         = 0x333333; //遊戲區域背景顔色     

//  private static final Color gameColor[]  = new Color[]     

    private static final int gameColor[]    = new int[]     

        0x444444,   //new Color( 0x444444 ),    //網格顔色     

        0xEEEEEE,   //new Color( 0xEEEEEE ),    //方塊顔色     

        0xEE0000,   //new Color( 0xEE0000 ),     

        0x00EE00,   //new Color( 0x00EE00 ),     

        0x0000EE,   //new Color( 0x0000EE ),     

        0xEE00EE,   //new Color( 0xEE00EE ),     

        0xEEEE00,   //new Color( 0xEEEE00 ),     

        0x00EEEE    //new Color( 0x00EEEE )     

    private static final short box_sum[][] = new short[][]  //所有方塊圖形     

        { 0x0660, 0x0660, 0x0660, 0x0660 },     

        { 0x2222, 0x00F0, 0x2222, 0x00F0 },     

        { 0x0264, 0x0630, 0x0264, 0x0630 },     

        { 0x0462, 0x0360, 0x0462, 0x0360 },     

        { 0x02E0, 0x4460, 0x0740, 0x0622 },     

        { 0x0E20, 0x2260, 0x0470, 0x0644 },     

        { 0x0464, 0x00E4, 0x04C4, 0x04E0 }     

    private static short next_box[] = new short[]{ 0x0660, 0x0660, 0x0660, 0x0660 };      

    private static short box[]      = new short[]{ 0x0660, 0x0660, 0x0660, 0x0660 };     

    private static short map[][];       //地圖     

    private static short box_state  = 0;//目前BOX的狀态//旋轉方向     

    private static short matrix[][] =   //定義矩陣用來計算出box_sum的方塊     

        { 0x1000, 0x0100, 0x0010, 0x0001 },     

        { 0x2000, 0x0200, 0x0020, 0x0002 },     

        { 0x4000, 0x0400, 0x0040, 0x0004 },     

        { (short)0x8000, 0x0800, 0x0080, 0x0008 }     

    public cGame240x320()     

        setFullScreenMode(true);        //設定遊戲為全螢幕模式,該函數隻能在支援midp2.0的手機上使用     

//      s_width = getWidth();           //得到螢幕尺寸     寬     

//      s_height= getHeight();          //得到螢幕尺寸     高     

        rand = new Random( System.currentTimeMillis() );     

            //gameOverImg = Toolkit.getDefaultToolkit().getImage("src/pics/laser.png");     

            gameOverImg = Image.createImage("/pics/laser.png");     

        }catch(Exception e){}     

        //setSize( s_width, s_height ); //設定畫布     

        Sound.initSound();              //初始化聲音資源     

        initGame();                     //遊戲初始化     

        thread  = new Thread(this);     

        thread.start();     

    private void initGame()     

        level       = 1;                //等級     

        success     = 0;                //得分     

        map  = new short[s_box_h_sum][s_box_w_sum];     

        setNextBox();                   //設定下一個BOX     

        setBox();                       //将下一個BOX設定成目前BOX     

        setGameOver( false );           //恢複遊戲     

    private void setBox()               //将next_box設定成目前可控制box     

        box_state       = 0;                                        //box 狀态     

        s_box_x         = init_x;                                   //目前方塊坐标X     

        s_box_y         = init_y;                                   //目前方塊坐标Y     

        boxColor        = s_next_box;                               //設定目前BOX顔色     

        System.arraycopy( next_box, 0, box, 0, next_box.length );   //box = next_box     

        goDownPreTime   = System.currentTimeMillis();               //設定好目前BOX後 計時     

        setNextBox();                                               //設定下一個BOX     

        if( !isCanMove() )     

            setGameOver( true );     

    public static boolean isGameOver = false;     

    public static long updatas  = 0;     

    public static long fps      = 0;     

    private long    startTime, beginTime, endTime;     

    private long    delay       = 25;     

    private long    upTime      = 25;     

    public void run()      

        while ( true )      

            try    

            {     

                beginTime = System.currentTimeMillis();     

                updatas++;     

                updata( updatas );     

                repaint();     

                endTime = System.currentTimeMillis();     

                upTime  = endTime-beginTime;     

                if( upTime&lt;delay )     

                {     

                    fps = 1000/delay;     

                    thread.sleep(delay-upTime);     

                }     

                else    

                    fps = 1000/upTime;     

            }catch(Exception e){ }     

    void setGameOver( boolean _isGameOver )     

        isGameOver = _isGameOver;     

    public void updata( long updatas )     

    public void update(Graphics g)      

        paint(g);     

    public static int   offx    = 0;     

    public static int   offy    = 0;     

    public void paint(Graphics g)     

            if( buffer == null )     

                buffer = Image.createImage( s_width, s_height );    //設定畫布緩沖區     

                gb = buffer.getGraphics();                  //得到繪圖裝置     

            }     

//          gb.translate( offx, offy );     

//          gb.setColor( new Color( 0x0 ) );                //初始化 畫布顔色     

            gb.setColor( 0x0 );                             //初始化 畫布顔色     

            gb.setClip ( 0, 0, s_width, s_height);          //初始化 畫布區域     

            gb.fillRect( 0, 0, s_width, s_height);          //初始化 畫布填充     

            paintReseau( gb );                              //繪制網格     

            paintNextBox( gb );                             //繪制下一BOX     

            paintMap( gb );                                 //繪制地圖上不可以動BOX     

            paintBox( gb, s_box_x, s_box_y );               //繪制目前可控制BOX     

//          gb.setColor( new Color( 0xFF3333 ) );           //分割線顔色     

            gb.setColor( 0xFF3333 );                        //分割線顔色     

            gb.drawLine( s_line_between_x, 0, s_line_between_x, s_height ); //分割線     

//          gb.drawString( "FPS:"+fps,          s_line_between_x+10,10 );   //祯數     

//          gb.drawString( "等級:"+level,         s_line_between_x+10,30 );   //等級     

//          gb.drawString( "得分:"+success,       s_line_between_x+10,50 );   //分數     

            gb.drawString( "FPS:"+fps,          s_line_between_x+10, 10, g.TOP|g.LEFT );//祯數     

            gb.drawString( "等級:"+level,         s_line_between_x+10, 30, g.TOP|g.LEFT );//等級     

            gb.drawString( "得分:"+success,       s_line_between_x+10, 50, g.TOP|g.LEFT );//分數     

            if( isGameOver )     

//              gb.drawImage( gameOverImg, (getWidth()-offx-gameOverImg.getWidth(null))/2, (getHeight()-gameOverImg.getHeight(null))/2 , null );     

                gb.drawImage( gameOverImg,  s_width&gt;&gt;1, s_height&gt;&gt;1, g.HCENTER|g.VCENTER );     

//          gb.translate( -offx, -offy );     

        catch(Exception e)     

        {      

            System.out.println("err at paint.e====="+e);     

//      g.drawImage( buffer, offx, offy, null);             //将畫布緩沖區繪制到螢幕//偏移 (2,2)     

        g.drawImage( buffer, offx, offy, 0);                //将畫布緩沖區繪制到螢幕//偏移 (2,2)     

    private void paintReseau( Graphics g )                  //繪制網格     

        g.setColor( gameBG );     

        g.fillRect( 0, 0, s_line_between_x, s_height );     

        if( isShowReseau )     

            g.setColor( gameColor[0] );     

            for( int i=0; i&lt;s_line_between_x/s_box_w; i++ )  // |     

                g.drawLine( i*s_box_h, 0, i*s_box_h, s_height );     

            for( int j=0; j&lt;s_height/s_box_h; j++ )          // -     

                g.drawLine( 0, j*s_box_w, s_line_between_x, j*s_box_w );     

    private void paintBox( Graphics g, int off_x, int off_y )     

        for( int i=0; i&lt;4; i++ )     //行     

            for( int j=0; j&lt;4; j++ ) //列     

                if( (box[box_state] &amp; matrix[i][j]) == matrix[i][j] )     

                    g.setColor( gameColor[ boxColor ] );     

                    g.fillRect( (off_x+j)*s_box_w, (off_y+i)*s_box_h, s_box_w, s_box_h );     

                    g.setColor( gameBG );     

                    g.drawRect( (off_x+j)*s_box_w+1, (off_y+i)*s_box_h+1, s_box_w-2, s_box_h-2 );     

        goDown();                       //BOX是否下降     

    private void paintNextBox( Graphics g )     

        int off_x = s_line_between_x+( s_width - s_line_between_x - 4*s_box_w )/2;     

        int off_y = s_height/2;     

        g.translate( off_x, off_y );     

        g.fillRect( 0, 0, 4*s_box_w, 4*s_box_h );     

        if( isShowReseau )              //顯示格式     

            for( int i=0; i&lt;5; i++ ) // |     

                g.drawLine( i*s_box_h, 0, i*s_box_h, 4*s_box_h );     

            for( int j=0; j&lt;5; j++ ) // -     

                g.drawLine( 0, j*s_box_w, 4*s_box_w, j*s_box_w );     

                if( (next_box[0] &amp; matrix[i][j]) == matrix[i][j] )     

                    g.setColor( gameColor[ s_next_box ] );     

                    g.fillRect( j*s_box_w, i*s_box_h, s_box_w, s_box_h );     

                    g.drawRect( j*s_box_w+1, i*s_box_h+1, s_box_w-2, s_box_h-2 );     

        g.translate( -off_x, -off_y );     

    private long goDownPreTime  = 0;    //上次下降時間     

    private long currTime       = 0;    //目前時間     

    private void goDown()               //目前BOX下降     

        if( isGameOver )    //遊戲結束     

        //isKeyDown按了向下移動就需要檢查 不需要時間     

        if( isKeyDown==1 || System.currentTimeMillis() - goDownPreTime &gt;= goDownDelayTime[level] )     

            s_box_y++;     

            goDownPreTime = System.currentTimeMillis();     

            if( !isCanMove() )     

                isKeyDown = 0;  //沒有按下     

                s_box_y--;     

                setMap();       //将BOX放進map      

                setBox();       //新的BOX     

    private void setMap()     

                if( ( box[box_state] &amp; matrix[i][j] ) == matrix[i][j] ) //是格子     

                    map[s_box_y+i][s_box_x+j] = boxColor;     

        //檢測是否可以消去一行     

        int line_success = 0;     

        for( int i=0; i&lt;s_box_h_sum; i++ )       //行     

            if( isFullLine( i ) )               //這行可以消去     

                setNullLine( i );               //設定第i行為空     

                setGoDownMap( i );              //地圖第i行以上的向下移動一行     

                line_success++;     

                Sound.playSound( 0 );     

        success += line_success*line_success;   //設定得分     

        level_up = (int)(goDownDelayTime[0]-goDownDelayTime[level]);     

        if( success &gt;= level_up )                //設定更新     

            level %= goDownDelayTime.length;     

            level ++;     

    private void paintMap( Graphics g )     

            for( int j=0; j&lt;s_box_w_sum; j++ )   //列     

                if( map[i][j] &gt; 0 )              //是格子//繪制格子     

                    g.setColor( gameColor[ map[i][j] ] );     

                    g.fillRect( j*s_box_w, i*s_box_h, s_box_w, s_box_h );        

    private boolean isFullLine(int line)    //是否一行已經滿了     

        for( int j=0; j&lt;s_box_w_sum; j++ )   //列     

            if( map[line][j] &lt;= 0 )     

                return false;     

        return true;     

    private void  setNullLine( int line )   //設定地圖上的這一行 空     

            map[line][j] = 0;     

        }        

    private void setGoDownMap( int line )   //設定地圖line以上的每行都向下移動一行     

        for( int i=line; i&gt;0; i-- )          //行     

                map[i][j] = map[i-1][j];    //向下移動一行     

    private static       int act_off_x  = 0;    //方塊在左右邊界旋轉的時候調整方塊位置的偏移     

    private static final int act_move   = 0;     

    private static final int act_transfiguration = 1;     

    private boolean isCanMove()     

        return isCanMove( act_move );     

    private boolean isCanMove( int act )     

                    if( s_box_x+j &lt; 0 )                  //左邊界檢測     

                    {     

                        if( act == act_transfiguration )//左邊界檢測失敗 調整 BOX 位置右移動 最多2格     

                        {     

                            act_off_x=1;     

                            s_box_x ++;     

                            if( isCanMove() )     

                            {     

                                return true;     

                            }     

                            else    

                                act_off_x=2;     

                                s_box_x ++;     

                                if( isCanMove() )     

                                {     

                                    return true;     

                                }     

                                else    

                                    act_off_x = 0;     

                        }     

                        System.out.println( "left s_box_x="+s_box_x+" matrix["+i+"]["+j+"]="+matrix[i][j]);     

                        return false;     

                    }     

                    if( s_box_x+j &gt; s_box_w_sum-1 )  //右邊界檢測     

                        if( act == act_transfiguration )//右邊界檢測失敗 調整 BOX 位置左移動 最多1格     

                            act_off_x = -1;     

                            s_box_x --;     

                                act_off_x = 0;     

                        System.out.println( "right s_box_x="+s_box_x+" matrix["+i+"]["+j+"]="+matrix[i][j]);     

                    if( s_box_y+i &gt; s_box_h_sum-1 )  //下邊界檢測     

                        System.out.println( "down s_box_y="+s_box_y+" matrix["+i+"]["+j+"]="+matrix[i][j]);     

                    if( map[s_box_y+i][s_box_x+j] &gt; 0 )  //地圖格子檢測     

                        System.out.println( "map s_box_y="+s_box_y+" matrix["+i+"]["+j+"]="+matrix[i][j]);     

    private short isKeyDown = 0;    //0沒有按下,1按下,2擡起     

//  public boolean keyDown(Event evt, int key)     

    public void keyPressed( int key )     

        key = getKeyCode( key );     

        switch( key )     

            case UP:                //順時針旋轉     

                isKeyDown = 0;      //0沒有按下     

                box_state ++;     

                box_state %= 4;     

//              s_box_x -= act_off_x;   //恢複偏移中心到未偏移前//不恢複的好1     

                if( !isCanMove( act_transfiguration ) )     

                    box_state --;     

                    if( box_state&lt;0 )     

                        box_state = 3;     

            break;     

            case DOWN:              //向下移動     

                act_off_x = 0;      //恢複BOX旋轉位置偏移為0     

                if( isKeyDown == 2 )     

                    isKeyDown = 1;     

                if( isKeyDown == 1 )     

                    s_box_y ++;      

                    if( !isCanMove() )     

                        s_box_y --;     

            case LEFT:              //向左移動BOX     

                s_box_x --;     

                if( !isCanMove() )     

                    s_box_x ++;      

            case RIGHT:             //向右移動BOX     

                s_box_x ++;     

                    s_box_x --;     

            case 53:                //數字5鍵     

                if( isGameOver )    //遊戲結束     

                    initGame();     //重新遊戲     

            case 42:     

//                  System.exit(0); //退出遊戲     

                    Tetris.s_midlet.destroyApp(true);     

            case 48:     

                setBox();           //新的BOX     

            case 49:                //是否顯示網格     

                isShowReseau = !isShowReseau;     

        repaint();                  //重新繪制螢幕     

//      return true;     

    public void keyRepeated( int key )     

        keyPressed( key );     

    public void setNextBox()     

        int sho   = Math.abs( rand.nextInt() );     

        s_next_box= (short)(sho%box_sum.length);     

//      s_next_box= (short)( rand.nextInt(box_sum.length) );     

        System.arraycopy( box_sum[s_next_box], 0, next_box, 0, next_box.length );     

        s_next_box++;     

    public int getKeyCode( int key )     

        System.out.println( "key="+key );     

            case 1004:  // up     

            case 119:   // w     

            case 87:    // W     

            case 50:    // 2     

            return UP;     

            case 1005:  // down     

            case 115:   // s     

            case 83:    // S     

            case 56:    // 8     

            return DOWN;     

            case 1006:  // left     

            case 97:    // a     

            case 65:    // A     

            case 52:    // 4     

            return LEFT;     

            case 1007:  // right     

            case 100:   // d     

            case 68:    // D     

            case 54:    // 6     

            return RIGHT;     

            default:     

            return key;     

//  public boolean keyUp(Event evt, int key)      

    public void keyReleased( int key )      

        isKeyDown = 2;  //釋放按鍵     

//  public boolean mouseDown(Event evt, int x, int y)     

//  {     

//      try     

//      {     

////            System.out.println( "x="+x+" y="+y );     

//      }catch( Exception e){e.printStackTrace();}     

////        this.repaint();     

//  }     

//  public boolean mouseMove(Event evt, int x, int y)     

//          //System.out.println( "x="+x+" y="+y );     

//    public static void main(String[] args)      

//    {     

//      JFrame frame = new JFrame("俄羅斯方塊 北京|雷神 QQ:38929568");     

//      final cGame dc = new cGame();     

//      frame.getContentPane().add(dc, BorderLayout.CENTER);     

//     

////        JButton button = new JButton("重新整理");     

////        button.addActionListener(new ActionListener()      

////        {     

////            public void actionPerformed(ActionEvent e)      

////            {     

////                dc.repaint();     

////            }     

////        });     

////        frame.getContentPane().add(button, BorderLayout.SOUTH);     

//      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);     

//      frame.setSize(dc.s_width+10, dc.s_height+30);     

//      frame.setVisible(true);     

}    

package code;  

//import java.awt.*;  

//import java.awt.Canvas;  

//import java.awt.event.*;  

//import javax.swing.*;  

import java.util.Random;  

import javax.microedition.lcdui.*;          //寫界面所需要的包  

/**  

 * 俄羅斯方塊  

 * 高雷  

 * 2007年11月30日  

 */ 

public class cGame240x320 extends Canvas implements Runnable   

{  

    private Random rand;  

    private Thread thread;  

    private Graphics    gb;  

    private Image       buffer;  

    private Image       gameOverImg;                    //遊戲結束  

    private static final int s_width    = 240;  

    private static final int s_height   = 320;  

    private static final int s_box_w    = 16;  

    private static final int s_box_h    = 16;  

    private static final int s_box_w_sum    = 10;       //操作區域寬 格子數  

    private static final int s_box_h_sum    = 20;       //操作區域高 格子數  

    private static final int s_line_between_x = s_box_w * s_box_w_sum;//分割線x位置  

    public static final int  UP     = -1;  

    public static final int  DOWN   = -2;  

    public static final int  LEFT   = -3;  

    public static final int  RIGHT  = -4;  

    public static final int  init_x         = 3;        //目前方塊初始化坐标X  

    public static final int  init_y         = 0;        //目前方塊初始化坐标y  

    public static int   s_box_x             = init_x;   //目前方塊坐标X  

    public static int   s_box_y             = init_y;   //目前方塊坐标Y  

    private static int  level               = 1;        //等級  

    private static int  success             = 0;        //得分  

    private static long goDownDelayTime[]   = //1800;   //下降延遲時間  

    {  

        1000,   900,    800,    700,  

        600,    500,    400,  

        300,    200,    100 

    };  

    private static int  level_up            = (int)(goDownDelayTime[0]-goDownDelayTime[level]);     //更新成績  

    private static boolean isShowReseau     = true;     //是否現實網格  

    private static short s_next_box         = 0;        //下一個方塊編号  

    private static short boxColor;                      //目前box的顔色  

//  private static final Color gameBG       = new Color( 0x333333 );    //遊戲區域背景顔色  

    private static final int gameBG         = 0x333333; //遊戲區域背景顔色  

//  private static final Color gameColor[]  = new Color[]  

    private static final int gameColor[]    = new int[]  

        0x444444,   //new Color( 0x444444 ),    //網格顔色  

        0xEEEEEE,   //new Color( 0xEEEEEE ),    //方塊顔色  

        0xEE0000,   //new Color( 0xEE0000 ),  

        0x00EE00,   //new Color( 0x00EE00 ),  

        0x0000EE,   //new Color( 0x0000EE ),  

        0xEE00EE,   //new Color( 0xEE00EE ),  

        0xEEEE00,   //new Color( 0xEEEE00 ),  

        0x00EEEE    //new Color( 0x00EEEE )  

    private static final short box_sum[][] = new short[][]  //所有方塊圖形  

        { 0x0660, 0x0660, 0x0660, 0x0660 },  

        { 0x2222, 0x00F0, 0x2222, 0x00F0 },  

        { 0x0264, 0x0630, 0x0264, 0x0630 },  

        { 0x0462, 0x0360, 0x0462, 0x0360 },  

        { 0x02E0, 0x4460, 0x0740, 0x0622 },  

        { 0x0E20, 0x2260, 0x0470, 0x0644 },  

        { 0x0464, 0x00E4, 0x04C4, 0x04E0 }  

    private static short next_box[] = new short[]{ 0x0660, 0x0660, 0x0660, 0x0660 };   

    private static short box[]      = new short[]{ 0x0660, 0x0660, 0x0660, 0x0660 };  

    private static short map[][];       //地圖  

    private static short box_state  = 0;//目前BOX的狀态//旋轉方向  

    private static short matrix[][] =   //定義矩陣用來計算出box_sum的方塊  

        { 0x1000, 0x0100, 0x0010, 0x0001 },  

        { 0x2000, 0x0200, 0x0020, 0x0002 },  

        { 0x4000, 0x0400, 0x0040, 0x0004 },  

        { (short)0x8000, 0x0800, 0x0080, 0x0008 }  

    public cGame240x320()  

        setFullScreenMode(true);        //設定遊戲為全螢幕模式,該函數隻能在支援midp2.0的手機上使用  

//      s_width = getWidth();           //得到螢幕尺寸     寬  

//      s_height= getHeight();          //得到螢幕尺寸     高  

        rand = new Random( System.currentTimeMillis() );  

        try 

        {  

            //gameOverImg = Toolkit.getDefaultToolkit().getImage("src/pics/laser.png");  

            gameOverImg = Image.createImage("/pics/laser.png");  

        }catch(Exception e){}  

        //setSize( s_width, s_height ); //設定畫布  

        Sound.initSound();              //初始化聲音資源  

        initGame();                     //遊戲初始化  

        thread  = new Thread(this);  

        thread.start();  

    }  

    private void initGame()  

        level       = 1;                //等級  

        success     = 0;                //得分  

        map  = new short[s_box_h_sum][s_box_w_sum];  

        setNextBox();                   //設定下一個BOX  

        setBox();                       //将下一個BOX設定成目前BOX  

        setGameOver( false );           //恢複遊戲  

    private void setBox()               //将next_box設定成目前可控制box  

        box_state       = 0;                                        //box 狀态  

        s_box_x         = init_x;                                   //目前方塊坐标X  

        s_box_y         = init_y;                                   //目前方塊坐标Y  

        boxColor        = s_next_box;                               //設定目前BOX顔色  

        System.arraycopy( next_box, 0, box, 0, next_box.length );   //box = next_box  

        goDownPreTime   = System.currentTimeMillis();               //設定好目前BOX後 計時  

        setNextBox();                                               //設定下一個BOX  

        if( !isCanMove() )  

            setGameOver( true );  

        }  

    public static boolean isGameOver = false;  

    public static long updatas  = 0;  

    public static long fps      = 0;  

    private long    startTime, beginTime, endTime;  

    private long    delay       = 25;  

    private long    upTime      = 25;  

    public void run()   

        while ( true )   

            try 

            {  

                beginTime = System.currentTimeMillis();  

                updatas++;  

                updata( updatas );  

                repaint();  

                endTime = System.currentTimeMillis();  

                upTime  = endTime-beginTime;  

                if( upTime&lt;delay )  

                {  

                    fps = 1000/delay;  

                    thread.sleep(delay-upTime);  

                }  

                else 

                    fps = 1000/upTime;  

            }catch(Exception e){ }  

    void setGameOver( boolean _isGameOver )  

        isGameOver = _isGameOver;  

    public void updata( long updatas )  

    public void update(Graphics g)   

        paint(g);  

    public static int   offx    = 0;  

    public static int   offy    = 0;  

    public void paint(Graphics g)  

            if( buffer == null )  

                buffer = Image.createImage( s_width, s_height );    //設定畫布緩沖區  

                gb = buffer.getGraphics();                  //得到繪圖裝置  

            }  

//          gb.translate( offx, offy );  

//          gb.setColor( new Color( 0x0 ) );                //初始化 畫布顔色  

            gb.setColor( 0x0 );                             //初始化 畫布顔色  

            gb.setClip ( 0, 0, s_width, s_height);          //初始化 畫布區域  

            gb.fillRect( 0, 0, s_width, s_height);          //初始化 畫布填充  

            paintReseau( gb );                              //繪制網格  

            paintNextBox( gb );                             //繪制下一BOX  

            paintMap( gb );                                 //繪制地圖上不可以動BOX  

            paintBox( gb, s_box_x, s_box_y );               //繪制目前可控制BOX  

//          gb.setColor( new Color( 0xFF3333 ) );           //分割線顔色  

            gb.setColor( 0xFF3333 );                        //分割線顔色  

            gb.drawLine( s_line_between_x, 0, s_line_between_x, s_height ); //分割線  

//          gb.drawString( "FPS:"+fps,          s_line_between_x+10,10 );   //祯數  

//          gb.drawString( "等級:"+level,         s_line_between_x+10,30 );   //等級  

//          gb.drawString( "得分:"+success,       s_line_between_x+10,50 );   //分數  

            gb.drawString( "FPS:"+fps,          s_line_between_x+10, 10, g.TOP|g.LEFT );//祯數  

            gb.drawString( "等級:"+level,         s_line_between_x+10, 30, g.TOP|g.LEFT );//等級  

            gb.drawString( "得分:"+success,       s_line_between_x+10, 50, g.TOP|g.LEFT );//分數  

            if( isGameOver )  

//              gb.drawImage( gameOverImg, (getWidth()-offx-gameOverImg.getWidth(null))/2, (getHeight()-gameOverImg.getHeight(null))/2 , null );  

                gb.drawImage( gameOverImg,  s_width&gt;&gt;1, s_height&gt;&gt;1, g.HCENTER|g.VCENTER );  

//          gb.translate( -offx, -offy );  

        catch(Exception e)  

        {   

            System.out.println("err at paint.e====="+e);  

//      g.drawImage( buffer, offx, offy, null);             //将畫布緩沖區繪制到螢幕//偏移 (2,2)  

        g.drawImage( buffer, offx, offy, 0);                //将畫布緩沖區繪制到螢幕//偏移 (2,2)  

    private void paintReseau( Graphics g )                  //繪制網格  

        g.setColor( gameBG );  

        g.fillRect( 0, 0, s_line_between_x, s_height );  

        if( isShowReseau )  

            g.setColor( gameColor[0] );  

            for( int i=0; i&lt;s_line_between_x/s_box_w; i++ ) // |  

                g.drawLine( i*s_box_h, 0, i*s_box_h, s_height );  

            for( int j=0; j&lt;s_height/s_box_h; j++ )         // -  

                g.drawLine( 0, j*s_box_w, s_line_between_x, j*s_box_w );  

    private void paintBox( Graphics g, int off_x, int off_y )  

        for( int i=0; i&lt;4; i++ )        //行  

            for( int j=0; j&lt;4; j++ )    //列  

                if( (box[box_state] &amp; matrix[i][j]) == matrix[i][j] )  

                    g.setColor( gameColor[ boxColor ] );  

                    g.fillRect( (off_x+j)*s_box_w, (off_y+i)*s_box_h, s_box_w, s_box_h );  

                    g.setColor( gameBG );  

                    g.drawRect( (off_x+j)*s_box_w+1, (off_y+i)*s_box_h+1, s_box_w-2, s_box_h-2 );  

        goDown();                       //BOX是否下降  

    private void paintNextBox( Graphics g )  

        int off_x = s_line_between_x+( s_width - s_line_between_x - 4*s_box_w )/2;  

        int off_y = s_height/2;  

        g.translate( off_x, off_y );  

        g.fillRect( 0, 0, 4*s_box_w, 4*s_box_h );  

        if( isShowReseau )              //顯示格式  

            for( int i=0; i&lt;5; i++ )    // |  

                g.drawLine( i*s_box_h, 0, i*s_box_h, 4*s_box_h );  

            for( int j=0; j&lt;5; j++ )    // -  

                g.drawLine( 0, j*s_box_w, 4*s_box_w, j*s_box_w );  

                if( (next_box[0] &amp; matrix[i][j]) == matrix[i][j] )  

                    g.setColor( gameColor[ s_next_box ] );  

                    g.fillRect( j*s_box_w, i*s_box_h, s_box_w, s_box_h );  

                    g.drawRect( j*s_box_w+1, i*s_box_h+1, s_box_w-2, s_box_h-2 );  

        g.translate( -off_x, -off_y );  

    private long goDownPreTime  = 0;    //上次下降時間  

    private long currTime       = 0;    //目前時間  

    private void goDown()               //目前BOX下降  

        if( isGameOver )    //遊戲結束  

            return;  

        //isKeyDown按了向下移動就需要檢查 不需要時間  

        if( isKeyDown==1 || System.currentTimeMillis() - goDownPreTime &gt;= goDownDelayTime[level] )  

            s_box_y++;  

            goDownPreTime = System.currentTimeMillis();  

            if( !isCanMove() )  

                isKeyDown = 0;  //沒有按下  

                s_box_y--;  

                setMap();       //将BOX放進map   

                setBox();       //新的BOX  

    private void setMap()  

                if( ( box[box_state] &amp; matrix[i][j] ) == matrix[i][j] ) //是格子  

                    map[s_box_y+i][s_box_x+j] = boxColor;  

        //檢測是否可以消去一行  

        int line_success = 0;  

        for( int i=0; i&lt;s_box_h_sum; i++ )      //行  

            if( isFullLine( i ) )               //這行可以消去  

                setNullLine( i );               //設定第i行為空  

                setGoDownMap( i );              //地圖第i行以上的向下移動一行  

                line_success++;  

                Sound.playSound( 0 );  

        success += line_success*line_success;   //設定得分  

        level_up = (int)(goDownDelayTime[0]-goDownDelayTime[level]);  

        if( success &gt;= level_up )               //設定更新  

            level %= goDownDelayTime.length;  

            level ++;  

    private void paintMap( Graphics g )  

            for( int j=0; j&lt;s_box_w_sum; j++ )  //列  

                if( map[i][j] &gt; 0 )             //是格子//繪制格子  

                    g.setColor( gameColor[ map[i][j] ] );  

    private boolean isFullLine(int line)    //是否一行已經滿了  

        for( int j=0; j&lt;s_box_w_sum; j++ )  //列  

            if( map[line][j] &lt;= 0 )  

                return false;  

        return true;  

    private void  setNullLine( int line )   //設定地圖上的這一行 空  

            map[line][j] = 0;  

    private void setGoDownMap( int line )   //設定地圖line以上的每行都向下移動一行  

        for( int i=line; i&gt;0; i-- )         //行  

                map[i][j] = map[i-1][j];    //向下移動一行  

    private static       int act_off_x  = 0;    //方塊在左右邊界旋轉的時候調整方塊位置的偏移  

    private static final int act_move   = 0;  

    private static final int act_transfiguration = 1;  

    private boolean isCanMove()  

        return isCanMove( act_move );  

    private boolean isCanMove( int act )  

                    if( s_box_x+j &lt; 0 )                 //左邊界檢測  

                    {  

                        if( act == act_transfiguration )//左邊界檢測失敗 調整 BOX 位置右移動 最多2格  

                        {  

                            act_off_x=1;  

                            s_box_x ++;  

                            if( isCanMove() )  

                            {  

                                return true;  

                            }  

                            else 

                                act_off_x=2;  

                                s_box_x ++;  

                                if( isCanMove() )  

                                {  

                                    return true;  

                                }  

                                else 

                                    act_off_x = 0;  

                        }  

                        System.out.println( "left s_box_x="+s_box_x+" matrix["+i+"]["+j+"]="+matrix[i][j]);  

                        return false;  

                    }  

                    if( s_box_x+j &gt; s_box_w_sum-1 ) //右邊界檢測  

                        if( act == act_transfiguration )//右邊界檢測失敗 調整 BOX 位置左移動 最多1格  

                            act_off_x = -1;  

                            s_box_x --;  

                                act_off_x = 0;  

                        System.out.println( "right s_box_x="+s_box_x+" matrix["+i+"]["+j+"]="+matrix[i][j]);  

                    if( s_box_y+i &gt; s_box_h_sum-1 ) //下邊界檢測  

                        System.out.println( "down s_box_y="+s_box_y+" matrix["+i+"]["+j+"]="+matrix[i][j]);  

                    if( map[s_box_y+i][s_box_x+j] &gt; 0 ) //地圖格子檢測  

                        System.out.println( "map s_box_y="+s_box_y+" matrix["+i+"]["+j+"]="+matrix[i][j]);  

    private short isKeyDown = 0;    //0沒有按下,1按下,2擡起  

//  public boolean keyDown(Event evt, int key)  

    public void keyPressed( int key )  

        key = getKeyCode( key );  

        switch( key )  

            case UP:                //順時針旋轉  

                isKeyDown = 0;      //0沒有按下  

                box_state ++;  

                box_state %= 4;  

//              s_box_x -= act_off_x;   //恢複偏移中心到未偏移前//不恢複的好1  

                if( !isCanMove( act_transfiguration ) )  

                    box_state --;  

                    if( box_state&lt;0 )  

                        box_state = 3;  

            break;  

            case DOWN:              //向下移動  

                act_off_x = 0;      //恢複BOX旋轉位置偏移為0  

                if( isKeyDown == 2 )  

                    isKeyDown = 1;  

                if( isKeyDown == 1 )  

                    s_box_y ++;   

                    if( !isCanMove() )  

                        s_box_y --;  

            case LEFT:              //向左移動BOX  

                s_box_x --;  

                if( !isCanMove() )  

                    s_box_x ++;   

            case RIGHT:             //向右移動BOX  

                s_box_x ++;  

                    s_box_x --;  

            case 53:                //數字5鍵  

                if( isGameOver )    //遊戲結束  

                    initGame();     //重新遊戲  

            case 42:  

//                  System.exit(0); //退出遊戲  

                    Tetris.s_midlet.destroyApp(true);  

            case 48:  

                setBox();           //新的BOX  

            case 49:                //是否顯示網格  

                isShowReseau = !isShowReseau;  

        repaint();                  //重新繪制螢幕  

//      return true;  

    public void keyRepeated( int key )  

        keyPressed( key );  

    public void setNextBox()  

        int sho   = Math.abs( rand.nextInt() );  

        s_next_box= (short)(sho%box_sum.length);  

//      s_next_box= (short)( rand.nextInt(box_sum.length) );  

        System.arraycopy( box_sum[s_next_box], 0, next_box, 0, next_box.length );  

        s_next_box++;  

    public int getKeyCode( int key )  

        System.out.println( "key="+key );  

            case 1004:  // up  

            case 119:   // w  

            case 87:    // W  

            case 50:    // 2  

            return UP;  

            case 1005:  // down  

            case 115:   // s  

            case 83:    // S  

            case 56:    // 8  

            return DOWN;  

            case 1006:  // left  

            case 97:    // a  

            case 65:    // A  

            case 52:    // 4  

            return LEFT;  

            case 1007:  // right  

            case 100:   // d  

            case 68:    // D  

            case 54:    // 6  

            return RIGHT;  

            default:  

            return key;  

//  public boolean keyUp(Event evt, int key)   

    public void keyReleased( int key )   

        isKeyDown = 2;  //釋放按鍵  

//  public boolean mouseDown(Event evt, int x, int y)  

//  {  

//      try  

//      {  

////            System.out.println( "x="+x+" y="+y );  

//      }catch( Exception e){e.printStackTrace();}  

////        this.repaint();  

//  }  

//  public boolean mouseMove(Event evt, int x, int y)  

//          //System.out.println( "x="+x+" y="+y );  

//    public static void main(String[] args)   

//    {  

//      JFrame frame = new JFrame("俄羅斯方塊 北京|雷神 QQ:38929568");  

//      final cGame dc = new cGame();  

//      frame.getContentPane().add(dc, BorderLayout.CENTER);  

//  

////        JButton button = new JButton("重新整理");  

////        button.addActionListener(new ActionListener()   

////        {  

////            public void actionPerformed(ActionEvent e)   

////            {  

////                dc.repaint();  

////            }  

////        });  

////        frame.getContentPane().add(button, BorderLayout.SOUTH);  

//      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  

//      frame.setSize(dc.s_width+10, dc.s_height+30);  

//      frame.setVisible(true);  

這部分代碼和前一篇(俄羅斯方塊_3)的代碼基本一緻,隻是添加了聲音的初始化和播放方法!

給大家參考,

為了程式完整性,該程式還有一個主MIDlet類

///////////////////////////////////////////////////////////////////////////////////////////////////     

import javax.microedition.midlet.*; //j2me MIDlet程式必須繼承MIDlet類,是以要引入此包     

import javax.microedition.lcdui.*;  //Display這個類所在包     

import javax.microedition.rms.*;     

import java.util.*;     

import java.util.Calendar;     

import java.util.Date;     

public class Tetris extends MIDlet      

    static Tetris s_midlet; //MIDlet類的靜态對象,友善實用 MIDlet類方法     

    static Display s_display = null;//用來顯示 Canvas     

    static cGame240x320 s_game = null;      //Canvas類對象,主要實作遊戲的類     

    public Tetris()     

        s_midlet = this;     

    /**    

     * 程式開始 系統會調用這個函數    

     * 也有些手機 可以把程式初始化部分放到構造函數裡,這連個地方應視手機的不同而定!    

     */    

    public void startApp()               

        ReadData();     

        if (s_display == null)      

            s_display = Display.getDisplay(this);//建立Display對象,參數是MIDlet類對象,也就是我們目前寫的這個Minesweeper類     

        if (s_game == null)      

            s_game = new cGame240x320();                //建立 Canvas對象     

            s_display.setCurrent(s_game);       //把Canvas對象設定成目前顯示     

        }      

        else      

            s_display.setCurrent(s_game);     

     * 程式暫停 系統會自動調用這個函數,不是所有手機都支援,    

     * 手機在接到中斷,如 來電,來短信時候會調用這個函數,這個函數 通常是空的!    

    public void pauseApp()            

     * 程式關閉 系統會調用這個函數,如果希望關閉程式的時候儲存資料,可在這個函數裡添加儲存資料的方法    

     * 比如遊戲進行中,按了關機鍵,程式就會調用這個函數,也可以在程式中調用這個函數來結束遊戲!    

    public void destroyApp(boolean unconditional)      

        WriteData();     

        notifyDestroyed();     

    static Calendar cal     = Calendar.getInstance();     

    static Date     date    = null;     

    public static String getDate()     

        date = new Date( System.currentTimeMillis() );     

        cal.setTime( date );     

        return "" +( cal.get( Calendar.MONTH ) + 1 )+"月"+cal.get( Calendar.DAY_OF_MONTH )+"日"+cal.get( Calendar.YEAR );     

    public static String getTime()     

        return "_" + cal.get( Calendar.HOUR_OF_DAY ) + "_" + cal.get( Calendar.MINUTE ) + "_"    

                + cal.get( Calendar.SECOND );     

    public static int getYear()     

        return cal.get( Calendar.YEAR );     

    public static int getMonth()     

        return ( cal.get( Calendar.MONTH ) + 1 );     

    public static int getDay()     

        return cal.get( Calendar.DAY_OF_MONTH );     

    public static final String      gameName    = "Tetris";     

    public static final int         recoreMax   = 8;     

    public static       int[]       success     = new int[recoreMax];     

    public static       String[]    dateTime    = new String[recoreMax];     

    public static       int[]   year    = new int[recoreMax];     

    public static       int[]   month   = new int[recoreMax];     

    public static       int[]   day     = new int[recoreMax];     

    * 讀取存檔記錄    

    */    

    public static void ReadData()     

        RecordStore         store  = null;     

        RecordEnumeration   result = null;     

        byte data[];     

        try      

            store = RecordStore.openRecordStore( gameName, false );     

            result= store.enumerateRecords( null, null, false );     

            data  = result.nextRecord();     

            store.closeRecordStore();     

            ByteArrayInputStream    inputstream = new ByteArrayInputStream( data );     

            DataInputStream         datastream  = new DataInputStream( inputstream );     

            int k;     

            k = datastream.readInt(); // 11備用     

            for(int i=0; i&lt;recoreMax; i++ )     

                success [i] = datastream.readInt();         //分數     

//              dateTime[i] = datastream.readUTF();         //日期     

                year    [i] = datastream.readInt();         //年     

                month   [i] = datastream.readInt();         //月     

                day     [i] = datastream.readInt();         //日     

//----------------2.0--------------              

            k = datastream.readInt(); // 12備用     

        }   catch ( Exception e ) { e.printStackTrace(); }     

        System.out.println("...ReadData...ok");     

    * 寫記錄    

    public static void WriteData()     

        ByteArrayOutputStream   bytestream = new ByteArrayOutputStream();     

        DataOutputStream        datastream = new DataOutputStream( bytestream );     

            int k0=0,k1=1;//保留字     

            datastream.writeInt(k0);     

                datastream.writeInt( success    [i] );          // 分數     

//              datastream.writeUTF( new String( dateTime[i].getBytes(),"UTF-8") ); // 日期     

                datastream.writeInt( year   [i] );      //年     

                datastream.writeInt( month  [i] );      //月     

                datastream.writeInt( day    [i] );      //日     

            datastream.writeInt(k1);     

        RecordStore store = null;     

            RecordStore.deleteRecordStore( gameName );     

        }   catch ( RecordStoreNotFoundException e ) { }     

        catch ( Exception e ) { }     

            store = RecordStore.openRecordStore( gameName, true );     

            store.addRecord( bytestream.toByteArray(), 0, bytestream.toByteArray().length);     

        }   catch ( Exception e ) {  }     

        System.out.println("...WriteData...ok");     

程式代碼部分就這3個類,另外整個工程已經打包上傳,如果還有問題可以在這裡留言,我會經常來看的!

<a href="http://down.51cto.com/data/2358284" target="_blank">附件:http://down.51cto.com/data/2358284</a>

本文轉自 kome2000 51CTO部落格,原文連結:http://blog.51cto.com/kome2000/578555