作者:雷神
QQ:38929568
QQ群:28048051JAVA游戏编程(满) 28047782(满) 50761834(新开)

声明:本人发表的代码全部可以用来学习,如果需要作商业用途,请及时与作者联系。

本例为J2SE游戏开发的经典游戏--俄罗斯方块,

方向键 上下左右ASDW2468都可以游戏,0更换方块,1显示隐藏网格!game over 5键重新开始,*退出游戏

游戏图片:

工程文件如附件所示,地址如下: 方块1

代码如下:


   
   
  1. package code;  
  2.  
  3. import java.awt.*;  
  4. //import java.awt.BorderLayout;  
  5. import java.awt.Canvas;  
  6. import java.awt.event.*;  
  7. import javax.swing.*;  
  8. import java.util.Random;  
  9.  
  10. /** *//**  
  11.  * 俄罗斯方块  
  12.  * 高雷  
  13.  * 2007年11月30日  
  14.  */ 
  15. public class Tetris extends Canvas implements Runnable   
  16. ...{  
  17.     private Random rand;  
  18.     private Thread thread;  
  19.     private Graphics    gb;  
  20.     private Image        buffer;  
  21.     private Image         gameOverImg;                    //游戏结束  
  22.     private static final int s_width      = 240;  
  23.     private static final int s_height     = 320;  
  24.     private static final int s_box_w      = 16;  
  25.     private static final int s_box_h      = 16;  
  26.     private static final int s_box_w_sum     = 10;        //操作区域宽 格子数  
  27.     private static final int s_box_h_sum     = 20;        //操作区域高 格子数  
  28.     private static final int s_line_between_x = s_box_w * s_box_w_sum;//分割线x位置  
  29.  
  30.     public static final int  UP     = -1;  
  31.     public static final int  DOWN     = -2;  
  32.     public static final int  LEFT     = -3;  
  33.     public static final int  RIGHT     = -4;  
  34.       
  35.     public static final int  init_x         = 3;        //当前方块初始化坐标X  
  36.     public static final int  init_y         = 0;        //当前方块初始化坐标y  
  37.       
  38.     public static int     s_box_x                = init_x;    //当前方块坐标X  
  39.     public static int     s_box_y                = init_y;    //当前方块坐标Y  
  40.     private static int    level                = 1;        //等级  
  41.     private static int    success                = 0;        //得分  
  42.     private static long goDownDelayTime[]    = //1800;    //下降延迟时间  
  43.     ...{  
  44.         1000,    900,    800,    700,  
  45.         600,    500,    400,  
  46.         300,    200,    100 
  47.     };  
  48.     private static int    level_up            = (int)(goDownDelayTime[0]-goDownDelayTime[level]);        //升级成绩  
  49.     private static boolean isShowReseau        = true;        //是否现实网格  
  50.     private static short s_next_box            = 0;        //下一个方块编号  
  51.     private static short boxColor;                        //当前box的颜色  
  52.     private static final Color gameBG        = new Color( 0x333333 );    //游戏区域背景颜色  
  53.     private static final Color gameColor[]    = new Color[]  
  54.     ...{  
  55.         new Color( 0x444444 ),    //网格颜色  
  56.         new Color( 0xEEEEEE ),    //方块颜色  
  57.         new Color( 0xEE0000 ),  
  58.         new Color( 0x00EE00 ),  
  59.         new Color( 0x0000EE ),  
  60.         new Color( 0xEE00EE ),  
  61.         new Color( 0xEEEE00 ),  
  62.         new Color( 0x00EEEE )  
  63.     };  
  64.     private static final short box_sum[][] = new short[][]    //所有方块图形  
  65.     ...{  
  66.         ...{ 0x06600x06600x06600x0660 },  
  67.         ...{ 0x22220x00F00x22220x00F0 },  
  68.         ...{ 0x02640x06300x02640x0630 },  
  69.         ...{ 0x04620x03600x04620x0360 },  
  70.         ...{ 0x02E00x44600x07400x0622 },  
  71.         ...{ 0x0E200x22600x04700x0644 },  
  72.         ...{ 0x04640x00E40x04C40x04E0 }  
  73.     };  
  74.  
  75.     private static short next_box[] = new short[]...{ 0x06600x06600x06600x0660 };   
  76.     private static short box[]          = new short[]...{ 0x06600x06600x06600x0660 };  
  77.     private static short map[][];        //地图  
  78.     private static short box_state  = 0;//当前BOX的状态//旋转方向  
  79.     private static short matrix[][] =    //定义矩阵用来计算出box_sum的方块  
  80.     ...{  
  81.         ...{ 0x10000x01000x00100x0001 },  
  82.         ...{ 0x20000x02000x00200x0002 },  
  83.         ...{ 0x40000x04000x00400x0004 },  
  84.         ...{ (short)0x80000x08000x00800x0008 }  
  85.     };  
  86.  
  87.     public Tetris()  
  88.     ...{  
  89.         rand = new Random( System.currentTimeMillis() );  
  90.           
  91.         try 
  92.         ...{  
  93.             gameOverImg = Toolkit.getDefaultToolkit().getImage("src/pics/laser.png");  
  94.         }catch(Exception e)...{}  
  95.           
  96.         setSize( s_width, s_height );    //设置画布  
  97.         initGame();                        //游戏初始化  
  98.         thread  = new Thread(this);  
  99.         thread.start();  
  100.     }  
  101.       
  102.     private void initGame()  
  103.     ...{  
  104.         level        = 1;                //等级  
  105.         success        = 0;                //得分  
  106.         map     = new short[s_box_h_sum][s_box_w_sum];  
  107.         setNextBox();                    //设置下一个BOX  
  108.         setBox();                        //将下一个BOX设置成当前BOX  
  109.         setGameOver( false );            //恢复游戏  
  110.     }  
  111.       
  112.     private void setBox()                //将next_box设置成当前可控制box  
  113.     ...{  
  114.         box_state         = 0;                                        //box 状态  
  115.         s_box_x            = init_x;                                    //当前方块坐标X  
  116.         s_box_y            = init_y;                                    //当前方块坐标Y  
  117.         boxColor        = s_next_box;                                //设置当前BOX颜色  
  118.         System.arraycopy( next_box, 0, box, 0, next_box.length );    //box = next_box  
  119.         goDownPreTime     = System.currentTimeMillis();                //设置好当前BOX后 计时  
  120.         setNextBox();                                                //设置下一个BOX  
  121.         if( !isCanMove() )  
  122.         ...{  
  123.             setGameOver( true );  
  124.         }  
  125.     }  
  126.  
  127.     public static boolean isGameOver = false;  
  128.     public static long updatas     = 0;  
  129.     public static long fps         = 0;  
  130.     private long     startTime, beginTime, endTime;  
  131.     private long     delay         = 25;  
  132.     private long     upTime         = 25;  
  133.     public void run()   
  134.     ...{  
  135.         while ( true )   
  136.         ...{  
  137.             try 
  138.             ...{  
  139.                 beginTime = System.currentTimeMillis();  
  140.                 updatas++;  
  141.                 updata( updatas );  
  142.                 repaint();  
  143.                 endTime = System.currentTimeMillis();  
  144.                 upTime  = endTime-beginTime;  
  145.                 if( upTime<delay )  
  146.                 ...{  
  147.                     fps = 1000/delay;  
  148.                     thread.sleep(delay-upTime);  
  149.                 }  
  150.                 else 
  151.                     fps = 1000/upTime;  
  152.             }catch(Exception e)...{ }  
  153.         }  
  154.     }  
  155.     void setGameOver( boolean _isGameOver )  
  156.     ...{  
  157.         isGameOver = _isGameOver;  
  158.     }  
  159.     public void updata( long updatas )  
  160.     ...{  
  161.  
  162.     }  
  163.     public void update(Graphics g)   
  164.     ...{  
  165.         paint(g);  
  166.     }  
  167.     public static int     offx     = 2;  
  168.     public static int     offy     = 2;  
  169.     public void paint(Graphics g)  
  170.     ...{  
  171.         try 
  172.         ...{  
  173.             if( buffer == null )  
  174.             ...{  
  175.                 buffer = createImage( s_width, s_height );    //设置画布缓冲区  
  176.                 gb = buffer.getGraphics();                    //得到绘图设备  
  177.             }  
  178. //            gb.translate( offx, offy );  
  179.             gb.setColor( new Color( 0x0 ) );                //初始化 画布颜色  
  180.             gb.setClip ( 00, s_width, s_height);            //初始化 画布区域  
  181.             gb.fillRect( 00, s_width, s_height);            //初始化 画布填充  
  182.             paintReseau( gb );                                //绘制网格  
  183.             paintNextBox( gb );                                //绘制下一BOX  
  184.             paintMap( gb );                                    //绘制地图上不可以动BOX  
  185.             paintBox( gb, s_box_x, s_box_y );                //绘制当前可控制BOX  
  186.             gb.setColor( new Color( 0xFF3333 ) );                            //分割线颜色  
  187.             gb.drawLine( s_line_between_x, 0, s_line_between_x, s_height );    //分割线  
  188.             gb.drawString( "FPS:"+fps,             s_line_between_x+10,10 );    //祯数  
  189.             gb.drawString( "等级:"+level,         s_line_between_x+10,30 );    //等级  
  190.             gb.drawString( "得分:"+success,         s_line_between_x+10,50 );    //分数  
  191.               
  192.             if( isGameOver )  
  193.             ...{  
  194.                 gb.drawImage( gameOverImg, (getWidth()-offx-gameOverImg.getWidth(null))/2, (getHeight()-gameOverImg.getHeight(null))/2 , null );  
  195.             }  
  196. //            gb.translate( -offx, -offy );  
  197.         }  
  198.         catch(Exception e)  
  199.         ...{   
  200.             System.out.println("err at paint.e====="+e);  
  201.         }  
  202.         g.drawImage( buffer, offx, offy, null);                    //将画布缓冲区绘制到屏幕//偏移 (2,2)  
  203.     }  
  204.       
  205.     private void paintReseau( Graphics g )                    //绘制网格  
  206.     ...{  
  207.         g.setColor( gameBG );  
  208.         g.fillRect( 00, s_line_between_x, s_height );  
  209.         if( isShowReseau )  
  210.         ...{  
  211.             g.setColor( gameColor[0] );  
  212.             forint i=0; i<s_line_between_x/s_box_w; i++ )    // |  
  213.             ...{  
  214.                 g.drawLine( i*s_box_h, 0, i*s_box_h, s_height );  
  215.             }  
  216.             forint j=0; j<s_height/s_box_h; j++ )            // -  
  217.             ...{  
  218.                 g.drawLine( 0, j*s_box_w, s_line_between_x, j*s_box_w );  
  219.             }  
  220.         }  
  221.     }  
  222.     private void paintBox( Graphics g, int off_x, int off_y )  
  223.     ...{  
  224.         forint i=0; i<4; i++ )        //行  
  225.         ...{  
  226.             forint j=0; j<4; j++ )    //列  
  227.             ...{  
  228.                 if( (box[box_state] & matrix[i][j]) == matrix[i][j] )  
  229.                 ...{  
  230.                     g.setColor( gameColor[ boxColor ] );  
  231.                     g.fillRect( (off_x+j)*s_box_w, (off_y+i)*s_box_h, s_box_w, s_box_h );  
  232.  
  233.                     g.setColor( gameBG );  
  234.                     g.drawRect( (off_x+j)*s_box_w+1, (off_y+i)*s_box_h+1, s_box_w-2, s_box_h-2 );  
  235.                 }  
  236.             }  
  237.         }  
  238.         goDown();                        //BOX是否下降  
  239.     }  
  240.     private void paintNextBox( Graphics g )  
  241.     ...{  
  242.         int off_x = s_line_between_x+( s_width - s_line_between_x - 4*s_box_w )/2;  
  243.         int off_y = s_height/2;  
  244.           
  245.         g.translate( off_x, off_y );  
  246.         g.setColor( gameBG );  
  247.         g.fillRect( 004*s_box_w, 4*s_box_h );  
  248.           
  249.         if( isShowReseau )                //显示格式  
  250.         ...{  
  251.             g.setColor( gameColor[0] );  
  252.             forint i=0; i<5; i++ )    // |  
  253.             ...{  
  254.                 g.drawLine( i*s_box_h, 0, i*s_box_h, 4*s_box_h );  
  255.             }  
  256.             forint j=0; j<5; j++ )    // -  
  257.             ...{  
  258.                 g.drawLine( 0, j*s_box_w, 4*s_box_w, j*s_box_w );  
  259.             }  
  260.         }  
  261.         forint i=0; i<4; i++ )        //行  
  262.         ...{  
  263.             forint j=0; j<4; j++ )    //列  
  264.             ...{  
  265.                 if( (next_box[0] & matrix[i][j]) == matrix[i][j] )  
  266.                 ...{  
  267.                     g.setColor( gameColor[ s_next_box ] );  
  268.                     g.fillRect( j*s_box_w, i*s_box_h, s_box_w, s_box_h );  
  269.  
  270.                     g.setColor( gameBG );  
  271.                     g.drawRect( j*s_box_w+1, i*s_box_h+1, s_box_w-2, s_box_h-2 );  
  272.                 }  
  273.             }  
  274.         }  
  275.         g.translate( -off_x, -off_y );  
  276.     }  
  277.  
  278.     private long goDownPreTime     = 0;    //上次下降时间  
  279.     private long currTime         = 0;    //当前时间  
  280.     private void goDown()                //当前BOX下降  
  281.     ...{  
  282.         if( isGameOver )    //游戏结束  
  283.             return;  
  284.         //isKeyDown按了向下移动就需要检查 不需要时间  
  285.         if( isKeyDown==1 || System.currentTimeMillis() - goDownPreTime >= goDownDelayTime[level] )  
  286.         ...{  
  287.             s_box_y++;  
  288.             goDownPreTime = System.currentTimeMillis();  
  289.             if( !isCanMove() )  
  290.             ...{  
  291.                 isKeyDown = 0;    //没有按下  
  292.                 s_box_y--;  
  293.                 setMap();        //将BOX放进map   
  294.                 setBox();        //新的BOX  
  295.             }  
  296.         }  
  297.     }  
  298.       
  299.     private void setMap()  
  300.     ...{  
  301.         forint i=0; i<4; i++ )        //行  
  302.         ...{  
  303.             forint j=0; j<4; j++ )    //列  
  304.             ...{  
  305.                 if( ( box[box_state] & matrix[i][j] ) == matrix[i][j] )    //是格子  
  306.                 ...{  
  307.                     map[s_box_y+i][s_box_x+j] = boxColor;  
  308.                 }  
  309.             }  
  310.         }  
  311.         //检测是否可以消去一行  
  312.         int line_success = 0;  
  313.         forint i=0; i<s_box_h_sum; i++ )        //行  
  314.         ...{  
  315.             if( isFullLine( i ) )                //这行可以消去  
  316.             ...{  
  317.                 setNullLine( i );                //设置第i行为空  
  318.                 setGoDownMap( i );                //地图第i行以上的向下移动一行  
  319.                 line_success++;  
  320.             }  
  321.         }  
  322.         success += line_success*line_success;    //设置得分  
  323.         level_up = (int)(goDownDelayTime[0]-goDownDelayTime[level]);  
  324.         if( success >= level_up )                //设置升级  
  325.         ...{  
  326.             level %= goDownDelayTime.length;  
  327.             level ++;  
  328.         }  
  329.     }  
  330.  
  331.     private void paintMap( Graphics g )  
  332.     ...{  
  333.         forint i=0; i<s_box_h_sum; i++ )        //行  
  334.         ...{  
  335.             forint j=0; j<s_box_w_sum; j++ )    //列  
  336.             ...{  
  337.                 if( map[i][j] > 0 )                //是格子//绘制格子  
  338.                 ...{  
  339.                     g.setColor( gameColor[ map[i][j] ] );  
  340.                     g.fillRect( j*s_box_w, i*s_box_h, s_box_w, s_box_h );      
  341.                       
  342.                     g.setColor( gameBG );  
  343.                     g.drawRect( j*s_box_w+1, i*s_box_h+1, s_box_w-2, s_box_h-2 );  
  344.                 }  
  345.             }  
  346.         }  
  347.     }  
  348.       
  349.     private boolean isFullLine(int line)    //是否一行已经满了  
  350.     ...{  
  351.         forint j=0; j<s_box_w_sum; j++ )    //列  
  352.         ...{  
  353.             if( map[line][j] <= 0 )  
  354.             ...{  
  355.                 return false;  
  356.             }  
  357.         }  
  358.         return true;  
  359.     }  
  360.       
  361.     private void  setNullLine( int line )    //设置地图上的这一行 空  
  362.     ...{  
  363.         forint j=0; j<s_box_w_sum; j++ )    //列  
  364.         ...{  
  365.             map[line][j] = 0;  
  366.         }      
  367.     }  
  368.     private void setGoDownMap( int line )    //设置地图line以上的每行都向下移动一行  
  369.     ...{  
  370.         forint i=line; i>0; i-- )            //行  
  371.         ...{  
  372.             forint j=0; j<s_box_w_sum; j++ )    //列  
  373.             ...{  
  374.                 map[i][j] = map[i-1][j];     //向下移动一行  
  375.             }  
  376.         }  
  377.     }  
  378.       
  379.     private boolean isCanMove()  
  380.     ...{  
  381.         forint i=0; i<4; i++ )        //行  
  382.         ...{  
  383.             forint j=0; j<4; j++ )    //列  
  384.             ...{  
  385.                 if( ( box[box_state] & matrix[i][j] ) == matrix[i][j] )    //是格子  
  386.                 ...{  
  387.                     if( s_box_x+j < 0 )                //左边界检测  
  388.                     ...{  
  389.                         System.out.println( "left s_box_x="+s_box_x+" matrix["+i+"]["+j+"]="+matrix[i][j]);  
  390.                         return false;  
  391.                     }  
  392.                     if( s_box_x+j > s_box_w_sum-1 )    //右边界检测  
  393.                     ...{  
  394.                         System.out.println( "right s_box_x="+s_box_x+" matrix["+i+"]["+j+"]="+matrix[i][j]);  
  395.                         return false;  
  396.                     }  
  397.                     if( s_box_y+i > s_box_h_sum-1 )    //下边界检测  
  398.                     ...{  
  399.                         System.out.println( "down s_box_y="+s_box_y+" matrix["+i+"]["+j+"]="+matrix[i][j]);  
  400.                         return false;  
  401.                     }  
  402.                     //地图格子检测  
  403.                     if( map[s_box_y+i][s_box_x+j] > 0 )  
  404.                         return false;  
  405.                 }  
  406.             }  
  407.         }  
  408.         return true;  
  409.     }  
  410.     private short isKeyDown = 0;    //0没有按下,1按下,2抬起  
  411.     public boolean keyDown(Event evt, int key)  
  412.     ...{  
  413.         key = getKeyCode( key );  
  414.         switch( key )  
  415.         ...{  
  416.             case UP:                //顺时针旋转  
  417.                 isKeyDown = 0;        //0没有按下  
  418.                 box_state ++;  
  419.                 box_state %= 4;  
  420.                 if( !isCanMove() )  
  421.                 ...{  
  422.                     box_state --;  
  423.                     if( box_state<0 )  
  424.                         box_state = 3;  
  425.                 }  
  426.             break;  
  427.             case DOWN:                //向下移动  
  428.                 if( isKeyDown == 2 )  
  429.                     isKeyDown = 1;  
  430.                 if( isKeyDown == 1 )  
  431.                 ...{  
  432.                     s_box_y ++;   
  433.                     if( !isCanMove() )  
  434.                         s_box_y --;  
  435.                 }  
  436.             break;  
  437.             case LEFT:                //向左移动BOX  
  438.                 isKeyDown = 0;        //0没有按下  
  439.                 s_box_x --;  
  440.                 if( !isCanMove() )  
  441.                     s_box_x ++;      
  442.             break;  
  443.             case RIGHT:                //向右移动BOX  
  444.                 isKeyDown = 0;        //0没有按下  
  445.                 s_box_x ++;  
  446.                 if( !isCanMove() )  
  447.                     s_box_x --;  
  448.             break;  
  449.             case 53:                //数字5键  
  450.                 if( isGameOver )    //游戏结束  
  451.                     initGame();        //重新游戏  
  452.             break;  
  453.             case 42:  
  454.                 if( isGameOver )    //游戏结束  
  455.                     System.exit(0);    //退出游戏  
  456.             break;  
  457.             case 48:  
  458.                 setBox();            //新的BOX  
  459.             break;  
  460.             case 49:                //是否显示网格  
  461.                 isShowReseau = !isShowReseau;  
  462.             break;  
  463.         }  
  464.         repaint();                    //重新绘制屏幕  
  465.         return true;  
  466.     }  
  467.       
  468.     public void setNextBox()  
  469.     ...{  
  470.         s_next_box = (short)rand.nextInt( box_sum.length );  
  471.         System.arraycopy( box_sum[s_next_box], 0, next_box, 0, next_box.length );  
  472.         s_next_box++;  
  473.     }  
  474.  
  475.     private int getKeyCode( int key )  
  476.     ...{  
  477.         System.out.println( "key="+key );  
  478.         switch( key )  
  479.         ...{  
  480.             case 1004:     // up  
  481.             case 119:     // w  
  482.             case 87:     // W  
  483.             case 50:     // 2  
  484.             return UP;  
  485.  
  486.             case 1005:     // down  
  487.             case 115:     // s  
  488.             case 83:     // S  
  489.             case 56:     // 8  
  490.             return DOWN;  
  491.  
  492.             case 1006:     // left  
  493.             case 97:     // a  
  494.             case 65:     // A  
  495.             case 52:     // 4  
  496.             return LEFT;  
  497.  
  498.             case 1007:     // right  
  499.             case 100:     // d  
  500.             case 68:     // D  
  501.             case 54:     // 6  
  502.             return RIGHT;  
  503.             default:  
  504.             return key;  
  505.         }  
  506.     }  
  507.     public boolean keyUp(Event evt, int key)   
  508.     ...{  
  509.         isKeyDown = 2;    //释放按键  
  510.         return true;  
  511.     }  
  512. //    public boolean mouseDown(Event evt, int x, int y)  
  513. //    {  
  514. //        try  
  515. //        {  
  516. ////            System.out.println( "x="+x+" y="+y );  
  517. //        }catch( Exception e){e.printStackTrace();}  
  518. ////        this.repaint();  
  519. //        return true;  
  520. //    }  
  521. //    public boolean mouseMove(Event evt, int x, int y)  
  522. //    {  
  523. //        try  
  524. //        {  
  525. //            //System.out.println( "x="+x+" y="+y );  
  526. //        }catch( Exception e){e.printStackTrace();}  
  527. //        return true;  
  528. //    }  
  529.     public static void main(String[] args)   
  530.     ...{  
  531.         JFrame frame = new JFrame("俄罗斯方块 北京|雷神 QQ:38929568");  
  532.         final Tetris dc = new Tetris();  
  533.         frame.getContentPane().add(dc, BorderLayout.CENTER);  
  534.  
  535. //        JButton button = new JButton("刷新");  
  536. //        button.addActionListener(new ActionListener()   
  537. //        {  
  538. //            public void actionPerformed(ActionEvent e)   
  539. //            {  
  540. //                dc.repaint();  
  541. //            }  
  542. //        });  
  543. //        frame.getContentPane().add(button, BorderLayout.SOUTH);  
  544.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  545.         frame.setSize(dc.s_width+10, dc.s_height+30);  
  546.         frame.setVisible(true);  
  547.     }