边做科研任务边带着学习JAVA,学了将近20天的飞机大战项目终于做好了!

目录

思路

World

Sky

FlyingObject

Hero

AirPlane

BigAirPlane

Bee

Bullet

Enemy

Award


思路
我总结一下这个项目的思路:
    首先,根据游戏成品来观察我们需要设计哪些类。这里,我观察到有AirPlane、BigAirPlane、Hero、Bee、Bullet这几个比较明显的物体,然后又考虑到背景在动,就加了Sky背景类,最后考虑到整个游戏需要main方法类,就设计了World游戏世界。
    接着,设计完类,应该给类赋予基本的属性,比如长 宽 高 坐标等。设计时发现,代码重复,为了代码复用,设计了一个FlyingObject超类,并让飞行物和子弹继承该超类,在超类赋予属性,然后子类自动继承。设计好属性,继续设计基本方法,比如移动step()。设计完,继续在World类中设计游戏窗口的大小和位置。
     设计完基本的属性方法,下面该画图了,画图用到了import javax.swing.JFrame;
 import javax.swing.JPanel;   import java.awt.Graphics; 画图先画游戏窗口,然后再画每个飞行物,在超类里面写了读取图片方法,但是每个飞行物读取图片的方式又不一样,所以需要重写画图的方法,除此,每个飞行物的移动方式也不同,也需要重写。       画完图,学到了修饰符与常量,又去改代码,将子类的属性设计成private修饰,然后又将Sky窗口设计成静态常量,因为是固定的。接着,设计了在游戏世界设计ACTION()方法来启动整个游戏。该方法里面调用各种子类的方法,比如画图、鼠标操作、得分、加命等。这里还用到了定时器,和鼠标的操作,import java.util.Timer;    import java.util.TimerTask;   和    import java.awt.event.MouseAdapter;    import java.awt.event.MouseEvent;  具体代码见下面,有点复杂。对于敌人和子弹会出现抛出窗口,所以要删除,避免占内存。所以设计了删除越界敌人和子弹的方法。接着,要画状态,因为游戏有启动、暂停、结束三种状态,所有的飞行物动态方法都是在启动运行时有效的。最后,游戏是通过打敌机得奖励和生命。所以,我设计了两个接口,以便于子类去继承。
具体代码如下:
World
package com.atjialiangExer;
 import javax.swing.JFrame;
 import javax.swing.JPanel;
 import java.awt.Graphics;
 import java.util.Timer;
 import java.util.TimerTask; 
 import java.util.Random;
 import java.util.Arrays;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.awt.image.BufferedImage;
 import javax.imageio.ImageIO;
 import java.awt.Graphics;         /**整个游戏世界*/
          public class World extends JPanel{
             public static final int WIDTH = 400;
             public static final int HEIGHT = 700;
             
             public static final int START = 0;
             public static final int RUNNING = 1;
             public static final int PAUSE = 2;
             public static final int GAME_OVER = 3;
             private int state = START;//当前状态默认启动状态
             
             private static BufferedImage start;
             private static BufferedImage pause;
             private static BufferedImage gameover;
             static {
                 start = FlyingObject.loadImage("start.png");
                 pause = FlyingObject.loadImage("pause.png");
                 gameover = FlyingObject.loadImage("gameover.png");
             }
             
             private Sky sky = new Sky();
             private Hero hero = new Hero();
             //引用类型最好先赋值,不写就是null,避免空指针
             private FlyingObject[] enemies = {};
             private Bullet[] bullets = {};
             
             /** 生成敌人  */
             public FlyingObject nextOne() {
                 Random rand = new Random();
                 int type = rand.nextInt(20);
                 if(type < 5) {
                     return new AirPlane();
                 }else if(type < 12) {
                     return new BigAirPlane();
                 }else {
                     return new Bee();
                 }
                     
             }        
                         
             /** 敌人入场 */
             int enterIndex = 0;  //敌人入场计数
             public void enterAction() { //如何控制频率
                 enterIndex++;
                 if(enterIndex % 40 == 0) { //每40*10毫秒走一次
                     FlyingObject obj = nextOne();                    
                     enemies = Arrays.copyOf(enemies,enemies.length + 1);  //数组的扩容
                     enemies[enemies.length - 1] = obj;
                 }                
             }
                     
             /** 子弹入场 */
             int shootIndex = 0;
             public void shootAction() {
                 shootIndex++;
                 if(shootIndex % 30 == 0) {
                     Bullet[] bs = hero.shoot();//获取子弹 对象
                     bullets = Arrays.copyOf(bullets,bullets.length + bs.length);
                     System.arraycopy(bs, 0,bullets,bullets.length - bs.length ,bs.length);
                 }
             }
             
             /** 飞行物移动*/
             public void stepAction() {
                 sky.step();
                 for(int i = 0;i < enemies.length ;i++) {
                     enemies[i].step();
                 }
                 for(int i = 0;i < bullets.length ;i++) {
                     bullets[i].step();
                 }
             }
             
             /** 删除越界敌人和子弹 */
             public void outOfBoundAction() {
                 int index = 0;
                 FlyingObject[] enemyLives = new FlyingObject[enemies.length];
                 for (int i = 0;i < enemies.length ;i++) {
                     FlyingObject f = enemies[i];
                     if(!f.outOfBounds()) {
                         enemyLives[index] = f;
                         index++;
                     }
                 } 
                 enemies = Arrays.copyOf(enemyLives,index);//将不越界敌人复制过去
                 
                 index = 0; 
                 Bullet[] bulletLives = new Bullet[bullets.length];
                 for(int i = 0;i < bullets.length ;i++) {
                     Bullet b = bullets[i];
                     if(!b.outOfBounds()) {
                         bulletLives[index] = b;
                         index++;
                     }
                 }
                 bullets = Arrays.copyOf(bulletLives, index);
             }
             
             
             /** 子弹与敌人碰撞 */
             int score = 0;//玩家得分
             public void bulletBangAction() {
                 for(int i = 0;i < bullets.length ;i++) {
                     Bullet b = bullets[i];
                     for(int j = 0;j < enemies.length;j++) {
                         FlyingObject f = enemies[j];
                         if(f.isLife() && b.isLife() && f.hit(b)) {
                             b.goDead();
                             f.goDead();
                             
                             if(f instanceof Enemy) {
                                 Enemy e = (Enemy)f; //强转得分借口
                                 score += e.getScore();
                             }            
                             if (f instanceof Award) {
                                 Award a = (Award)f;
                                 int type = a.getAwardType();
                                 switch(type) {
                                     case 0 : 
                                         hero.addDoubleFire();
                                         break;
                                     case 1 :
                                         hero.addlife();
                                         break;
                                 }
                             }
                         }
                     }
                 }
             }
             
             /** 英雄机与敌人碰撞 */
             public void heroBangAction() {
                 for(int i = 0;i < enemies.length ;i++) {
                     FlyingObject f = enemies[i];
                     if(hero.isLife() && f.isLife() && f.hit(hero)) {
                         f.goDead();
                         hero.subtractlife();
                         hero.clearDoubleFire();
                     }
                 }
             }
             
             /** 检测游戏结束 */
             public void checkGameOverAction() {
                 if(hero.LIFE <= 0) {
                     
                 }
             }
             
             /** 启动程序 */
             public void action() {//测试代码
                      MouseAdapter l = new MouseAdapter() {
                         /** 重写mouseMoved */
                         public void mouseMoved(MouseEvent e) {
                             if(state == RUNNING) {
                                 int x = e.getX();
                                 int y = e.getY();
                                 hero.moveTo(x, y);
                             }
                         }
                         
                         /** 鼠标点击 */    
                         public void mouseClicked(MouseEvent e) {
                             switch (state) {
                             case START:
                                 state = RUNNING;
                                 break;
                             case GAME_OVER:
                                 score = 0;    //清理现场
                                 sky = new Sky();
                                 hero = new Hero();
                                 enemies = new FlyingObject[0];
                                 bullets = new Bullet[0];
                                 state = START;
                                 break;
                             }
                         }
                         
                         /** 鼠标移出 */
                         public void mouseExited(MouseEvent e) {
                             if(state == RUNNING) {
                                 state = PAUSE;
                             }
                         }
                         
                         /** 鼠标移入 */
                         public void mouseEntered(MouseEvent e) {
                             if(state == PAUSE) {
                                 state = RUNNING;
                             }
                         }
                     };
                     this.addMouseListener(l); //处理鼠标操作事件
                     this.addMouseMotionListener(l);  //处理鼠标移动事件
                     
                     
                     Timer timer = new Timer();
                     int intervel = 10;//每10毫秒
                     timer.schedule(new TimerTask() {
                         public void run() {
                             if(state == RUNNING) {
                                 enterAction();//敌人入场
                                 shootAction();//子弹入场
                                 stepAction(); //飞行物移动
                                 outOfBoundAction(); //删除越界敌人
                                 bulletBangAction(); //子弹敌人碰撞
                                 checkGameOverAction();//检测是否游戏结束
                             }
                             repaint();    //重画敌人                        
                         }
                     },intervel,intervel);//第一个10,从程序启动开始到第一次触发的时间间隔
                                             //第二个10,第一次触发到第二次触发时间间隔...
                 }            /** 重写paint()画 */
             public void paint(Graphics g) {
                 sky.paintObject(g);
                 hero.paintObject(g);
                 for(int i = 0;i < enemies.length ;i++) {
                     enemies[i].paintObject(g);
                 }
                 for(int i = 0;i < bullets.length ;i++) {
                     bullets[i].paintObject(g); 
                 }
                 g.drawString("SCORE:" + score, 10, 25);
                 g.drawString("LIFE:" + hero.getLife(), 10, 45);
                             
                 switch(state) {
                 case START:
                     g.drawImage(start,0,0,null);
                     break;
                 case PAUSE:
                     g.drawImage(pause,0,0,null);
                     break;
                 case GAME_OVER:
                     g.drawImage(gameover,0,0,null);
                     break;
                 }
             }            public static void main(String[] args) {
                 //画窗口
                 JFrame frame = new JFrame();
                 World world = new World();
                 frame.add(world);
                 
                 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                 frame.setSize(WIDTH,HEIGHT);
                 frame.setLocationRelativeTo(null);
                 frame.setVisible(true); //1设置窗口可见2尽快调用paint()方法
                 
                 world.action();
                 
             }
             
 }
  Sky
package com.atjialiangExer;
 import java.awt.Graphics;
 import java.awt.image.BufferedImage;//装图片的类
 public class Sky extends FlyingObject {
     private static BufferedImage image;
     static { //静态块给图片赋值
         image = loadImage("background.png");
     }
     
     private int speed;
     private int y1;//第二张图片的y坐标
     
     /**构造方法 */
     public Sky(){
         super(World.WIDTH,World.HEIGHT,0,0);
         speed = 1;
         y1 = -World.HEIGHT;
     }
     
     /** 重写 step()移动 */
     public void step() {
         y += speed;
         y1 += speed;
         if(y >= World.HEIGHT) {
             y = -World.HEIGHT;
         }
         if(y1 >= World.HEIGHT) {
             y1 = -World.HEIGHT;
         }
     }
     
     /**重写 getImage */
     public BufferedImage getImage() {
         return image; //直接返回image
     }
     
     /** 重写:画对象  g:画笔 */
     public void paintObject(Graphics g) { //谁调用就画谁
         g.drawImage(getImage(),x,y,null);
         g.drawImage(getImage(),x,y1,null);
     }
 }FlyingObject
 package com.atjialiangExer;
import java.util.Random;
 import java.awt.image.BufferedImage;
 import javax.imageio.ImageIO;
 import java.awt.Graphics;
   
    /** 飞行器 (超类) */
    public abstract class FlyingObject {
     public static final int LIFE = 0;
     public static final int DEAD = 1;
     public static final int REMOVE = 2;    
     protected int state = LIFE;
     
     protected int width;
     protected int height;
     protected int x;
     protected int y;
     
     /** 专门给小敌机、大敌机、小蜜蜂 */
     public FlyingObject(int width,int height) {
         this.width = width;
         this.height = height;
         Random rand = new Random(); 
         x = rand.nextInt(World.WIDTH - this.width); 
         y = this.height;
     }
     
     /** 专门给英雄机、天空、子弹 */
     public FlyingObject(int width,int height,int x,int y) {
         this.width = width;
         this.height = height;
         this.x = x;
         this.y = y;
     }
     
     /** 读取图片 */
     public static BufferedImage loadImage(String fileName) {
         try {//异常处理
             BufferedImage img = ImageIO.read(FlyingObject.class.getResource(fileName));//同包图片读写
               return img;        
         }catch (Exception e) {
             e.printStackTrace();
             throw new RuntimeException(); 
         }
     }
     
     /** 飞行物移动 */
     public abstract void step();
     
     /** 获取对象的图片*/    
     public abstract BufferedImage getImage();    /** 判断是否活着 */
     public boolean isLife() { 
             return state == LIFE;
     }
     
     public boolean isDead() {
         return state == DEAD;
     }
     
     public boolean isRemove() {
         return state == REMOVE;
     }
     
     
     /** 检查是否越界 */
     public boolean outOfBounds() {
         return this.y >= World.HEIGHT;
     }
     
     /** 检测是否碰撞   this:敌人    other:子弹、英雄机*/
     public boolean hit(FlyingObject other) {         
             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;
         }
     
         public void goDead() {
                 state = DEAD;
         }
     
     
     /** 画对象  g:画笔 */
     public void paintObject(Graphics g) { //谁调用就画谁
         g.drawImage(getImage(),x,y,null);
     }
 }
  Hero
package com.atjialiangExer;
import java.awt.image.BufferedImage;
public class Hero extends FlyingObject{
     private static BufferedImage[] images;
     static { //静态块给图片赋值
         images = new BufferedImage[2];
         images[0] = loadImage("hero0.png");
         images[1] = loadImage("hero1.png"); 
     }
     
     private int life;
     private int doubleFire;
     
     public Hero(){
         super(97,139,140,400);
         life = 3;
         doubleFire = 0;        
     }
     
     /** 英雄机随着鼠标移动 x/y */
     public void moveTo(int x, int y) {
         this.x = x - this.width / 2;
         this.y = y - this.height / 2;
     }
     
     /** 重写 step()移动 */
     public void step() {
         
     }
     
     int index = 0;
     /** 重写getImage */
     public BufferedImage getImage() {  //每10毫秒切换一次
         if(isLife()) {
             return images[index++ % images.length ]; //0和1的切换
         }
         return null;
     }
     
     /** 子弹生成  */
     public Bullet[] shoot() {
         int xStep = this.width / 4;
         int yStep = 20;            //间隔固定
         if(doubleFire > 0) {
             Bullet[] bs = new Bullet[2];
             bs[0] = new Bullet(this.x + 1 * xStep,this.y - yStep);
             bs[1] = new Bullet(this.x + 3 * xStep,this.y - yStep);
             doubleFire -= 2;
             return bs;
         }else {
             Bullet[] bs = new Bullet[1];
             bs[0] = new Bullet(this.x + 2 * xStep,this.y - yStep);
             return bs;
         }
     }
     
     /** 增加生命 */
     public void addlife() {
         life++;
     }
     
     /** 获取生命值*/
     public int getLife() {
         return life;        
     }
     
     /** 增加火力 */
     public void addDoubleFire() {
         doubleFire += 40;
     }
     
     /** 减少生命 */
     public void subtractlife() {
         life--;
     }
     
     /** 清除火力 */
     public void clearDoubleFire() {
         doubleFire = 0;
     }
 }AirPlane
import java.awt.image.BufferedImage;
 import java.util.Random;public  class AirPlane extends FlyingObject implements Enemy{
     private static BufferedImage[] images;
     static { //静态块给图片赋值
         images = new BufferedImage[5];
         for(int i = 0;i < images.length;i++) {
             images[i] = loadImage("airplane" + i + ".png");
         }
         
     }
     
     private int speed;
     
     public AirPlane(){
         super(49,36);
         speed = 2;
     }
     
     /** 重写 step()移动 */
     public void step() {
         y += speed; 
     }
     
     int index = 1;
     /** 重写getImage */
     public BufferedImage getImage() { //如果死了,每10毫秒返回一张图片
         if(isLife()) {
             return images[0];
         }else if(isDead()) {
             BufferedImage img = images[index++];
             if(index == images.length ) {
                 state = REMOVE;
             }
             return img;
         }
         return null;  //删除状态,返回null    
     }
     
     /** 重写getScore */
     public int getScore() {
         return 1; //打掉小敌机
     }
 }
  BigAirPlane
package com.atjialiangExer;
import java.awt.image.BufferedImage;
 import java.util.Random;public class BigAirPlane extends FlyingObject implements Enemy{
     private static BufferedImage[] images;
     static { //静态块给图片赋值
         images = new BufferedImage[2];
         for(int i = 0;i < images.length;i++) {
             images[i] = loadImage("bigplane" + i + ".png");
         }
     }
     
     private int speed;
     
     public BigAirPlane(){
         super(66,89);
         speed = 2;
         }
     
     /** 重写 step()移动 */
     public void step() {
         y += speed;
     }
     
     int index = 1;
     /** 重写getImage */
     public BufferedImage getImage() { //如果死了,每10毫秒返回一张图片
         if(isLife()) {
             return images[0];
         }else if(isDead()) {
             BufferedImage img = images[index++];
             if(index == images.length ) {
                 state = REMOVE;
             }
             return img;
         }
         return null;  //删除状态,返回null    
     }
     
     /** 重写getScore */
     public int getScore() {
         return 3; //打掉大敌机
     }    
 }Bee
package com.atjialiangExer;
import java.awt.image.BufferedImage;
 import java.util.Random;
 import java.util.Random;
 public  class Bee extends FlyingObject implements Award{
     private static BufferedImage[] images;
     static { //静态块给图片赋值
         images = new BufferedImage[5];
         for(int i = 0;i < images.length;i++) {
             images[i] = loadImage("bee" + i + ".png");
         }
     }
     
     private int xSpeed;
     private int ySpeed;
     private int awardType;//奖励类型:随机生成
     
     public Bee(){
         super(60,51);
         xSpeed = 1;
         ySpeed = 2;    
         Random rand = new Random();
         awardType = rand.nextInt(2);//0或者1
       }        
     
     /** 重写 step()移动 */
     public void step() {
         x += xSpeed;
         y += ySpeed;
         if(x <= 0 || x >= World.WIDTH - this.width) { //换方向
             xSpeed *= -1;
         }
     }
     
     int index = 1;
     /** 重写getImage */
     public BufferedImage getImage() { //如果死了,每10毫秒返回一张图片
         if(isLife()) {
             return images[0];
         }else if(isDead()) {
             BufferedImage img = images[index++];
             if(index == images.length ) {
                 state = REMOVE;
             }
             return img;
         }
         return null;  //删除状态,返回null    
     }
     
     /** 重写getAwardType */
     public int getAwardType() {
         return awardType;
     }
 }
  Bullet
package com.atjialiangExer;
import java.awt.image.BufferedImage;
public class Bullet extends FlyingObject{
     private static BufferedImage image;
     static { //静态块给图片赋值
         image = loadImage("bullet.png");
     }
     
     private int speed;
     
     public Bullet(int x,int y){
         super(8,14,x,y);
         speed = 3;
     }
     
     /** 重写 step()移动 */
     public void step() {
         y -= speed;
     }
     
     /** 重写getImage */
     public BufferedImage getImage() {
         if(isLife()) {
             return image;
         }else if(isDead()) {
             state = REMOVE;
         }
         return null;
     }
     
     /** 重写子弹是否越界 */
     public boolean outOfBounds() {
         return this.y <= -this.height;
     }
 }
  Enemy
package com.atjialiangExer;
 /** 得分接口 */
 public interface Enemy {
     /** 得分 */
     public int getScore();    
 }
  Award
package com.atjialiangExer;
 /** 奖励接口 */
 public interface Award {
      public int DOUBLE_FIRE = 0;
      public int LIFE = 1;
      /** 获取奖励类型  返回0或1 */
      public int getAwardType();
 }