Java编写打砖块 经典游戏设计

[程序中使用的数据结构和符号说明]
HitBrick类
GreenBallThread 控制小球路线
xUp,yUp,bouncing 定义变量存储16位数值形式
x,y 小球坐标
xDx,yDy 坐标增量
MAX_X,MAX_Y 坐标最大值
renew 初始化
label 标签
Rx,Ry 横板坐标
Brick[] 砖块
ball 小球
HitBrick() 定义小球横板及砖块位置坐标
keyPressd(keyEent) 定义小球启动键(按空格键启动)
keyReleased(keyEvent) 接收键盘事件侦听器接口)
keyTyped(keyEvent) 键入空格键时调用keyEvent
paint(Graphics) 对砖块填充颜色
move 定义小球的运动轨迹和砖块的消失
main 主函数


BallThread类
通过继承Thread类使Ball类线程化,并把小球的弹跳动作放进Run()中执行


Brick类
定义砖块坐标位置和砖块按钮


Ball类
定义小球坐标位置


[程序设计流程]
程序中使用的部分方法解释
开始命令:空格键
private JLabel label;定义一个标签,label=new JLabel("按空格键开始");内容为空格键开始,addKeyListener(this);定义一个键盘监听器,
if (e.getKeyCode() ==e.VK_SPACE) {
      if(renew){
        greenBallThread=new BallThread(this);
        bouncing = true;
        greenBallThread.start();
        label.setVisible(false);
      }
      renew=false;
    }
 重置并开始游戏


移动命令:方向键左键和右键
if(e.getKeyCode()==e.VK_LEFT){
      Rx=Rx-20;
      if(bouncing){
        if(Rx<0){
          Rx=0;
        }
      }
      else{
        if(Rx<0){
          Rx=0;
        }
        else{
          x=x-20;
          ball.ball_x=x;
        }
      }
      repaint();
    }
同开始命令原理,如果键入左键,横版向左移动20个单位(Rx为横板坐标),如果小球还在运动,当横板移到最左侧(Rx=0),不能再向左移动,则横板靠在最左侧(Rx=0),
if(e.getKeyCode()==e.VK_RIGHT){
      Rx=Rx+20;
      if(bouncing){
        if(Rx+80>300){
          Rx=220;
        }
      }
      else{
        if(Rx+80>300){
          Rx=220;
        }
        else{
          x=x+20;
          ball.ball_x=x;
        }
      }
      repaint();
    }
  }
向右移动同向左移动原理,因为定义界面横坐标最大值为300,横板长度80,故Rx=220时碰最右侧


砖块设定:
brick[0]=new Brick(0,60,50,20);
    brick[1]=new Brick(50,60,50,20);
    brick[2]=new Brick(100,60,50,20);
……
brick[16]=new Brick(200,160,50,20);
    brick[17]=new Brick(250,160,50,20);
    ball=new Ball(150,450,10,10);    


public void paint(Graphics g){
    super.paint(g);
    ball.rect.setLocation(x,y);
    if(bouncing){
      for(int i=0;i<=17;i++){
        if(brick[i].visible==true){
          switch(i){
            case 0 :g.setColor(Color.blue);
                    break;
            case 1 :g.setColor(Color.cyan);
                    break;
            case 2 :g.setColor(Color.gray);
                    break;
             ……
case 17 :g.setColor(Color.yellow);
                    break;
           }
        g.fill3DRect(brick[i].brick_x,brick[i].brick_y,brick[i].brick_width,brick[i].brick_height,true);
        }
      }
      g.setColor(Color.red);
      g.fillOval(x, y, 10, 10);
      g.setColor(Color.blue);
      g.fillRect(Rx,Ry,80,20);
brick[0]=new Brick(0,60,50,20);设置砖块坐标,ball=new Ball(150,450,10,10);和小球的坐标
if(brick[i].visible==true) 判断砖块存在,用switch语句,逐个对砖块填充颜色,最后四行代码是分别对小球和横板颜色坐标的定义


小球的移动:
try{
        Thread.currentThread().sleep(25);
      }
      catch(InterruptedException exception){
        System.err.println(exception.toString());
      }
定义小球的速度,若发生错误,则执行catch语句,打印错误
for(int i=0;i<=17;i++){
        if(ball.rect.intersects(brick[i].rect)&&brick[i].visible){
          brick[i].visible=false;
          yUp=!yUp;/
        }
      }
当小球接触到砖块时,砖块不可见(消失)
if(x+5>Rx&&x+5=Ry){
        yUp=false;
        xDx=(int)(Math.random()*5+2);
        yDy=(int)(Math.random()*5+2);
      }
判断小球坐标和横板坐标,当小球落在横板坐标之内,小球反弹,小球横坐标和纵坐标都以一个随机值改变后运动
if(xUp==true){
        x+=xDx;
      }
      else{
        x-=xDx;
      }
      if(yUp==true){
        y+=yDy;
      }
      else{
        y-=yDy;
      }
判断小球横坐标如果在增加,小球横坐标=小球原横坐标+小球横坐标增量,否则小球横坐标=小球原横坐标-小球横坐标增量;纵坐标同理
if(y<=0){
        y=0;
        ball.ball_y=y;
        yUp=true;
        xDx=(int)(Math.random()*5+2);
        yDy=(int)(Math.random()*5+2);
      }
      else if(y>=MAX_Y-15){
        yDy=(int)(Math.random()*5+2);
        //yUp=false;
        break;
      }
判断小球到画面顶部(定义顶部的纵坐标为0),小球向下反弹,原理同小球和横板接触的反弹规则,否则,判断小球纵坐标是否大于MAX_Y-15(纵坐标最大值-15),反弹规则改变为横坐标不变,纵坐标随机改变
if(x<=0){
        x=0;
        ball.ball_x=x;
        xUp=true;
        xDx=(int)(Math.random()*5+2);
        yDy=(int)(Math.random()*5+2);
      }
      else if(x>=MAX_X-10){
        x=MAX_X-10;
        ball.ball_x=x;
        xDx=(int)(Math.random()*5+2);
        yDy=(int)(Math.random()*5+2);
        xUp=false;
      }
判断小球到画面最左侧(定义最左侧横坐标为0),向右侧反弹,反弹规则同小球和横板接触的反弹规则,或者小球到画面最右侧,向左反弹,反弹规则同上,(if(x>=MAX_X-10)判断小球是否到右边侧,小球的直径为10)
int i;                                         
      for(i=0;i<=17&&brick[i].visible==false;i++){   
      }
      if(i==18){
        break;
      }    
如果所有砖块都不可见,则重新玩
renew=true;          //初始化
    bouncing=false;
    for(int i=0;i<=17;i++){
      brick[i].visible=true;
    }
    xUp=true;
    yUp=false;
    xDx=1;
    yDy=1;
    x=150;
    y=450;
    Rx=120;
    Ry=460;             //
重新开始,初始化,小球静止,所有砖块可见,小球在横坐标方向,可随横板移动而移动,纵坐标在未开时游戏前不能改变,定义小球横坐标和纵坐标增量都为1,小球初始位置坐标(150,450)横板初始位置坐标(120,460)




[源程序]
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;


public class HitBrick extends JFrame implements  KeyListener{
  private BallThread greenBallThread;//控制小球的线程
  private boolean xUp,yUp,bouncing;
  private int x,y,xDx,yDy;//小球坐标,增量
  private final int MAX_X=300,MAX_Y=500;
  private boolean renew;
  private JLabel label;
  private int Rx,Ry;//横板坐标


  private Brick brick[]=new Brick[18];//砖块
  private Ball ball;//小球


  public HitBrick(){
    super("打砖块");
    
    Container pane=getContentPane();//设置空白面板容器


    label=new JLabel("按空格键开始"); //标签
    label.setHorizontalAlignment(JLabel.CENTER);//水平
    label.setVerticalAlignment(JLabel.BOTTOM);//垂直
    pane.add(label);//向面板里添加标签
    xUp=true;//横坐标可以移动
    yUp=false;//纵坐标不可以移动
    xDx=1;
    yDy=1;
    x=150;//小球坐标
    y=450;
    Rx=120;//横板坐标
    Ry=460;
    renew=true;
    bouncing=false;
    addKeyListener(this);//键盘监听器




    brick[0]=new Brick(0,60,50,20);//砖块坐标
    brick[1]=new Brick(50,60,50,20);
    brick[2]=new Brick(100,60,50,20);
    brick[3]=new Brick(150,60,50,20);
    brick[4]=new Brick(200,60,50,20);
    brick[5]=new Brick(250,60,50,20);
    brick[6]=new Brick(0,90,50,20);
    brick[7]=new Brick(50,110,50,20);
    brick[8]=new Brick(100,130,50,20);
    brick[9]=new Brick(150,130,50,20);
    brick[10]=new Brick(200,110,50,20);
    brick[11]=new Brick(250,90,50,20);
    brick[12]=new Brick(0,160,50,20);
    brick[13]=new Brick(50,160,50,20);
    brick[14]=new Brick(100,160,50,20);
    brick[15]=new Brick(150,160,50,20);
    brick[16]=new Brick(200,160,50,20);
    brick[17]=new Brick(250,160,50,20);
    ball=new Ball(150,450,10,10);//球的坐标
    
    
    setSize(MAX_X,MAX_Y);//窗口大小
    setResizable(false);
    setVisible( true );//可视化    
  }


  public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() ==e.VK_SPACE) {
      if(renew){
        greenBallThread=new BallThread(this);
        bouncing = true;
        greenBallThread.start();
        label.setVisible(false);
      }
      renew=false;
    }
    if(e.getKeyCode()==e.VK_LEFT){
      Rx=Rx-20;
      if(bouncing){
        if(Rx<0){
          Rx=0;
        }
      }
      else{
        if(Rx<0){
          Rx=0;
        }
        else{
          x=x-20;
          ball.ball_x=x;
        }
      }
      repaint();
    }
    if(e.getKeyCode()==e.VK_RIGHT){
      Rx=Rx+20;
      if(bouncing){
        if(Rx+80>300){
          Rx=220;
        }
      }
      else{
        if(Rx+80>300){
          Rx=220;
        }
        else{
          x=x+20;
          ball.ball_x=x;
        }
      }
      repaint();
    }
  }


  public void keyReleased (KeyEvent e) {}
  public void keyTyped (KeyEvent e){}


  public void paint(Graphics g){
    super.paint(g);
    ball.rect.setLocation(x,y);
    if(bouncing){
      for(int i=0;i<=17;i++){
        if(brick[i].visible==true){
          switch(i){
            case 0 :g.setColor(Color.blue);
                    break;
            case 1 :g.setColor(Color.cyan);
                    break;
            case 2 :g.setColor(Color.gray);
                    break;
            case 3 :g.setColor(Color.green);
                    break;
            case 4 :g.setColor(Color.magenta);
                    break;
            case 5 :g.setColor(Color.yellow);
                    break;
            case 6 :g.setColor(Color.white);
                    break;
            case 7 :g.setColor(Color.black);
                    break;
            case 8 :g.setColor(Color.orange);
                    break;
            case 9 :g.setColor(Color.pink);
                    break;
            case 10 :g.setColor(Color.darkGray);
                    break;
            case 11 :g.setColor(Color.red);
                    break;
            case 12 :g.setColor(Color.blue);
                    break;
            case 13 :g.setColor(Color.cyan);
                    break;
            case 14 :g.setColor(Color.gray);
                    break;
            case 15 :g.setColor(Color.green);
                    break;
            case 16 :g.setColor(Color.magenta);
                    break;
            case 17 :g.setColor(Color.yellow);
                    break;
           }
        g.fill3DRect(brick[i].brick_x,brick[i].brick_y,brick[i].brick_width,brick[i].brick_height,true);
        }
      }
      g.setColor(Color.red);
      g.fillOval(x, y, 10, 10);
      g.setColor(Color.blue);
      g.fillRect(Rx,Ry,80,20);
    }
    else{
      for(int i=0;i<=17;i++){
        switch(i){
            case 0 :g.setColor(Color.blue);
                    break;
            case 1 :g.setColor(Color.cyan);
                    break;
            case 2 :g.setColor(Color.gray);
                    break;
            case 3 :g.setColor(Color.green);
                    break;
            case 4 :g.setColor(Color.magenta);
                    break;
            case 5 :g.setColor(Color.yellow);
                    break;
            case 6 :g.setColor(Color.white);
                    break;
            case 7 :g.setColor(Color.black);
                    break;
           case 8 :g.setColor(Color.orange);
                    break;
           case 9 :g.setColor(Color.pink);
                    break;
           case 10 :g.setColor(Color.darkGray);
                    break;
           case 11 :g.setColor(Color.red);
                    break;
           case 12 :g.setColor(Color.blue);
                    break;
           case 13 :g.setColor(Color.cyan);
                    break;
           case 14 :g.setColor(Color.gray);
                    break;
           case 15 :g.setColor(Color.green);
                    break;
           case 16 :g.setColor(Color.magenta);
                    break;
           case 17 :g.setColor(Color.yellow);
                    break;
         }
         g.fill3DRect(brick[i].brick_x,brick[i].brick_y,brick[i].brick_width,brick[i].brick_height,true);
      }
      g.setColor(Color.red);
      g.fillOval(x, y, 10, 10);
      g.setColor(Color.blue);
      g.fillRect(Rx, Ry, 80, 20);
    }
  }


  public void move(){
    while(true){
      try{
        Thread.currentThread().sleep(25);
      }
      catch(InterruptedException exception){
        System.err.println(exception.toString());
      }


      for(int i=0;i<=17;i++){
        if(ball.rect.intersects(brick[i].rect)&&brick[i].visible){
          brick[i].visible=false;
          yUp=!yUp;//打到球不可见
        }
      }


      if(x+5>Rx&&x+5=Ry){
        yUp=false;
        xDx=(int)(Math.random()*5+2);//小球坐标增量
        yDy=(int)(Math.random()*5+2);
      }


      if(xUp==true){
        x+=xDx;//小球左右移动坐标改变
      }
      else{
        x-=xDx;
      }
      if(yUp==true){
        y+=yDy;
      }
      else{
        y-=yDy;
      }


      if(y<=0){
        y=0;
        ball.ball_y=y;
        yUp=true;
        xDx=(int)(Math.random()*5+2);
        yDy=(int)(Math.random()*5+2);
      }
      else if(y>=MAX_Y-15){
        yDy=(int)(Math.random()*5+2);
        //yUp=false;
        break;
      }


      if(x<=0){
        x=0;
        ball.ball_x=x;
        xUp=true;
        xDx=(int)(Math.random()*5+2);
        yDy=(int)(Math.random()*5+2);
      }
      else if(x>=MAX_X-10){
        x=MAX_X-10;
        ball.ball_x=x;
        xDx=(int)(Math.random()*5+2);
        yDy=(int)(Math.random()*5+2);
        xUp=false;
      }
      ball.rect.setLocation(ball.ball_x,ball.ball_y);
      repaint();
      int i;                                         //如果所有砖块都不可见
      for(i=0;i<=17&&brick[i].visible==false;i++){   //则重新玩
      }
      if(i==18){
        break;
      }                                             //
    }
    renew=true;          //初始化
    bouncing=false;
    for(int i=0;i<=17;i++){
      brick[i].visible=true;
    }
    xUp=true;
    yUp=false;
    xDx=1;
    yDy=1;
    x=150;
    y=450;
    Rx=120;
    Ry=460;             //
    repaint();
    repaint();
    label.setVisible(true);
  }


  public static void main(String[] args) {
    HitBrick mar=new HitBrick();
  }
}


class BallThread extends Thread{
  private HitBrick m;
  BallThread(HitBrick a){
    //super();
    m=a;
  }


  public void  run(){
    m.move();
    m.repaint();
  }
}


class Brick{
  Rectangle rect=null; //长方形对象,砖块按钮的位置和宽高
  int brick_x,brick_y;//按扭的左上角坐标
  int brick_width,brick_height; //按扭的宽和高
  boolean visible;
  public Brick(int x,int y,int w,int h)
      {
      brick_x=x;brick_y=y;
      brick_width=w;brick_height=h;
      visible=true;
      rect=new Rectangle(x,y,w,h); //创建长方形对象---砖块按钮的位置和宽高。
  }
}


class Ball{
  Rectangle rect=null;
  int ball_x,ball_y;
  int ball_width,ball_height;
  public Ball(int x,int y,int w,int h){
    ball_x=x;
    ball_y=y;
    ball_width=w;
    ball_height=h;
    rect=new Rectangle(x,y,w,h);
  }
}
[小结与体会]

虽然系统的基本功能都已实现,但还是存在系统不稳定等多个bug尚待解决。在做系统的过程中遇到了很多问题,有的是知识存储不足,有的是考虑不够周全,所以学习之路永无止境。作为一个程序编程人员,要保持清醒的头脑,以现实为依据,让自己的每一行代码都能实现自己的意义。

你可能感兴趣的:(Java编写打砖块 经典游戏设计)