您的位置:首页 > 编程语言 > Java开发

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个类,另外整个工程已经打包上传,如果还有问题可以在这里留言,我会经常来看的!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: