JAVA游戏编程之三----j2me 手机游戏入门开发--俄罗斯方块_4_增加消除行声音
2009-05-14 14:15
1101 查看
之前的游戏代码中都未加声音,不少网友在做别业设计时要求增加声音,其实声音还是比较好做的!但手机真机上可能会有不同的问题,但在模拟器上一般都没什么问题,所以真机上的问题就具体问题具体分析吧!这里给出一个很简单的声音应用。
在原 俄罗斯方块_3的代码基础上增加一个声音类!
工程文件如附件所示,地址如下:方块4
示例代码如下
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 ) { try { if( m_sounds == null ) return; if( m_sounds.getState() == javax.microedition.media.Player.STARTED ) return; m_currentSoundID = soundID; m_sounds.setMediaTime( 0 ); m_sounds.setLoopCount( loopCount ); m_sounds.start(); Thread.sleep( 50 ); // maybe this can help for sound problems }catch( Exception e ) { e.printStackTrace(); } } private static void stopSound() throws Exception { try { if( m_sounds == null ) return; if( m_sounds.getState() == javax.microedition.media.Player.STARTED ) m_sounds.stop(); if( m_sounds.getState() == javax.microedition.media.Player.PREFETCHED ) m_sounds.deallocate(); m_currentSoundID = -1; }catch( Exception e ) { e.printStackTrace(); } } public static int readFileToMemory( String fileName, byte[] buffer ) { java.io.InputStream file = null; int size; try { file = fileName.getClass().getResourceAsStream( fileName ); size = file.read( buffer ); file.close(); file = null; }catch( Exception e ) { return -1; } return size; } }
使用方法 是在主Canvas类的初始化或者游戏初始化的地方调用 Sound类的initSound()方法,来初始化声音文件,
然后在想要播放的地方调用Sound类的playSound()方法,目前这个简单的例子里只有一个声音,所以参数给啥都一样,如果以后声音多了!就可以用这个参数来区分用户要调用的是那个声音了!这里的用户是相对这个Sound类的使用者,就是程序员,Sound类都是静态方法,这里相对于一个公共的工具类!
如果上述使用方法您没看明白,那就看一下代码
主Canvas类代码如下
view plaincopy to clipboardprint? 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<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) { try { 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>>1, s_height>>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<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<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<4; i++ ) //行 { for( int j=0; j<4; j++ ) //列 { if( (box[box_state] & 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.setColor( gameBG ); g.fillRect( 0, 0, 4*s_box_w, 4*s_box_h ); if( isShowReseau ) //显示格式 { g.setColor( gameColor[0] ); for( int i=0; i<5; i++ ) // | { g.drawLine( i*s_box_h, 0, i*s_box_h, 4*s_box_h ); } for( int j=0; j<5; j++ ) // - { g.drawLine( 0, j*s_box_w, 4*s_box_w, j*s_box_w ); } } for( int i=0; i<4; i++ ) //行 { for( int j=0; j<4; j++ ) //列 { if( (next_box[0] & 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.setColor( gameBG ); 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 >= goDownDelayTime[level] ) { s_box_y++; goDownPreTime = System.currentTimeMillis(); if( !isCanMove() ) { isKeyDown = 0; //没有按下 s_box_y--; setMap(); //将BOX放进map setBox(); //新的BOX } } } private void setMap() { for( int i=0; i<4; i++ ) //行 { for( int j=0; j<4; j++ ) //列 { if( ( box[box_state] & 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<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 >= level_up ) //设置升级 { level %= goDownDelayTime.length; level ++; } } private void paintMap( Graphics g ) { for( int i=0; i<s_box_h_sum; i++ ) //行 { for( int j=0; j<s_box_w_sum; j++ ) //列 { if( map[i][j] > 0 ) //是格子//绘制格子 { g.setColor( gameColor[ map[i][j] ] ); g.fillRect( j*s_box_w, i*s_box_h, s_box_w, s_box_h ); g.setColor( gameBG ); g.drawRect( j*s_box_w+1, i*s_box_h+1, s_box_w-2, s_box_h-2 ); } } } } private boolean isFullLine(int line) //是否一行已经满了 { for( int j=0; j<s_box_w_sum; j++ ) //列 { if( map[line][j] <= 0 ) { return false; } } return true; } private void setNullLine( int line ) //设置地图上的这一行 空 { for( int j=0; j<s_box_w_sum; j++ ) //列 { map[line][j] = 0; } } private void setGoDownMap( int line ) //设置地图line以上的每行都向下移动一行 { for( int i=line; i>0; i-- ) //行 { for( int j=0; j<s_box_w_sum; j++ ) //列 { 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 ) { for( int i=0; i<4; i++ ) //行 { for( int j=0; j<4; j++ ) //列 { if( ( box[box_state] & matrix[i][j] ) == matrix[i][j] ) //是格子 { if( s_box_x+j < 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 > s_box_w_sum-1 ) //右边界检测 { if( act == act_transfiguration )//右边界检测失败 调整 BOX 位置左移动 最多1格 { act_off_x = -1; s_box_x --; if( isCanMove() ) { return true; } else { act_off_x = 0; } } System.out.println( "right s_box_x="+s_box_x+" matrix["+i+"]["+j+"]="+matrix[i][j]); return false; } if( s_box_y+i > s_box_h_sum-1 ) //下边界检测 { System.out.println( "down s_box_y="+s_box_y+" matrix["+i+"]["+j+"]="+matrix[i][j]); return false; } if( map[s_box_y+i][s_box_x+j] > 0 ) //地图格子检测 { System.out.println( "map s_box_y="+s_box_y+" matrix["+i+"]["+j+"]="+matrix[i][j]); return false; } } } } return true; } 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<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 --; } break; case LEFT: //向左移动BOX act_off_x = 0; //恢复BOX旋转位置偏移为0 isKeyDown = 0; //0没有按下 s_box_x --; if( !isCanMove() ) s_box_x ++; break; case RIGHT: //向右移动BOX act_off_x = 0; //恢复BOX旋转位置偏移为0 isKeyDown = 0; //0没有按下 s_box_x ++; if( !isCanMove() ) s_box_x --; break; case 53: //数字5键 if( isGameOver ) //游戏结束 initGame(); //重新游戏 break; case 42: if( isGameOver ) //游戏结束 // System.exit(0); //退出游戏 Tetris.s_midlet.destroyApp(true); break; case 48: setBox(); //新的BOX break; case 49: //是否显示网格 isShowReseau = !isShowReseau; break; } 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 ); switch( 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; //释放按键 // return true; } // public boolean mouseDown(Event evt, int x, int y) // { // try // { //// System.out.println( "x="+x+" y="+y ); // }catch( Exception e){e.printStackTrace();} //// this.repaint(); // return true; // } // public boolean mouseMove(Event evt, int x, int y) // { // try // { // //System.out.println( "x="+x+" y="+y ); // }catch( Exception e){e.printStackTrace();} // return true; // } // 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<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) { try { 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>>1, s_height>>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<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<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<4; i++ ) //行 { for( int j=0; j<4; j++ ) //列 { if( (box[box_state] & 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.setColor( gameBG ); g.fillRect( 0, 0, 4*s_box_w, 4*s_box_h ); if( isShowReseau ) //显示格式 { g.setColor( gameColor[0] ); for( int i=0; i<5; i++ ) // | { g.drawLine( i*s_box_h, 0, i*s_box_h, 4*s_box_h ); } for( int j=0; j<5; j++ ) // - { g.drawLine( 0, j*s_box_w, 4*s_box_w, j*s_box_w ); } } for( int i=0; i<4; i++ ) //行 { for( int j=0; j<4; j++ ) //列 { if( (next_box[0] & 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.setColor( gameBG ); 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 >= goDownDelayTime[level] ) { s_box_y++; goDownPreTime = System.currentTimeMillis(); if( !isCanMove() ) { isKeyDown = 0; //没有按下 s_box_y--; setMap(); //将BOX放进map setBox(); //新的BOX } } } private void setMap() { for( int i=0; i<4; i++ ) //行 { for( int j=0; j<4; j++ ) //列 { if( ( box[box_state] & 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<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 >= level_up ) //设置升级 { level %= goDownDelayTime.length; level ++; } } private void paintMap( Graphics g ) { for( int i=0; i<s_box_h_sum; i++ ) //行 { for( int j=0; j<s_box_w_sum; j++ ) //列 { if( map[i][j] > 0 ) //是格子//绘制格子 { g.setColor( gameColor[ map[i][j] ] ); g.fillRect( j*s_box_w, i*s_box_h, s_box_w, s_box_h ); g.setColor( gameBG ); g.drawRect( j*s_box_w+1, i*s_box_h+1, s_box_w-2, s_box_h-2 ); } } } } private boolean isFullLine(int line) //是否一行已经满了 { for( int j=0; j<s_box_w_sum; j++ ) //列 { if( map[line][j] <= 0 ) { return false; } } return true; } private void setNullLine( int line ) //设置地图上的这一行 空 { for( int j=0; j<s_box_w_sum; j++ ) //列 { map[line][j] = 0; } } private void setGoDownMap( int line ) //设置地图line以上的每行都向下移动一行 { for( int i=line; i>0; i-- ) //行 { for( int j=0; j<s_box_w_sum; j++ ) //列 { 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 ) { for( int i=0; i<4; i++ ) //行 { for( int j=0; j<4; j++ ) //列 { if( ( box[box_state] & matrix[i][j] ) == matrix[i][j] ) //是格子 { if( s_box_x+j < 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 > s_box_w_sum-1 ) //右边界检测 { if( act == act_transfiguration )//右边界检测失败 调整 BOX 位置左移动 最多1格 { act_off_x = -1; s_box_x --; if( isCanMove() ) { return true; } else { act_off_x = 0; } } System.out.println( "right s_box_x="+s_box_x+" matrix["+i+"]["+j+"]="+matrix[i][j]); return false; } if( s_box_y+i > s_box_h_sum-1 ) //下边界检测 { System.out.println( "down s_box_y="+s_box_y+" matrix["+i+"]["+j+"]="+matrix[i][j]); return false; } if( map[s_box_y+i][s_box_x+j] > 0 ) //地图格子检测 { System.out.println( "map s_box_y="+s_box_y+" matrix["+i+"]["+j+"]="+matrix[i][j]); return false; } } } } return true; } 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<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 --; } break; case LEFT: //向左移动BOX act_off_x = 0; //恢复BOX旋转位置偏移为0 isKeyDown = 0; //0没有按下 s_box_x --; if( !isCanMove() ) s_box_x ++; break; case RIGHT: //向右移动BOX act_off_x = 0; //恢复BOX旋转位置偏移为0 isKeyDown = 0; //0没有按下 s_box_x ++; if( !isCanMove() ) s_box_x --; break; case 53: //数字5键 if( isGameOver ) //游戏结束 initGame(); //重新游戏 break; case 42: if( isGameOver ) //游戏结束 // System.exit(0); //退出游戏 Tetris.s_midlet.destroyApp(true); break; case 48: setBox(); //新的BOX break; case 49: //是否显示网格 isShowReseau = !isShowReseau; break; } 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 ); switch( 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; //释放按键 // return true; } // public boolean mouseDown(Event evt, int x, int y) // { // try // { //// System.out.println( "x="+x+" y="+y ); // }catch( Exception e){e.printStackTrace();} //// this.repaint(); // return true; // } // public boolean mouseMove(Event evt, int x, int y) // { // try // { // //System.out.println( "x="+x+" y="+y ); // }catch( Exception e){e.printStackTrace();} // return true; // } // 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类
view plaincopy to clipboardprint? package code; /////////////////////////////////////////////////////////////////////////////////////////////////// /** * 俄罗斯方块 * 高雷 * 2007年11月30日 */ /////////////////////////////////////////////////////////////////////////////////////////////////// import javax.microedition.midlet.*; //j2me MIDlet程序必须继承MIDlet类,所以要引入此包 import javax.microedition.lcdui.*; //Display这个类所在包 import javax.microedition.rms.*; import java.io.*; 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() { date = new Date( System.currentTimeMillis() ); cal.setTime( date ); return "_" + cal.get( Calendar.HOUR_OF_DAY ) + "_" + cal.get( Calendar.MINUTE ) + "_" + cal.get( Calendar.SECOND ); } public static int getYear() { date = new Date( System.currentTimeMillis() ); cal.setTime( date ); return cal.get( Calendar.YEAR ); } public static int getMonth() { date = new Date( System.currentTimeMillis() ); cal.setTime( date ); return ( cal.get( Calendar.MONTH ) + 1 ); } public static int getDay() { date = new Date( System.currentTimeMillis() ); cal.setTime( date ); 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<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 ); try { int k0=0,k1=1;//保留字 datastream.writeInt(k0); for(int i=0; i<recoreMax; i++ ) { 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); } catch ( Exception e ) { e.printStackTrace(); } RecordStore store = null; try { RecordStore.deleteRecordStore( gameName ); } catch ( RecordStoreNotFoundException e ) { } catch ( Exception e ) { } try { store = RecordStore.openRecordStore( gameName, true ); store.addRecord( bytestream.toByteArray(), 0, bytestream.toByteArray().length); store.closeRecordStore(); } catch ( Exception e ) { } System.out.println("...WriteData...ok"); } }
程序代码部分就这3个类,另外整个工程已经打包上传,如果还有问题可以在这里留言,我会经常来看的!
相关文章推荐
- JAVA游戏编程之三----j2me 手机游戏入门开发--俄罗斯方块_3_增加成绩记录
- JAVA游戏编程之三----j2me 手机游戏入门开发--俄罗斯方块_5_使用LUA脚本写游戏
- JAVA游戏编程之二----j2me MIDlet 手机游戏入门开发--贪吃蛇_1
- JAVA游戏编程之三----j2me 手机游戏入门开发--俄罗斯方块_2
- JAVA游戏编程之二----j2me MIDlet 手机游戏入门开发--扫雷(3)-带线程--仿windows扫雷
- JAVA游戏编程之二----j2me MIDlet 手机游戏入门开发--扫雷(2)-不含线程
- JAVA游戏编程之二----j2me MIDlet 手机游戏入门开发--贪吃蛇
- [java游戏开发快速入门]俄罗斯方块游戏开发开篇
- [java游戏开发快速入门]俄罗斯方块游戏开发开篇
- JAVA游戏编程之三----j2se 手机游戏入门开发--俄罗斯方块_1
- java开发学习俄罗斯方块游戏
- Java开发的游戏之四 俄罗斯方块 完整源代码
- 用Eclipse开发J2ME手机游戏入门(创建Hello)》
- J2ME移动2D图形开发快速入门-Java基础-Java-编程开发
- J2me Game开发技巧:手机游戏中声音播放及处理
- j2me手机游戏编程第一课(开发环境搭建和第一个MIDlet程序 视频)
- 用Eclipse开发J2ME手机游戏入门讲座
- 用Eclipse开发J2ME手机游戏入门讲座(续)
- java swing开发俄罗斯方块游戏
- 用Eclipse开发J2ME手机游戏入门讲座