作者:雷神
QQ:38929568
QQ群:28048051JAVA游戏编程(满) 28047782(满) 50761834(新开)
声明:本人发表的代码全部可以用来学习,如果需要作商业用途,请及时与作者联系。
本例为J2SE游戏开发的经典游戏--俄罗斯方块,
方向键 上下左右ASDW2468都可以游戏,0更换方块,1显示隐藏网格!game over 时5键重新开始,*键退出游戏
游戏图片:
工程文件如附件所示,地址如下:
方块2
代码如下:
- package code;
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- /** *//**
- * 俄罗斯方块
- * 高雷
- * 2007年11月30日
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- import javax.microedition.midlet.*; //j2me MIDlet程序必须继承MIDlet类,所以要引入此包
- import javax.microedition.lcdui.*; //Display这个类所在包
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- public class Tetris extends MIDlet
- ...{
- static Tetris s_midlet; //MIDlet类的静态对象,方便实用 MIDlet类方法
- static Display s_display = null;//用来显示 Canvas
- static cGame s_game = null; //Canvas类对象,主要实现游戏的类
- public Tetris()
- ...{
- s_midlet = this;
- }
- /** *//**
- * 程序开始 系统会调用这个函数
- * 也有些手机 可以把程序初始化部分放到构造函数里,这连个地方应视手机的不同而定!
- */
- public void startApp()
- ...{
- if (s_display == null)
- ...{
- s_display = Display.getDisplay(this);//创建Display对象,参数是MIDlet类对象,也就是我们当前写的这个Minesweeper类
- }
- if (s_game == null)
- ...{
- s_game = new cGame(); //创建 Canvas对象
- s_display.setCurrent(s_game); //把Canvas对象设置成当前显示
- }
- else
- ...{
- s_display.setCurrent(s_game);
- }
- }
- /** *//**
- * 程序暂停 系统会自动调用这个函数,不是所有手机都支持,
- * 手机在接到中断,如 来电,来短信时候会调用这个函数,这个函数 通常是空的!
- */
- public void pauseApp()
- ...{
- }
- /** *//**
- * 程序关闭 系统会调用这个函数,如果希望关闭程序的时候保存数据,可在这个函数里添加保存数据的方法
- * 比如游戏进行中,按了关机键,程序就会调用这个函数,也可以在程序中调用这个函数来结束游戏!
- */
- public void destroyApp(boolean unconditional)
- ...{
- notifyDestroyed();
- }
- }
程序主要逻辑代码类
- 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 cGame 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 cGame()
- ...{
- 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 ); //设置画布
- 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++;
- }
- }
- 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 boolean isCanMove()
- ...{
- 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 ) //左边界检测
- ...{
- 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 ) //右边界检测
- ...{
- 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 )
- 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;
- if( !isCanMove() )
- ...{
- box_state --;
- if( box_state<0 )
- box_state = 3;
- }
- break;
- case DOWN: //向下移动
- if( isKeyDown == 2 )
- isKeyDown = 1;
- if( isKeyDown == 1 )
- ...{
- s_box_y ++;
- if( !isCanMove() )
- s_box_y --;
- }
- break;
- case LEFT: //向左移动BOX
- isKeyDown = 0; //0没有按下
- s_box_x --;
- if( !isCanMove() )
- s_box_x ++;
- break;
- case RIGHT: //向右移动BOX
- 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()
- ...{
- 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);
- // }
- }
附件:http://down.51cto.com/data/2358282
本文转自 kome2000 51CTO博客,原文链接:http://blog.51cto.com/kome2000/578539