<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<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>>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.fillRect( 0, 0, 4*s_box_w, 4*s_box_h );
if( isShowReseau ) //顯示格式
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 );
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.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 >= 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] & 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 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 );
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 ) //設定地圖上的這一行 空
map[line][j] = 0;
}
private void setGoDownMap( int line ) //設定地圖line以上的每行都向下移動一行
for( int i=line; i>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 < 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 --;
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 > 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] > 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<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<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>>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.fillRect( 0, 0, 4*s_box_w, 4*s_box_h );
if( isShowReseau ) //顯示格式
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 );
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.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()
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 j=0; j<s_box_w_sum; j++ ) //列
if( map[i][j] > 0 ) //是格子//繪制格子
g.setColor( gameColor[ map[i][j] ] );
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 ) //設定地圖上的這一行 空
map[line][j] = 0;
private void setGoDownMap( int line ) //設定地圖line以上的每行都向下移動一行
for( int i=line; i>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 < 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 --;
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 > 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] > 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<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<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