飞机大战JAVA编程

来源:互联网 发布:java pdf转word 编辑:程序博客网 时间:2024/04/29 17:02

飞机大战JAVA编程

最近在学习java语言,飞机大战是其中一个练习小项目。这里记录一下写这个程序的思路。

  • 首先是需求分析,这里建立项目需求的思维导图,一目了然:

    这里写图片描述
  • 然后是思路分析

    这里写图片描述
    这是写程序前列举的一个基本的思路,以此为主线,写的时候遇到具体问题再进行修改,最后得出最终程序。
  • 最后是写好的程序结构图:

    这里写图片描述

这里就不多写文字了,所有内容都在图中,下面是运行结果和源代码。
运行结果:


这里写图片描述
源码:

//FlyingObject类,抽象类:package com.centerm.shoot;import java.awt.image.BufferedImage;/** * 将四个主要角色的共同属性提取出来组成一个父类 * @author 89447 */public abstract class FlyingObject {    //定义所有飞行器共有的属性:图片、坐标、尺寸    protected BufferedImage image;    protected int x;    protected int y;    protected int width;    protected int height;    //定义所有飞行器共有的方法:移动、越界    public abstract void moveFlying();    public abstract boolean outOfBound();    //下面定义的这个方法只有Airplane和Bee使用    public boolean shootBy(Bullet bullet){        int x1 = this.x;        int x2 = this.x + this.width;        int y1 = this.y;        int y2 = this.y + this.height;        int xb1 = bullet.x;        int xb2 = bullet.x + bullet.width;        int yb1 = bullet.y;        int yb2 = bullet.y + bullet.height;        return (xb1>x1 && xb1<x2) && (yb1>y1 && yb1<y2) ||                 (xb2>x1 && xb2<x2) && (yb1>y1 && yb1<y2) ||                 (xb1>x1 && xb1<x2) && (yb2>y1 && yb2<y2) ||                 (xb2>x1 && xb2<x2) && (yb2>y1 && yb2<y2);    }}
package com.centerm.shoot;import java.util.Random;/** * 敌机 * @author 89447 * */public class Airplane extends FlyingObject{    //前进速度    private int speed;    //构造方法    public Airplane(){        image = Stage.airplane;        x = new Random().nextInt(Stage.STAGE_WIDTH - image.getWidth());        y = -image.getHeight();        width = image.getWidth();        height = image.getHeight();        speed = 3;    }    //移动    public void moveFlying(){        this.y += this.speed;    }    //出界判断    public boolean outOfBound() {        return this.y > Stage.STAGE_HEIGHT;    }}
package com.centerm.shoot;import java.util.Random;/** * 蜜蜂类 * @author 89447 * */public class Bee extends FlyingObject{    //奖励类型    public static final int AWARD_LIFE = 0;    public static final int AWARD_FIRE = 1;    //左右飞行,用于飞行方向的改变    private static final int FLY_RIGHT = 1;    private static final int FLY_LEFT = -1;    //飞行方向变量    private int flyingDirection = FLY_RIGHT;    //X、Y方向上前进的速度    private int speedX;    private int speedY;    //构造函数    public Bee(){        image = Stage.bee;        x = new Random().nextInt(Stage.STAGE_WIDTH - image.getWidth());        y = -image.getHeight();        width = image.getWidth();        height = image.getHeight();        speedX = 2;        speedY = 1;    }    //移动一步    public void moveFlying(){        /**         * 先确定小蜜蜂飞行的方向         */        if(this.x >= Stage.STAGE_WIDTH - this.width){            flyingDirection = FLY_LEFT;        }        if(this.x <= 0){            flyingDirection = FLY_RIGHT;        }        /**         * 再根据方向进行移动         */        if(flyingDirection == FLY_RIGHT){            this.x += this.speedX;            this.y += this.speedY;        }else{            this.x -= this.speedX;            this.y += this.speedY;        }    }    //获取奖励类型    public int getAwardType(){        return new Random().nextInt(2)==AWARD_LIFE ? AWARD_LIFE : AWARD_FIRE;    }    //判断出界    public boolean outOfBound() {        return this.y > Stage.STAGE_HEIGHT;    }}
package com.centerm.shoot;/** * 子弹类 * @author 89447 * */public class Bullet extends FlyingObject{    //子弹运行速率    private int speed;    //构造函数    public Bullet(int x, int y){        this.x = x;        this.y = y;        image = Stage.bullet;        width = image.getWidth();        height = image.getHeight();        speed = 4;    }    //子弹移动一步    public void moveFlying(){        this.y -= this.speed;    }    //判断出界    public boolean outOfBound() {        return this.y < 0;    }}
package com.centerm.shoot;/** * 英雄机的类 * @author 89447 * */public class Hero extends FlyingObject{    //定义默认生命值    private static final int DEFAULT_LIFE = 3;      //定义移动方向,用于键盘控制    public static final int MOVE_UP = 1;            public static final int MOVE_DOWN = -1;    public static final int MOVE_LEFT = 2;    public static final int MOVE_RIGHT = -2;    //定义一次移动的距离,用于键盘控制    public static final int STEP_DISTANCE = 10;             //定义火力值、生命值    private int firePower;    private int life;    //构造函数    public Hero(int x, int y){        this.x = x;        this.y = y;        image = Stage.hero0;        width = image.getWidth();        height = image.getHeight();        firePower = 0;        life = DEFAULT_LIFE;    }    //获取生命值    public int getLife(){        return life;    }    //生命值减一    public void substactLife() {        this.life --;    }    //生命值加一    public void addLife() {        this.life ++;    }    //获取双倍火力值    public int getFirePower(){        return firePower;    }    //清空火力值    public void clrFirePower(){        firePower = 0;    }    //火力值增加固定的数值    public void addFirePower(){        firePower += 40;    }    //英雄机按照某个方向移动一步,用于键盘控制    public void moveDirection(int direction){        switch (direction) {        case MOVE_DOWN:            if(this.y >= Stage.STAGE_HEIGHT - this.height){                break;            }else if(this.y >= Stage.STAGE_HEIGHT - this.height- STEP_DISTANCE &&                    this.y <Stage.STAGE_HEIGHT - this.height){                this.y = Stage.STAGE_HEIGHT - this.height;            }else{                this.y += STEP_DISTANCE;            }            break;        case MOVE_UP:            if(this.y == 0){                break;            }else if(this.y > 0 && this.y <= STEP_DISTANCE){                this.y = 0;            }else {                this.y -= STEP_DISTANCE;            }            break;        case MOVE_LEFT:            if(this.x == 0){                break;            }else if(this.x > 0 && this.x <= STEP_DISTANCE){                this.x = 0;            }else {                this.x -= STEP_DISTANCE;            }            break;        case MOVE_RIGHT:            if(this.x == Stage.STAGE_WIDTH - this.width){                break;            }else if(this.x >= Stage.STAGE_WIDTH - this.width - STEP_DISTANCE &&                 this.x < Stage.STAGE_WIDTH - this.width){                this.x = Stage.STAGE_WIDTH - this.width;            }else {                this.x += STEP_DISTANCE;            }            break;        default:            break;        }    }    //英雄机移动,用于图片切换    private int indexOfImage = 0;    public void moveFlying(){        indexOfImage = 1 - indexOfImage;        if(indexOfImage == 0){            image = Stage.hero0;        }else{            image = Stage.hero1;        }    }    //直接将英雄机移动到某个确定的位置,用于鼠标控制    public void setLocation(int x, int y){        this.x = x - this.width/2;        this.y = y - this.height/2;    }    //创建子弹,可能是一个,也可能是两个,因此这里返回数组    public Bullet[] createBullets(){        if(firePower > 0){            firePower -= 2;            return new Bullet[]{new Bullet(this.x + this.width/4 - 10, this.y),                                 new Bullet(this.x + this.width*3/4 - 10, this.y)};        }else {            return new Bullet[]{new Bullet(this.x + this.width/2 - 10, this.y)};        }    }    //出界判断,由于英雄机无法出界,因此这里返回null    public boolean outOfBound() {        return false;    }    //英雄机撞击敌机判断    public boolean hitFlying(FlyingObject flying){        int x1 = this.x;        int x2 = this.x + this.width;        int y1 = this.y;        int y2 = this.y + this.height;        int xb1 = flying.x;        int xb2 = flying.x + flying.width;        int yb1 = flying.y;        int yb2 = flying.y + flying.height;        return (xb1>x1 && xb1<x2) && (yb1>y1 && yb1<y2) ||                 (xb2>x1 && xb2<x2) && (yb1>y1 && yb1<y2) ||                 (xb1>x1 && xb1<x2) && (yb2>y1 && yb2<y2) ||                 (xb2>x1 && xb2<x2) && (yb2>y1 && yb2<y2);    }}
//舞台类,关键package com.centerm.shoot;import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.image.BufferedImage;import java.io.File;import java.io.IOException;import java.util.Arrays;import java.util.Random;import java.util.Timer;import java.util.TimerTask;import javax.imageio.ImageIO;import javax.swing.JFrame;import javax.swing.JPanel;/** * 舞台类 * @author 89447 * */@SuppressWarnings("serial")public class Stage extends JPanel{    public static final int STAGE_WIDTH = 400;    public static final int STAGE_HEIGHT = 650;    public static final String PATH = "." + File.separator + "src" + File.separator + "com" + File.separator + "centerm" + File.separator + "shoot" + File.separator;    /**     * 下面统一管理图片,也可以放在各个具体的类中,但是会显得比较混乱,因此这里放在一起     */    public static BufferedImage hero0;    public static BufferedImage hero1;    public static BufferedImage bee;    public static BufferedImage bullet;    public static BufferedImage airplane;    public static BufferedImage background;    public static BufferedImage pause;    public static BufferedImage start;    public static BufferedImage gameover;    //定义几个状态    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;    //主要的成员变量    private Hero hero = new Hero(200,300);;    private Bullet[] bullets = {};    private FlyingObject[] flyings = {};    //分数    private int score = 0;    //初始化图片的静态块    static{        try {            hero0 = ImageIO.read(new File(PATH + "hero0.bmp"));            hero1 = ImageIO.read(new File(PATH + "hero1.bmp"));            bee = ImageIO.read(new File(PATH + "bee.bmp"));            bullet = ImageIO.read(new File(PATH + "bullet.bmp"));            airplane = ImageIO.read(new File(PATH + "airplane.bmp"));            background = ImageIO.read(new File(PATH + "background.bmp"));            pause = ImageIO.read(new File(PATH + "pause.bmp"));            start = ImageIO.read(new File(PATH + "start.bmp"));            gameover = ImageIO.read(new File(PATH + "gameover.bmp"));        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }    //绘制所有元素    public void paint(Graphics g) {        // TODO Auto-generated method stub        g.drawImage(background, 0, 0, null);    //绘制背景图片        paintHero(g);   //绘制英雄机        paintFlyings(g);//绘制敌机:包括小蜜蜂和飞行器        paintBullet(g); //绘制子弹:        paintText(g);        paintState(g);    }    //绘制英雄机,为paint()服务    public void paintHero(Graphics g){        g.drawImage(hero.image, hero.x, hero.y, null);    }    //绘制敌机,为paint()服务    public void paintFlyings(Graphics g){        for(FlyingObject flying : flyings){            g.drawImage(flying.image, flying.x, flying.y, null);        }    }    //绘制子弹,为paint()服务    public void paintBullet(Graphics g){        for(Bullet bullet : bullets){            g.drawImage(bullet.image, bullet.x, bullet.y, null);        }    }    //绘制文字信息,为paint()服务    public void paintText(Graphics g){        g.setColor(new Color(0xff0000));        g.setFont(new Font(Font.DIALOG, 20, 20));        g.drawString("生命数:"+Integer.toString(hero.getLife()), 0, 100);        g.drawString("分数:"+Integer.toString(score), 0, 50);        g.drawString("火力剩余:"+Integer.toString(hero.getFirePower()), 0, 75);    }    //绘制各个状态下的图片,为paint()服务    public void paintState(Graphics g){        switch(state){        case START:            g.drawImage(start, 0, 0, null);            break;        case RUNNING:            break;        case PAUSE:            g.drawImage(pause, 0, 0, null);            break;        case GAMEOVER:            g.drawImage(gameover, 0, 0, null);            break;        default:            break;        }    }    //生成新的敌机,为FlyingEnter()方法服务    public FlyingObject createFlying(){        Random random = new Random();        if(random.nextInt(20) < 2){            return new Bee();        }else{            return new Airplane();        }    }    //敌机入场    int flyingEnterDelay = 0;    public void FlyingEnter(){        if(flyingEnterDelay ++ >= 40){            flyingEnterDelay = 0;            flyings = Arrays.copyOf(flyings, flyings.length + 1);            flyings[flyings.length - 1] = createFlying();        }    }    //子弹入场    int BulletEnterDelay = 0;    public void BulletEnter(){        if(BulletEnterDelay ++ >= 20){            BulletEnterDelay = 0;            Bullet[] bullets_temp = hero.createBullets();            bullets = Arrays.copyOf(bullets, bullets.length + bullets_temp.length);            for(int i = 0; i<bullets_temp.length; i++){                bullets[bullets.length - i - 1] = bullets_temp[i];            }        }    }    //移动一帧    public void moveStepAction(){        //移动英雄机:切换图片        hero.moveFlying();        //移动敌机        for(FlyingObject flying: flyings){            flying.moveFlying();        }        //移动子弹        for(Bullet bullet: bullets){            bullet.moveFlying();        }    }    //出界处理方法    public void outOfBoundAction(){        FlyingObject[] flying_temp = new FlyingObject[flyings.length];        int flying_index = 0;        for(int i = 0; i<flyings.length; i++){            FlyingObject flying = flyings[i];            if(!flying.outOfBound()){                flying_temp[flying_index ++] = flying;            }        }        flyings = Arrays.copyOf(flying_temp, flying_index);        Bullet[] bullets_temp = new Bullet[bullets.length];        int bullet_index = 0;        for(int i = 0; i<bullets.length; i++){            Bullet bullet = bullets[i];            if(!bullet.outOfBound()){                bullets_temp[bullet_index ++] = bullet;            }        }        bullets = Arrays.copyOf(bullets_temp, bullet_index);    }    //一颗子弹射击敌机方法,为shootAction()服务    public boolean bulletShootFlyings(Bullet bullet){        int index = -1;        FlyingObject flying;        for(int i = 0; i<flyings.length; i++){            flying = flyings[i];            if(flying.shootBy(bullet)){                index = i;  //如果有撞击到,将被撞击的元素下标取出,在外部处理这个元素,避免嵌套过深                break;            }        }        if(index != -1){            flying = flyings[index];            if(flying instanceof Bee){                int type = ((Bee) flying).getAwardType();                if(type == Bee.AWARD_FIRE){                    hero.addFirePower();                }                if(type == Bee.AWARD_LIFE){                    hero.addLife();                }            }            if(flying instanceof Airplane){                score += 5;            }            //省去了使用循环操作的麻烦            flyings[index] = flyings[flyings.length - 1];            flyings = Arrays.copyOf(flyings, flyings.length - 1);            return true;        }        return false;    }    //子弹击落敌机方法    public void shootAction(){        Bullet[] bullets_temp = new Bullet[bullets.length];        int bullet_index = 0;        for(int i = 0; i<bullets.length; i++){            Bullet bullet = bullets[i];            if(!bulletShootFlyings(bullet)){                bullets_temp[bullet_index ++] = bullet;            }        }        bullets = Arrays.copyOf(bullets_temp, bullet_index);    }    //英雄机撞击敌人    public void hitAction(){        for(int i = 0; i<flyings.length; i++){            FlyingObject flying = flyings[i];            if(hero.hitFlying(flying)){                hero.substactLife();                hero.clrFirePower();                flyings[i] = flyings[flyings.length - 1];                flyings = Arrays.copyOf(flyings, flyings.length - 1);            }        }    }    public void gameOverAction(){        if(hero.getLife() <= 0){            state = GAMEOVER;        }    }    public void action(){        Timer timer = new Timer();        /**         * 用于移动的定时任务         */        timer.schedule(new TimerTask() {            @Override            public void run() {                if(state == RUNNING){                    FlyingEnter();                    BulletEnter();                    moveStepAction();                    outOfBoundAction();                    shootAction();                    hitAction();                    gameOverAction();                }                repaint();            }        }, 0, 10);        /**         * 键盘控制英雄机的行动         */        this.requestFocus();            this.addKeyListener(new KeyAdapter() {            public void keyPressed(KeyEvent e) {                    if(state == RUNNING){   //程序没有运行时英雄机是不能动的                    switch(e.getKeyCode()){                    case KeyEvent.VK_UP:                        hero.moveDirection(Hero.MOVE_UP);                        repaint();                        break;                    case KeyEvent.VK_DOWN:                        hero.moveDirection(Hero.MOVE_DOWN);                        repaint();                        break;                    case KeyEvent.VK_LEFT:                        hero.moveDirection(Hero.MOVE_LEFT);                        repaint();                        break;                    case KeyEvent.VK_RIGHT:                        hero.moveDirection(Hero.MOVE_RIGHT);                        repaint();                        break;                    default:                        break;                    }                }            }        });        /**         * 鼠标控制英雄机的行动         */        MouseAdapter adapter = new  MouseAdapter() {            public void mouseMoved(MouseEvent arg0) {                if(state == RUNNING){   //状态不是运行时候不能移动英雄机                    hero.setLocation(arg0.getX(), arg0.getY());                }            }            public void mouseClicked(MouseEvent arg0) {                if(state == START){                    state = RUNNING;                }                if(state == GAMEOVER){                    score = 0;                    hero = new Hero(200, 300);                    flyings = new FlyingObject[]{};                    bullets = new Bullet[]{};                    state = START;                }            }            public void mouseExited(MouseEvent arg0) {                if(state == RUNNING){                    state = PAUSE;                }            }            public void mouseEntered(MouseEvent arg0) {                if(state == PAUSE){                    state = RUNNING;                }            }        };        this.addMouseListener(adapter);        this.addMouseMotionListener(adapter);    }    public static void main(String[] args) {        JFrame frame = new JFrame();        Stage panel = new Stage();        frame.add(panel);        frame.setSize(STAGE_WIDTH+10, STAGE_HEIGHT+10);        frame.setAlwaysOnTop(true);     //将串口一直放在所有窗口之上        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   //设置默认关闭操作为串口关闭时退出程序        frame.setLocationRelativeTo(null);  //设置窗口位置居中        frame.setVisible(true);         //显示窗口,尽快调用paint()方法        panel.action();    }}
0 0
原创粉丝点击