Java编程打砖块游戏

开发 开发工具
创建游戏需要的砖块,砖块的行数和每行的数量都是确定的(NBRICK_ROWS,NBRICKS_PER_ROW),最上一排砖块距窗口顶部距离 (BRICK_Y_OFFSET)。然后是颜色的填充,利用行数判断所需的颜色。

初始需要定义的一些常量,和使用的库。

  1. import acm.graphics.*;  
  2.  import acm.program.*;  
  3.  import acm.util.*;  
  4.  import java.applet.*;  
  5.  import java.awt.*;  
  6.  import java.awt.event.*;  
  7.  public class Breakout extends GraphicsProgram {  
  8.  /** Width and height of application window in pixels */ 
  9.      public static final int APPLICATION_WIDTH = 400;  
  10.      public static final int APPLICATION_HEIGHT = 600;  
  11.  /** Dimensions of game board (usually the same) */ 
  12.      private static final int WIDTH = APPLICATION_WIDTH;  
  13.      private static final int HEIGHT = APPLICATION_HEIGHT;  
  14.  /** Dimensions of the paddle */ 
  15.      private static final int PADDLE_WIDTH = 60;  
  16.      private static final int PADDLE_HEIGHT = 10;  
  17.  /** Offset of the paddle up from the bottom */ 
  18.      private static final int PADDLE_Y_OFFSET = 30;  
  19.  /** Number of bricks per row */ 
  20.      private static final int NBRICKS_PER_ROW = 10;  
  21.  /** Number of rows of bricks */ 
  22.      private static final int NBRICK_ROWS = 10;  
  23.  /** Separation between bricks */ 
  24.      private static final int BRICK_SEP = 4;  
  25.  /** Width of a brick */ 
  26.      private static final int BRICK_WIDTH =  
  27.        (WIDTH - (NBRICKS_PER_ROW - 1) * BRICK_SEP) / NBRICKS_PER_ROW;  
  28.  /** Height of a brick */ 
  29.      private static final int BRICK_HEIGHT = 8;  
  30.  /** Radius of the ball in pixels */ 
  31.      private static final int BALL_RADIUS = 10;  
  32.  /** Offset of the top brick row from the top */ 
  33.      private static final int BRICK_Y_OFFSET = 70;  
  34.  /** Number of turns */ 
  35.      private static final int NTURNS = 3

***步:创建游戏需要的砖块,砖块的行数和每行的数量都是确定的(NBRICK_ROWS,NBRICKS_PER_ROW),最上一排砖块距窗口顶部距离 (BRICK_Y_OFFSET)。然后是颜色的填充,利用行数判断所需的颜色。

  1. for(int i = 0; i < NBRICK_ROWS; i++){  
  2.              for(int j = 0; j < NBRICKS_PER_ROW; j++){  
  3.                  GRect brick = new GRect(0 + j * (BRICK_WIDTH + BRICK_SEP), BRICK_Y_OFFSET + i * (BRICK_HEIGHT + BRICK_SEP), BRICK_WIDTH, BRICK_HEIGHT);  
  4.                  brick.setFilled(true);  
  5.                  if(i < 2){  
  6.                      brick.setColor(Color.RED);  
  7.                  } else if(i < 4){  
  8.                      brick.setColor(Color.ORANGE);  
  9.                  } else if(i < 6){  
  10.                      brick.setColor(Color.YELLOW);  
  11.                  } else if(i < 8){  
  12.                      brick.setColor(Color.GREEN);  
  13.                  } else {  
  14.                      brick.setColor(Color.CYAN);  
  15.                  }  
  16.                  add(brick);  
  17.              }  
  18.          } 

第二步:创建游戏所需的挡板

挡板的大小位置都是确定的;

  1. private void createPaddle(){  
  2.          /* HEIGHT 定义的是窗口高度所以要使用getHeight();*/ 
  3.          GRect paddle = new GRect((WIDTH - PADDLE_WIDTH) / 2, getHeight() - PADDLE_HEIGHT - PADDLE_Y_OFFSET, PADDLE_WIDTH, PADDLE_HEIGHT);  
  4.          paddle.setFilled(true);  
  5.          paddle.setColor(Color.BLACK);  
  6.          add(paddle);  
  7.            
  8.      } 

比较有挑戓性的部分是能够让挡板随着鼠标移劢。挡板只需要在x轴方向上移动。

加入鼠标侦听事件:addMouseListeners9();

和鼠标拖拽事件的代码:

  1. /* 单击鼠标事件 */ 
  2.  public void mousePressed(MouseEvent e){  
  3.      last = new GPoint(e.getPoint());  
  4.      gobj = getElementAt(last);  
  5.  }  
  6.  /* 鼠标拖动事件 */ 
  7.  public void mouseDragged(MouseEvent e){  
  8.      if(gobj != null){  
  9.          gobj.move(e.getX() - last.getX(), 0);  
  10.          last = new GPoint(e.getPoint());  
  11.      }  
  12.  } 

这样就可以使用鼠标拖动挡板了。但是还需要求挡板能移动出游戏的边界,所以加入判断条件

  1. (gobj.getX() > 0 || e.getX() - last.getX() > 0) && (gobj.getX() + gobj.getWidth() < getWidth() || e.getX() - last.getX() < 0)  
  2.  

当挡板移动到左边界时,鼠标需要向右移动才有效,当挡板移动到右边界时,鼠标需要向左移动才有效。

  1. /* 鼠标拖动事件 */ 
  2.  public void mouseDragged(MouseEvent e){  
  3.      if(gobj != null && (gobj.getX() > 0 || e.getX() - last.getX() > 0) && (gobj.getX() + gobj.getWidth() < getWidth() || e.getX() - last.getX() < 0)){  
  4.          gobj.move(e.getX() - last.getX(), 0);  
  5.          last = new GPoint(e.getPoint());  
  6.      }  
  7.  } 

第三步:创建一个小球,使其在墙内反弹;

程序需要记录小球的速度。它由两个独立分量组成,你们可以按照下面的例子声明实例变量:private double vx, vy;速度分量表示在每个时间区间位置的变化量。一开始,小球向下运劢,初始速度vy可以设为+3.0(在Java 中,y 值向屏幕往下增加)。如果每个回合小球的路线都相同,游戏会很无聊,因此,vx 分量的值应该随机选取。

1. 声明一个实例变量rgen, 随机数生成器: private RandomGenerator rgen = RandomGenerator.getInstance();

2. 初始化vx 变量: vx = rgen.nextDouble(1.0, 3.0);if (rgen.nextBoolean(0.5)) vx=-vx; 返段代码生成一个1.0到3.0间的双浮点型随机数赋给 vx,并按0.5 的概率将速度取反。这种算法比调用 nextDouble(-3.0, +3.0) 好很多,后者可能会出现小球几乎垂直下落的情况,返对玩家来说太过于简单。

然后是让小球在墙壁之间来回弹跳,先忽略挡板和砖块的影响。

  1. /* 创建一个反弹的小球 */ 
  2.      private void createBall(){  
  3.          GOval ball = new GOval((getWidth() - 2 * BALL_RADIUS) / 2, (getHeight() - 2 * BALL_RADIUS) / 2, BALL_RADIUS, BALL_RADIUS);  
  4.          ball.setFilled(true);  
  5.          add(ball);  
  6.          vy = 3.0;  
  7.          vx = rgen.nextDouble(1.03.0);   
  8.          if(rgen.nextBoolean(0.5)) vx = -vx;  
  9.          while(true){  
  10.              ball.move(vx,vy);  
  11.              pause(PAUSE_TIME);  
  12.              if(ball.getX() < 0 || ball.getX() + 2 * BALL_RADIUS > getWidth()) vx = -vx;  
  13.              if(ball.getY() < 0 || ball.getY() + 2 * BALL_RADIUS > getHeight()) vy = -vy;  
  14.          }  
  15.      } 

第四步:碰撞检测

现在到了有趣的部分。为了使突破游戏更真实,需要判断小球是否和屏幕中其它物体产生了碰撞。

这里我为了让其他方法能获取ball和paddle的数据定义两个实例变量:

private GOval BALL;

private GRect PADDLE;

然后分别在createBall和createPaddle中加入 BALL = ball 和 PADDLE = paddle;

创建碰撞检测的方法

  1. private GObject getCollidingObject(){  
  2.          /* 小球的正切正方形的四个顶点 */ 
  3.          double x1 = BALL.getX();  
  4.          double y1 = BALL.getY();  
  5.          double x2 = BALL.getX() + 2 * BALL_RADIUS;  
  6.          double y2 = BALL.getY();  
  7.          double x3 = BALL.getX() + 2 * BALL_RADIUS;  
  8.          double y3 = BALL.getY() + 2 * BALL_RADIUS;  
  9.          double x4 = BALL.getX();  
  10.          double y4 = BALL.getY() + 2 * BALL_RADIUS;  
  11.          if(getElementAt(x1,y1) != null){  
  12.              return getElementAt(x1,y1);  
  13.          } else if(getElementAt(x2,y2) != null){  
  14.              return getElementAt(x2,y2);  
  15.          } else if(getElementAt(x3,y3) != null){  
  16.              return getElementAt(x3,y3);  
  17.          } else if(getElementAt(x4,y4) != null){  
  18.              return getElementAt(x4,y4);  
  19.          } else{  
  20.              return null;  
  21.          }  
  22.      } 

是用小球的正切正方形的四个点进行判断十分碰到挡板或砖块;碰到挡板垂直反弹,碰到砖块,消除方块并反弹。

  1. if(collider == PADDLE){  
  2. vy = -vy;  
  3. else if (collider != null){  
  4. vy = -vy;  
  5. remove(collider);  
  6. n++;  

第五步:尾声

1.加入游戏获胜和失败的判断条件;

2.加入获胜和失败的反馈;

3.加入回合数;

 完整代码:

  1. /*  
  2.  * File: Breakout.java  
  3.  * -------------------  
  4.  * Name:  
  5.  * Section Leader:  
  6.  *   
  7.  * This file will eventually implement the game of Breakout.  
  8.  */ 
  9.  
  10. import acm.graphics.*;  
  11. import acm.program.*;  
  12. import acm.util.*;  
  13.  
  14. import java.applet.*;  
  15. import java.awt.*;  
  16. import java.awt.event.*;  
  17.  
  18. public class Breakout extends GraphicsProgram {  
  19.  
  20. /** Width and height of application window in pixels */ 
  21.     public static final int APPLICATION_WIDTH = 400;  
  22.     public static final int APPLICATION_HEIGHT = 600;  
  23.  
  24. /** Dimensions of game board (usually the same) */ 
  25.     private static final int WIDTH = APPLICATION_WIDTH;  
  26.     private static final int HEIGHT = APPLICATION_HEIGHT;  
  27.  
  28. /** Dimensions of the paddle */ 
  29.     private static final int PADDLE_WIDTH = 60;  
  30.     private static final int PADDLE_HEIGHT = 10;  
  31.  
  32. /** Offset of the paddle up from the bottom */ 
  33.     private static final int PADDLE_Y_OFFSET = 30;  
  34.  
  35. /** Number of bricks per row */ 
  36.     private static final int NBRICKS_PER_ROW = 10;  
  37.  
  38. /** Number of rows of bricks */ 
  39.     private static final int NBRICK_ROWS = 10;  
  40.  
  41. /** Separation between bricks */ 
  42.     private static final int BRICK_SEP = 4;  
  43.  
  44. /** Width of a brick */ 
  45.     private static final int BRICK_WIDTH =  
  46.       (WIDTH - (NBRICKS_PER_ROW - 1) * BRICK_SEP) / NBRICKS_PER_ROW;  
  47.  
  48. /** Height of a brick */ 
  49.     private static final int BRICK_HEIGHT = 8;  
  50.  
  51. /** Radius of the ball in pixels */ 
  52.     private static final int BALL_RADIUS = 10;  
  53.  
  54. /** Offset of the top brick row from the top */ 
  55.     private static final int BRICK_Y_OFFSET = 70;  
  56.  
  57. /** Number of turns */ 
  58.     private static final int NTURNS = 3;  
  59.  
  60. /* Method: run() */ 
  61. /** Runs the Breakout program. */ 
  62.     public void run() {  
  63.         createAllBrick(NBRICK_ROWS, NBRICKS_PER_ROW);  
  64.         createPaddle();  
  65.         int i = 0;  
  66.         while(i < NTURNS){  
  67.             createBall();  
  68.             i++;  
  69.             if (isWin == 1break;  
  70.         }  
  71.         if(i == 3){  
  72.             add(new GLabel("YOU LOSE", getWidth() / 2, getHeight() / 2));  
  73.         }  
  74.     }  
  75.     /*  
  76.      * 根据提供的数据创建游戏需要的砖块;  
  77.      */ 
  78.     private void createAllBrick(int row, int rank){  
  79.         for(int i = 0; i < row; i++){  
  80.             for(int j = 0; j < rank; j++){  
  81.                 GRect brick = new GRect(0 + j * (BRICK_WIDTH + BRICK_SEP), BRICK_Y_OFFSET + i * (BRICK_HEIGHT + BRICK_SEP), BRICK_WIDTH, BRICK_HEIGHT);  
  82.                 brick.setFilled(true);  
  83.                 if(i < 2){  
  84.                     brick.setColor(Color.RED);  
  85.                 } else if(i < 4){  
  86.                     brick.setColor(Color.ORANGE);  
  87.                 } else if(i < 6){  
  88.                     brick.setColor(Color.YELLOW);  
  89.                 } else if(i < 8){  
  90.                     brick.setColor(Color.GREEN);  
  91.                 } else {  
  92.                     brick.setColor(Color.CYAN);  
  93.                 }  
  94.                 add(brick);  
  95.             }  
  96.         }  
  97.     }  
  98.     /*  
  99.      * 创建一个可以用鼠标拖动的挡板;  
  100.      * 挡板不能被拖出屏幕边界;  
  101.      */ 
  102.     private void createPaddle(){  
  103.         /* HEIGHT 定义的是窗口高度所以要使用getHeight();*/ 
  104.         GRect paddle = new GRect((WIDTH - PADDLE_WIDTH) / 2, getHeight() - PADDLE_HEIGHT - PADDLE_Y_OFFSET, PADDLE_WIDTH, PADDLE_HEIGHT);  
  105.         PADDLE = paddle;  
  106.         paddle.setFilled(true);  
  107.         paddle.setColor(Color.BLACK);  
  108.         add(paddle);  
  109.         addMouseListeners();  
  110.     }  
  111.     /* 单击鼠标事件 */ 
  112.     public void mousePressed(MouseEvent e){  
  113.         last = new GPoint(e.getPoint());  
  114.         gobj = getElementAt(last);  
  115.     }  
  116.     /* 鼠标拖动事件 */ 
  117.     public void mouseDragged(MouseEvent e){  
  118.         if(gobj != null && (gobj.getX() > 0 || e.getX() - last.getX() > 0) && (gobj.getX() + gobj.getWidth() < getWidth() || e.getX() - last.getX() < 0)){  
  119.             gobj.move(e.getX() - last.getX(), 0);  
  120.             last = new GPoint(e.getPoint());  
  121.         }  
  122.     }  
  123.     /* 创建一个反弹的小球 */ 
  124.     private void createBall(){  
  125.         GOval ball= new GOval((getWidth() - 2 * BALL_RADIUS) / 2, (getHeight() - 2 * BALL_RADIUS) / 2, BALL_RADIUS, BALL_RADIUS);  
  126.         ball.setFilled(true);  
  127.         BALL = ball;  
  128.         add(ball);  
  129.         int n = 0//记录消除的砖块数目;  
  130.         vy = 3.0;  
  131.         vx = rgen.nextDouble(1.03.0);   
  132.         if(rgen.nextBoolean(0.5)) vx = -vx;  
  133.         while(true){  
  134.             ball.move(vx,vy);  
  135.             GObject collider = getCollidingObject();  
  136.             pause(PAUSE_TIME);  
  137.             if(collider == PADDLE){  
  138.                 vy = -vy;  
  139.             } else if (collider != null){  
  140.                 vy = -vy;  
  141.                 remove(collider);  
  142.                 n++;  
  143.                 if (n == 100){  
  144.                     add(new GLabel("YOU WIN!", getWidth() /2, getHeight() / 2));//显示消息;  
  145.                     remove(ball);  
  146.                     isWin = 1;  
  147.                     break;  
  148.                 }  
  149.             }  
  150.             if(ball.getX() < 0 || ball.getX() + 2 * BALL_RADIUS > getWidth()) vx = -vx;  
  151.             if(ball.getY() < 0) vy = -vy;  
  152.             if(ball.getY() + 2 * BALL_RADIUS > getHeight()){  
  153.                 remove(ball);  
  154.                 break;  
  155.             }  
  156.         }  
  157.     }  
  158.     private GObject getCollidingObject(){  
  159.         /* 小球的正切正方形的四个顶点 */ 
  160.         double x1 = BALL.getX();  
  161.         double y1 = BALL.getY();  
  162.         double x2 = BALL.getX() + 2 * BALL_RADIUS;  
  163.         double y2 = BALL.getY();  
  164.         double x3 = BALL.getX() + 2 * BALL_RADIUS;  
  165.         double y3 = BALL.getY() + 2 * BALL_RADIUS;  
  166.         double x4 = BALL.getX();  
  167.         double y4 = BALL.getY() + 2 * BALL_RADIUS;  
  168.         if(getElementAt(x1,y1) != null){  
  169.             return getElementAt(x1,y1);  
  170.         } else if(getElementAt(x2,y2) != null){  
  171.             return getElementAt(x2,y2);  
  172.         } else if(getElementAt(x3,y3) != null){  
  173.             return getElementAt(x3,y3);  
  174.         } else if(getElementAt(x4,y4) != null){  
  175.             return getElementAt(x4,y4);  
  176.         } else{  
  177.             return null;  
  178.         }  
  179.     }  
  180.     /* 创建一个随机数生成器 */ 
  181.     private RandomGenerator rgen = RandomGenerator.getInstance();  
  182.     /* 小球移动的实例变量 */ 
  183.     private double vx, vy;   
  184.     /* 小球移动的暂停时间 */ 
  185.     private int PAUSE_TIME = 20;  
  186.     private GOval BALL;  
  187.     private GRect PADDLE;  
  188.     private int isWin = 0;/* 是否获胜 */ 
  189.     private GObject gobj; /* The object being dragged */ 
  190.     private GPoint last; /* The last mouse position */ 
  191.       

刚开始学,还有很多地方实现的不完善;

原文链接:http://www.cnblogs.com/mybluecode/archive/2012/12/17/2821370.html

责任编辑:张伟 来源: 博客园
相关推荐

2015-03-19 10:12:36

下拉刷新开源组件

2022-07-13 16:24:12

ArkUI(JS)打地鼠游戏

2011-07-21 16:48:19

iPhone 游戏

2016-06-14 15:33:47

SpriteKitSwift开发

2016-06-14 15:57:18

SpriteKitSwift游戏

2011-09-19 10:24:22

编程

2014-11-24 14:14:17

2015-10-10 14:40:36

编程游戏

2011-04-01 14:24:07

C#编程

2010-02-25 15:28:53

重复数据删除

2010-06-17 10:16:59

Linux开源技术

2019-08-09 10:35:54

2020-05-25 20:55:55

游戏编程程序员

2013-12-03 10:58:50

Cocos2D-X砖块地图

2013-09-02 15:33:30

WindowsDirectX

2011-07-26 15:56:53

iPhone 游戏 启动画面

2018-10-24 10:46:51

黑鲨

2015-10-22 15:15:58

Acer

2017-04-11 11:49:00

人工智能

2011-04-08 10:49:35

编程语言编程游戏开发
点赞
收藏

51CTO技术栈公众号