Java实战--飞机大战

根据引导自己动手试试看

源码具体详情请点击  https://download.csdn.net/download/qq_40803710/11011232  进行下载。

1.第一个任务:做6个子类

       Sky: y1;step   step();

       Hero: life;doubleFire   move(int x,int y){}

       Airplane: step      step();

       BigAirplane: step   step();

       Bee: xstep; ystep;   awardType//0表示带命;1表示带分    step();

       Bullet: step        step();

2.第二个任务:使用构造方法,初始化数据

       1)Sky:无参构造

              public Sky() {

              super(400,700,0,0);       

              y1=-700;

              step = 1;

       }

       2) Hero:无参构造

              public Hero() {

              super(97,124,400/2-97/2,400);

              life = 3;

              doubleFire = 0;//0表示单倍火力    >0表示双倍火力

       }

       3)敌人对象(Airplane,BigAirplane,Bee)无参构造

              public Airplane() {

              super(49,36);

              step = 2;

       }

       public BigAirplane() {

              super(69,99);

              step = 2;

       }

       public Bee() {

              super(60,50);

              xstep = 1;

              ystep = 2;

              awardType = new Random().nextInt(2);  //0:火力值    1:命

       }

       4)Bullet

              public Bullet(int x,int y) {

              super(8,14,x,y);

              step = 3;

              state = LIFE;

       }

 

3. 第三个任务:定义FlyingObject(实现代码重用)

1)定义FlyingObject,定义通用的变量和方法

2)设计两个构造方法:

     对Airplane,Bee ,BigAirplane对象的初始化方法

     //给敌人对象初始化Airplane,BigAirplane,Bee

     public FlyingObject(int width,int height){

           this.width = width;

           this.height = height;

           x = new Random().nextInt(400-this.width);

          y = -height;

     },在子类中调用

     对Hero,Sky,Bullet对象的初始化方法

    //给Sky,Hero,Bullet三个类实例化的方法

    public FlyingObject(int width,int height,int x,int y){

           this.width = width;

           this.height = height;

           this.x = x;

           this.y = y;

    },在子类中调用

    3)调整成员变量的修饰符

    父类中可以被访问的成员访问修饰符:protected

    子类中的成员不被外界访问修饰符:private

4.第四个任务:画页面

1)定义World类,继承JPanel

2)定义窗口,显示窗口

import javax.swing.JPanel;

import java.awt.Graphics;

import javax.swing.JFrame;

 

public class world extends JPanel{

    Sky sky = new Sky();

    public static void main(String args[]) {

           JFrame frame = new JFrame();

           world world = new world();

           frame.add(world);

          

           frame.setTitle("飞机大战");  //设置窗口标题

           frame.setSize(400,700);   //设置窗口大小

           frame.setLocationRelativeTo(null);  //设置窗口居中显示

           frame.setVisible(true);   //设置窗口可视化

    }

    //实现画的功能

    public void paint(Graphics g) {

           sky.paintObject(g);

    }

}

3)把图片拷贝到工程包下

4)加载图片

4.1)天空

//存放图片对象

    private static BufferedImage image;

    static{

           try {

                  //使用ImageIO读取图片

                  image = ImageIO.read(Sky.class.getResource("background.png"));

           } catch (IOException e) {

                  // TODO Auto-generated catch block

                  e.printStackTrace();

           }

    }

    4.2)小敌机

    //加载图片到数组中

    private static BufferedImage[] images = new BufferedImage[5];

    static{

           for(int i = 0;i<images.length;i++){

                  try {

                         images[i]=ImageIO.read(Airplane.class.getResource("airplane"+i+".png"));

                  } catch (IOException e) {

                         // TODO Auto-generated catch block

                         e.printStackTrace();

                  }

           }

    }

    4.3)大敌机

    //加载图片到数组中

    private static BufferedImage[] images = new BufferedImage[5];

    static{

           for(int i = 0;i<images.length;i++){

                  try {

                         images[i]=ImageIO.read(Airplane.class.getResource("bigplane"+i+".png"));

                  } catch (IOException e) {

                         // TODO Auto-generated catch block

                         e.printStackTrace();

                  }

           }

    }

5)获取图片

//类中有一个抽象方法时类不能定义为对象 要想让当前类创建对象

//要将父类抽象且方法抽象(父类中声明)才可以实现

public abstract BufferedImage getImage();

//子类中具体实现

5.1)天空@Override

    public BufferedImage getImage() {

           return image;

    }

       (1)小敌机

/*

        * 1、如果当前状态为活着,加载数组的第一张图片

        * 2、如果当前状态为死亡,加载数组中剩余的四张图片,把state=REMOVE

        */

       int deadIndex = 1;

       @Override

       public BufferedImage getImage() {

              if(this.isLife()) {

                     return images[0];

              }else if(this.isDead()) {

                     //解决怎样加载剩余四张图片  可以多次调用返回

                     BufferedImage image = images[deadIndex++];

                     if(deadIndex==images.length) {

                            state = REMOVE;

                     }

                     return image;

              }

              return null;

       }

(2)大敌机

/*

        * 1、如果当前状态为活着,加载数组的第一张图片

        * 2、如果当前状态为死亡,加载数组中剩余的四张图片,把state=REMOVE

        */

       int deadIndex = 1;

       @Override

       public BufferedImage getImage() {

              if(this.isLife()) {

                     return images[0];

              }else if(this.isDead()) {

                     BufferedImage image = images[deadIndex++];

                     if(deadIndex==images.length) {

                            state = REMOVE;

                     }

                     return image;

              }

              return null;

       }

(3)蜜蜂

/*

        * 1、如果当前状态为活着,加载数组的第一张图片

        * 2、如果当前状态为死亡,加载数组中剩余的四张图片,把state=REMOVE

        */

       int deadIndex = 1;

       @Override

       public BufferedImage getImage() {

              if(this.isLife()) {

                     return images[0];

              }else if(this.isDead()) {

                     //解决怎样加载剩余四张图片  可以多次调用返回

                     BufferedImage image = images[deadIndex++];

                     if(deadIndex==images.length) {

                            state = REMOVE;

                     }

                     return image;

              }

              return null;

       }

(4)子弹

public Bullet[] getBullet() {

              if(doubleFire == 0) {

                     Bullet[] b = new Bullet[1];

                     int b_x = this.x + this.width/2;

                     int b_y = this.y - 20;

                     Bullet b1 = new Bullet(b_x,b_y);

                     b[0] = b1;

                     return b;

              }else {

                     Bullet[] b = new Bullet[2];    

                     int b_x = this.x + this.width/4;

                     int b_y = this.y - 20;

                     Bullet b1 = new Bullet(b_x,b_y);

                     b[0] = b1;

                    

                     int b_x2 = this.x + this.width/4*3;

                     Bullet b2 = new Bullet(b_x2,b_y);

                     b[0] = b1;

                     b[1] = b2;

                     return b;

              }

       }

 

/*

        * 1、如果当前状态为活着,加载数组的第一张图片

        * 2、如果当前状态为死亡,把state=REMOVE

        */

       @Override

       public BufferedImage getImage() {

              if(this.isLife()) {

                     return image;

              }else if(this.isDead()) {

                            state = REMOVE;

                     }

              return null;

       }

6)画图片

public void paintObject(Graphics g) {

       g.drawImage(getImage(), x, y, null);

g.drawImage(getImage(), x, y, null);

}

在World类中画图片

    定义方法objectAction

    FlyingObject object [] = {};

    //敌人入场

    public void objectAction(){

           //小敌机的初始化

           object = new FlyingObject[6];

           object[0] = new Airplane();

           object[1] = new Airplane();

           object[2] = new Airplane();

           object[3] = new BigAirplane();

           object[4] = new BigAirplane();

           object[5] = new BigAirplane();

    }

    //实现画的功能

    public void paint(Graphics g){

           sky.paintObject(g);

           //画小敌机

           for(int i = 0;i<object.length;i++){

                  object[i].paintObject(g);

           }

    }

5.第五个任务:让画面动起来

(1)动起来

//天空向下移动

public void step() {

    y += step;

    y1 += step;

    if(y >= 700) {

           y = -700;

    }

    if(y1 >= 700) {

           y1 = -700;

    }

}

//敌人对象动起来

public void step() {

    y += step;

}

//小蜜蜂的step方法

public void step() {

           x += xstep;

           y += ystep;

           if(x>=400-this.width) {

                  xstep *= -1;

           }

    }

//子弹动起来

public void step() {

           y -= step;

}

(2)在world中定义方法

       //让飞行物动起来

       public void stepAction() {

       //天空

       sky.step();

       //让敌人(小敌机、大敌机、蜜蜂)动起来

       for(int i = 0;i<object.length;i++) {

              object[i].step();

       }

       //让子弹动起来

       for(int i = 0;i<bullets.length;i++) {

              bullets[i].step();

       }

}

在run方法中调用

public void action() {

       //使用定时器

       Timer timer = new Timer();

       timer.schedule(new TimerTask() {

              public void run() {

                     objectAction();  //生成敌人对象

                     stepAction();    //让画面动起来

                     bulletAction();

                     //run()功能:调用paint()方法

                     repaint();

              }

       }, 10, 10);  //delay延迟  period

}

(3)随机产生敌人对象

3.1)//随机产生一个敌人对象

       public FlyingObject nextOne() {

              //20以内随机数  分成三个范围  定义其类型

              int Random = new Random().nextInt(20);

              if(Random<4) {

                     return new Bee();

              }else if(Random>=4 && Random<12) {

                     return new BigAirplane();

              }else {

                     return new Airplane();

              }

       }

       //控制生成敌人数量

       int flyIndex = 0;

       //敌人入场

       public void objectAction() {

              flyIndex++;

              if(flyIndex % 40 == 0) {

                     //敌人的初始化

                     FlyingObject obj = nextOne();

                     object = Arrays.copyOf(object, object.length+1);

                     object[object.length-1] = obj;

              }

       }

      

       //控制生成子弹数量

       int bulletIndex = 0;

       public void bulletAction() {

              bulletIndex++;

              if(bulletIndex % 40 == 0) {

                     //子弹的初始化

                     Bullet b1[] = hero.getBullet();

                     //数组扩容:原来数组回收,新建数组拷贝扩容,第二参数为数组总大小

                     //Arrays.copyOf(original, newLength)

                     bullets = Arrays.copyOf(bullets, bullets.length + b1.length);

                     //对原数组数据拷贝第一个:从哪里开始拷;第四个:从哪里开始拷贝;第五个:拷贝多少个

                     System.arraycopy(b1, 0, bullets, bullets.length - b1.length, b1.length);

              }

             

       }

       3.2)把随机对象放到数组中

       int index = 0;

       //敌人入场

       public void objectAction(){

              index++;

              if(index%40==0){

                     //小敌机的初始化

                     FlyingObject ob = nextOne();

                     object = Arrays.copyOf(object,object.length+1);

                     object[object.length-1]=ob;

              }

       }

 

       4)子弹的产生

       4.1)在Hero类中定义方法

       public Bullet[] getBullet(){

              if(doubleFire==0){

                     Bullet[] b = new Bullet[1];

                     int b_x = this.x + this.width/2;

                     int b_y = this.y - 20;

                     Bullet bl = new Bullet(b_x,b_y);

                     b[0] = bl;

                     return b;

              }else{

                     Bullet[] b = new Bullet[2];

                     int b_x = this.x + this.width/4;

                     int b_y = this.y - 20;

                     Bullet b1 = new Bullet(b_x,b_y);

                     int b_x2 = this.x + this.width/4*3;

                     Bullet b2 = new Bullet(b_x2,b_y);

                     b[0] = b1;

                     b[1] = b2;

                     return b;

              }

       }

 

       4.2)把子弹对象放到数组中

       int bulletIndex=0;

       //子弹入场

       public void bulletAction(){

              bulletIndex++;

              if(bulletIndex%30==0){

              Bullet bl[] = hero.getBullet();

      

              //数组扩容

              bullets = Arrays.copyOf(bullets, bullets.length+bl.length);

              //数组拷贝

              System.arraycopy(bl, 0, bullets, bullets.length-bl.length, bl.length);

             

              }

       }

             

       5)英雄机随鼠标移动(Hero类中)

       5.1)//x,y表示鼠标的座标   (Hero类中)

       public void move(int x,int y){

              this.x = x - this.width/2;

              this.y = y - this.height/2;

       }

       5.2)添加事件监视器   (World类中)

       //定义鼠标的移动事件处理方法(内部类:(匿名类))

              MouseAdapter l = new MouseAdapter(){

                     public void mouseMoved(MouseEvent e){

                            //获取鼠标点的座标

                            int x = e.getX();

                            int y = e.getY();

                            hero.move(x, y);

                     }

              };

              //给Jpanel添加事件监视器的对象

              this.addMouseMotionListener(l);

6.第六个任务:删除越界的对象

  1. 在父类定义越界的方法,分别在子类中实现方法

public abstract boolean outOfBounds();

  1. 分别实现方法(敌人对象y>700,子弹y<0,天空和英雄机永不越界)
  1. 敌人

public boolean outOfBounds() {

   return this.y>700;

}

  1. 子弹

public boolean outOfBounds() {

   return this.y<0;

}

  1. 天空和英雄机

public boolean outOfBounds() {

   return false;

}

  1. 在world类中定义方法,回收越界对象,在action方法中调用

//回收越界的对象:(敌人,子弹)

  public void outOfBoundsAction() {

         //装活着的敌人的对象的数组

         FlyingObject[] fo = new FlyingObject[object.length];

         //活着的敌人对象数目

         int lifeIndex = 0;

         //遍历数组

         for(int i = 0;i<object.length;i++) {

                //从数组中获取敌人的对象

                FlyingObject f = object[i];

                //找出没有越界的敌人

                if(!f.outOfBounds()&&!f.isRemove()) {

                       fo[lifeIndex] = f;

                       lifeIndex++;

                }

         }

         //数组的拷贝

         object = Arrays.copyOf(fo, lifeIndex);

        

         //子弹的越界对象的删除

         //定义数组,装没有越界的子弹

         Bullet[] bo = new Bullet[bullets.length];

         //活着的子弹对象数目

         int bulletsIndex = 0;

         //遍历数组

         for(int i = 0;i<bullets.length;i++) {

                //从数组中获取子弹的对象

                Bullet b = bullets[i];

                //找出没有越界的子弹

                if(!b.outOfBounds()&&!b.isRemove()) {

                       bo[bulletsIndex] = b;

                       bulletsIndex++;

                }

         }

         //数组的拷贝

         bullets = Arrays.copyOf(bo, bulletsIndex);

  }

7.第七个任务:定义敌人和子弹(英雄机)发生碰撞的方法

  1. 定义方法,对敌人和子弹(英雄机)是否碰撞,other表示子弹(英雄机) this表示敌人对象

              public boolean hit(FlyingObject other) {

/*  x轴的范围:this.x-other.width(左x)    this.x+this.width(右x)

y轴的范围:this.y+this.height(上y)    this.y-other.height(下y)

  如果子弹的x,y座标在以上范围内,说明撞上了,返回true,否则返回false        */

int x1 = this.x-other.width;

         int x2 = this.x + this.width;

         int y1 = this.y - other.height;

         int y2 = this.y + this.height;

         int x = other.x;

         int y = other.y;

 

         return x>=x1 && x<=x2 && y>=y1 && y<=y2;

  }

(2)定义接口,定义得分的方法

public interface Enemy { 

  public int getScore();

}

需要大敌机和小敌机实现接口,重写方法

public int getScore() {

  return 1;

}

(3)定义接口,定义福利

public interface Award {//接口中都是公有静态常量,不用写属性,只需类型名字

  int DOUBLEFIRE = 0;//带火力值

  int LIFE = 1;//带名

  int getType();

}

需要小蜜蜂实现接口

public int getType() {

  return awardType;

}

(4)定义功能方法

//让敌人去死的方法(在FlyingObject类中实现)

public void goDead() {

  state = DEAD;

  }

//加命(在Hero类中实现)

  public void addLife(){

         life++;

  }

  //获取命(在Hero类中实现)

  public int getLife(){

         return life;

  }

  //增加火力值(在Hero类中实现)

  public void addDoubleFire(){

         doubleFire+=40;

  }

8.第八个任务:当子弹和敌人碰撞之后的得分和福利的设置,并在页面画分和命

//子弹和敌人发生碰撞

int score = 0;

public void bulletHitAction(){

       //遍历子弹集合,

       for(int i = 0;i<bullets.length;i++){

              //拿到一个子弹对象

              Bullet b = bullets[i];

              for(int j = 0;j<object.length;j++){//遍历敌人集合

                     FlyingObject f = object[j];//获取一个敌人对象

                            if(b.isLife()&&f.isLife()&&f.hit(b)){//子弹对象和所有的敌人碰撞的匹配

                            f.goDead();//敌人去死

                            b.goDead();//子弹去死

                            if(f instanceof Enemy){//如果是(大敌机或者是小敌机)

                                   score += ((Enemy) f).getScore();//得分

                            }

                            if(f instanceof Award){//如果是小蜜蜂

                                   switch(((Award) f).getType()){

                                   case  Award.DOUBLEFIRE://带火力值得小蜜蜂

                                          hero.addDoubleFire();//火力值增加

                                   case Award.LIFE://带命的小蜜蜂

                                          hero.addLife();//命增加

                                   }

                            }

                     }

              }

       }

       }

  g.drawString("Scoure:"+score, 10, 40);

  g.drawString("Life:"+hero.getLife(), 10, 60);

 

9.第九个任务:英雄机和敌人发生碰撞:如果碰到的是大(小)敌机,命-1;

                 如果碰到的是小蜜蜂:火力清0

(1)在Hero类中定义方法:subLife();    clearFire();

//减命

       public void subLife(){

              life--;

       }

       //清空火力值

       public void clearFire(){

              doubleFire = 0;

       }

(2)heroHitAction();

//英雄机和敌人碰撞

       public void heroHitAction() {

              for(int i = 0;i<object.length;i++) //遍历敌人集合

              {

                     FlyingObject f = object[i]; //获取一个敌人对象

                     if(f.isLife()&&f.hit(hero)) {

                            f.goDead(); //敌人去死

                            if(f instanceof Enemy) {

                                   hero.subLife();

                            }

                            if(f instanceof Award) {

                                   hero.clearFire();

                            }

                     }

              }

       }

10.第10个任务:画窗口的状态

  1. 在World类中定义4个常量,表示窗口的状态:开始,运行,暂停,结束

public static final int START = 0;

public static final int RUNNING = 1;

public static final int PAUSE = 2;

public static final int GAMEOVER = 3;

     private int state = START;

  1. 设计程序结束的方法,checkGameOverAction();

  public void checkGameOverAction() {

         if(hero.getLife()==0&&hero.isRemove()) {

                state = GAMEOVER;

         }

         if(hero.getLife()==0)

         {

                hero.goDead();

         }

         }

  1. 在World类中定义3个静态变量,加载图片(启动,暂停,结束)

//存放图片对象

  private static BufferedImage startImage;

  private static BufferedImage pauseImage;

  private static BufferedImage gameOverImage;

  static {

         try {

                //以读取流的方式加载图片

                startImage = ImageIO.read(Sky.class.getResource("start.png"));

                pauseImage = ImageIO.read(Sky.class.getResource("pause.png"));

                gameOverImage = ImageIO.read(Sky.class.getResource("gameover.png"));

         }

         catch(IOException e) {

                e.printStackTrace();

         }

  }

  1. 在World类中的paint()方法中根据不同的状态画不同的的图片

switch(state) {

         case START:

                g.drawImage(startImage, 0, 0, null);

                break;

         case PAUSE:

                g.drawImage(pauseImage, 0, 0, null);

                break;

         case GAMEOVER:

                g.drawImage(gameOverImage, 0, 0, null);

                break;

         }

  1. 在不同状态下,显示不同的运行情况

MouseAdapter l = new MouseAdapter() {

                public void mouseMoved(MouseEvent e) {

                       if(state == RUNNING) {

                              int x = e.getX();

                              int y = e.getY();

                              hero.move(x, y);

                       }

                }

                public void mouseEntered(MouseEvent e) {

                       if(state == PAUSE) {

                              state = RUNNING;

                       }

                }

                public void mouseExited(MouseEvent e) {

                       if(state == RUNNING) {

                              state = PAUSE;

                       }

                }

                public void mouseClicked(MouseEvent e) {

                       if(state == START) {

                              state = RUNNING;

                       }

                       if(state == GAMEOVER) {

                              //初始化操作

                              object = new FlyingObject[0];

                              bullets = new Bullet[0];

                              score = 0;

                              hero = new Hero();

                              state = START;

                       }

                }

         };

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章