Java飞机大战

本文详细介绍了使用JavaSwing开发一款飞机大战小游戏的过程,包括游戏界面组件的绘制、组件的动态运动以及碰撞检测的实现。通过面向对象编程,利用多线程控制不同组件的运动状态,确保游戏流畅运行。同时,文章还展示了游戏的主程序入口、监听器、游戏对象类等关键代码实现。
摘要由CSDN通过智能技术生成

一、项目分析

   1、设计步骤

      在一个Java Swing的小游戏中,首先需要考虑的是组件的绘制,其次是如何让需要运动的组件运动起来,最后是如何检测物体的碰撞等。

      (1)、组件绘制:这一步需要将游戏界面中的组件全部绘制出来,包括背景、飞机、子弹、文字等。

      (2)、组件运动:游戏开始,首先需要背景滚动起来,其次是飞机、子弹等物体需要运动,这里需要使用多线程控制不同组件的运动状态。

      (3)、组件碰撞:这一步需要对物体进行碰撞检测,以便在后续结算过程能得到数据,以及判断飞机是否被击落等情况。

    2、知识点

      (1)、面向对象的开发思想和过程,其中包括封装、接口实现和继承等。

      (2)、Java Swing使用,其中包括窗口创建、图形绘制等。

      (3)、ArrayList使用,使用ArrayList存储并读取对象等。

      (4)、多线程技术,通过多线程控制不同的组件完成不同的效果

二、代码实现

    1、主程序入口

public class GameMain extends JFrame implements config{
    static int gameStatus = 0; //游戏状态码,0表示未开始
    BufferedImage BFI; //图像双缓冲
    GameListener gl; //当前界面的监听器

    //窗口设置
    public void setWindow(int width , int height){
        //窗口标题
        this.setTitle("飞机大战");
        //窗口大小设置
        Dimension d = this.getToolkit().getScreenSize();
        Rectangle r = new Rectangle((d.width - width) / 2 , (d.height - height) / 2 , width , height);
        this.setBounds(r);
        //设置窗口可见
        this.setVisible(true);
        //无法调节窗口大小    
        this.setResizable(false);
        //窗口关闭状态
        this.setDefaultCloseOperation(3);
        //窗口图像缓冲,在重绘组件时防止闪烁
        BFI = new BufferedImage(windowsWidth , windowsHeight , 2);
    }

    //添加监听器
    public void addListener(){
        //获取界面画笔
        Graphics g = this.getGraphics();
        //将画笔传给监听器,在监听到鼠标时绘制相应组件
        gl = new GameListener(g);
        //在窗口添加监听器
        this.addMouseListener(gl);//鼠标点击事件
        this.addMouseMotionListener(gl);//鼠标滑动事件
        this.addKeyListener(gl);//键盘输入事件
    }


    //设置窗口重绘功能,保证在最小化后图像依然存在
    @Override
    public void paint(Graphics g) {
        //游戏未开始时绘制开始界面
        if(gameStatus == 0){
            g.drawImage(backGround , 0 , 0 , null);
            g.drawImage(plane0 , 80 , 40 , null);
            g.setColor(Color.ORANGE);
            g.setFont(new Font("Strasua" , Font.BOLD , 35));
            g.drawString("CLICK TO START" , 75 , 500);
        }
    }

    //初始化函数
    public void init(){
        setWindow(windowsWidth , windowsHeight);
        addListener();

    }

    public static void main(String[] args) {
        GameMain gm = new GameMain();
        gm.init();
    }
}

 

     2、监听器

public class GameListener extends JPanel implements KeyListener, MouseListener , MouseMotionListener , config{
    //设置监听器画笔
    Graphics drawObj;
    //设置游戏状态
    static int gameStatus;
    //键盘按键代码
    static int keyCode;


    public GameListener(Graphics g){
        this.drawObj = g;
    }

    public void keyTyped(KeyEvent e) {
        }
    public void keyPressed(KeyEvent e) {
        //设置游戏暂停功能(按下空格)
        keyCode = e.getKeyCode();
        if(e.getKeyCode() == 32){
            switch (gameStatus){
                case 1:
                    gameStatus = 0;
                    break;
                case 0:
                    gameStatus = 1;
                    break;
            }
        }

        }
    public void keyReleased(KeyEvent e) {
        }

    public void mouseClicked(MouseEvent e) {
        //当状态码为1时启动绘制组件的线程
        if(e.getButton() == 1 && gameStatus == 0 && keyCode != 32){
            gameStatus = 1;
            objMotion();
        }
        if(keyCode == 32){
            System.out.println("暂停");
        }
    }

    public void mousePressed(MouseEvent e) {}

    public void mouseReleased(MouseEvent e) {}

    public void mouseEntered(MouseEvent e) {}

    public void mouseExited(MouseEvent e) {}

    public void mouseDragged(MouseEvent e){}

    public void mouseMoved(MouseEvent e){
        //捕捉鼠标的坐标
        if(gameStatus == 1){
            objectMotion.setX(e.getX());
            objectMotion.setY(e.getY());
        }
    }

  
}

     3、游戏对象类

public class GameObject extends JPanel implements config{

    Image img;
    int x , y , width , height;
    double speedX , speedY;

    //一下均为对象类的构造器,每个构造器所含参数不同,根据每个对象的需求使用。
    public GameObject(){}

    public GameObject(Image img , int x , int y , int width , int height , double speedY){
        this.img = img;
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.speedY = speedY;
    }

    public GameObject(Image img , int x , int y){
        this.img = img;
        this.x = x;
        this.y = y;
    }

    public GameObject(Image img, int x, int y, int width, int height, double speedX, double speedY) {
        this.img = img;
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.speedX = speedX;
        this.speedY = speedY;
    }

    public GameObject(Image img, int x, int y, double speedX, double speedY) {
        this.img = img;
        this.x = x;
        this.y = y;
        this.speedX = speedX;
        this.speedY = speedY;
    }

    public GameObject(Image img, int x, int y, double speedY) {
        this.img = img;
        this.x = x;
        this.y = y;
        this.speedY = speedY;
    }

    //图片
    public Image getImg() {
        return img;
    }

    public void setImg(Image img) {
        this.img = img;
    }

    //物体坐标
    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    //物体大小
    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }


    //物体速度
    public double getSpeedX() {
        return speedX;
    }

    public void setSpeedX(double speedX) {
        this.speedX = speedX;
    }

    public double getSpeedY() {
        return speedY;
    }

    public void setSpeedY(double speedY) {
        this.speedY = speedY;
    }

    //对象的绘制方法
    public void paintSelf(Graphics g){
        g.drawImage(img , x , y , null);
    }

    //获取对象的矩形,后续进行碰撞检测
    public Rectangle getRec(){
        return new Rectangle(this.x , this.y , this.width , this.height);
    }
}

     4、我方战机类

public class PlayerPlane extends GameObject implements config{
    BufferedImage BFI3;
    static Rectangle enePlaneBullet;

    //设置玩家机生命
    static int life = 100;

   
    //玩家机构造器
    public PlayerPlane(Image img, int x, int y, int width, int height, double speedX, double speedY) {
        super(img, x, y, width, height, speedX, speedY);
    }

    public PlayerPlane(Image img , int x , int y , int width , int height){
        this.img = img;
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    public PlayerPlane(Image img, int x, int y) {
        super(img, x, y);
    }

    public PlayerPlane(){}

    public PlayerPlane(Image img, int x, int y, double speedX, double speedY) {
        super(img, x, y, speedX, speedY);
    }



    public void setLife(int life){
        this.life = life;
    }

 
    public int getLife(){
        return life;
    }

    @Override
    public int getX() {
        return super.getX() - 38;
    }

    @Override
    public void setX(int x) {
        super.setX(x);
    }

    @Override
    public int getY() {
        return super.getY() - 38;
    }

    @Override
    public void setY(int y) {
        super.setY(y);
    }

    @Override
    public void paintSelf(Graphics g) {
        g.drawImage(img , getX() , getY() , null);
    }

    @Override
    public Rectangle getRec() {
        return super.getRec();
    }

}

     5、我方战机子弹

public class Bullet extends GameObject implements config{

    public Bullet(){}
    public Bullet(Image img, int x, int y, int width, int height, double speedX, double speedY) {
        super(img, x, y, width, height, speedX, speedY);
    }

    public Bullet(Image img, int x, int y, double speedX, double speedY) {
        super(img, x, y, speedX, speedY);
    }


    @Override
    public int getX() {
        return super.getX();
    }

    @Override
    public void setX(int x) {
        super.setX(x);
    }

    @Override
    public int getY() {
        return super.getY();
    }

    @Override
    public void setY(int y) {
        super.setY(y);
    }

    @Override
    public void paintSelf(Graphics g) {
        y += speedY; //子弹速度设置
        g.drawImage(img , x , y , null);
    }

    @Override
    public Rectangle getRec() {
        return super.getRec();
    }
}

     6、敌方战机

public class enePlaneObj extends GameObject implements config{
    static Rectangle playerPlane;

    static Bullet playerPlaneBullet;

    PlayerPlane playerPlane01 = new PlayerPlane();

    Score score = new Score();

    public enePlaneObj (){}

    public enePlaneObj(Image img, int x, int y, int width, int height, double speedX, double speedY) {
        super(img, x, y, width, height, speedX, speedY);
    }

    //敌机矩形
    public void setPlayerPlane(Rectangle playerPlane) {
        this.playerPlane = playerPlane;
    }

    public void setPlayerPlaneBullet(Bullet playerPlaneBullet){
        this.playerPlaneBullet = playerPlaneBullet;
    }

    @Override
    public void setSpeedX(double speedX) {
        super.setSpeedX(speedX);
    }

    @Override
    public void setSpeedY(double speedY) {
        super.setSpeedY(speedY);
    }

    @Override
    public void paintSelf(Graphics g) {
        x += speedX;
        y += speedY;
        g.drawImage(img , x , y , null);
        //敌机与玩家机碰撞检测
        //新建碰撞检测对象
        rectCross rectCross = new rectCross(this.getX() , this.getY() , this.getWidth() , this.getHeight() , (int)(playerPlane.getX()) - 38 , (int)(playerPlane.getY()) - 38, (int)(playerPlane.getWidth()) - 19 , (int)(playerPlane.getHeight()) - 19);
        //发生碰撞后,敌机消失,分数增加
        if( rectCross.cross() == true){
            g.drawImage(explode , this.getX() - 50 , this .getY() - 50 , null);
            playerPlane01.setLife(playerPlane01.getLife() - 4);
            score.setScore(score.getScore() + 1);
            this.setX(-100);
            this.setY(100);
        }
        //敌机与玩家子弹碰撞检测
        for(Bullet bullet : bulletList){
            rectCross rectCross1 = new rectCross(this.getX() , this.getY() , this.getWidth() , this.getHeight() , bullet.getX() , bullet.getY() , bullet.getWidth() , bullet.getHeight());
            if(rectCross1.cross() == true){
                g.drawImage(explode , this.getX() - 50 , this .getY() - 50 , null);
                score.setScore(score.getScore() + 1);
                bullet.setX(-100);
                bullet.setY(100);
                this.setX(-200);
                this.setY(200);
            }
        }
    }

    @Override
    public Rectangle getRec() {
        return super.getRec();
    }
}

     7、敌方子弹

public class eneBulletObject extends GameObject{
    static Rectangle playerPlane;
    PlayerPlane playerPlane02 = new PlayerPlane();


    public eneBulletObject(Image img, int x, int y, int width, int height, double speedX, double speedY) {
        super(img, x, y, width, height, speedX, speedY);
    }

    public eneBulletObject (){}

    public void setPlayerPlane(Rectangle playerPlane){
        this.playerPlane = playerPlane;
    }

    @Override
    public void paintSelf(Graphics g) {
        y += speedY;
        g.drawImage(img , x , y , null);
        //敌机子弹与玩家机碰撞
        rectCross rectCross = new rectCross(this.getX() , this.getY() , this.getWidth() , this.getHeight() , (int)(playerPlane.getX()) - 38 , (int)(playerPlane.getY()) - 38, (int)(playerPlane.getWidth()) - 19 , (int)(playerPlane.getHeight()) - 19);
        if(rectCross.cross() == true){
            playerPlane02.setLife(playerPlane02.getLife() - 1);
            this.setX(-100);
            this.setY(100);
        }
    }

    @Override
    public Rectangle getRec() {
        return super.getRec();
    }
}

     8、启动线程

public class objectMotion extends JPanel implements config , Runnable {
    Graphics objMove; //设置画笔
    BufferedImage BFI2;//图片双缓冲
    static int count = 0;//对象创建计数
    int x , eneBulletX , bossPlaneX;
    int y , eneBulletY , bossPlaneY;
    static int bossBulletGo;
    Random r = new Random();
    backGroundObj backGroundObj = new backGroundObj(backGround ,0 , -1200 , 5);
    enePlaneObj enePlaneObj = new enePlaneObj();
    eneBulletObject eneBulletObject = new eneBulletObject();
    PlayerPlane playerPlane01 = new PlayerPlane();
    Score newSc = new Score();
    bossPlane bossPlane = new bossPlane();
    BossBullet boss_Bullet = new BossBullet();

    public objectMotion(){}

    public objectMotion(Graphics g){
        this.objMove = g;
    }


    @Override
    public int getX() {
        return x;
    }

    //我方战机坐标
    public void setX(int x) {
        this.x = x;
    }

    @Override
    public int getY() {
        return y;
    }


    public void setY(int y) {
        this.y = y;
    }

    @Override
    public void run() {
        rolling();
    }

    public void rolling(){
        while (true){
            FlyObjectCreate();
            PlayerPlane playerPlane = new PlayerPlane(plane1 , getX() , getY() , 76 , 76);
            PlayerPlane playerPlane2 = new PlayerPlane(plane1 , playerPlane.getX() + 38  , playerPlane.getY() + 38, 76 , 76);
            playerPlaneList.add(playerPlane2);
            BFI2 = new BufferedImage(windowsWidth , windowsHeight , 2);
            backGroundObj.paintSelf(objMove);
            playerPlane.paintSelf(objMove);

            //玩家机列表
            for (int i = 0; i < playerPlaneList.size(); i++) {
                enePlaneObj.setPlayerPlane(playerPlaneList.get(i).getRec());
                eneBulletObject.setPlayerPlane(playerPlaneList.get(i).getRec());
                bossPlane.setPlayerplane(playerPlaneList.get(i).getRec());
                boss_Bullet.setPlayerPlane(playerPlaneList.get(i).getRec());
            }
            //玩家机子弹
            for (int i = 0; i < bulletList.size(); i++) {
                bulletList.get(i).paintSelf(objMove);
            }
            //敌机列表
            for (int i = 0; i < enePlaneList.size(); i++) {
                enePlaneList.get(i).paintSelf(objMove);
                eneBulletX = enePlaneList.get(i).getX();
                eneBulletY = enePlaneList.get(i).getY();
            }
            //敌机子弹列表
            for (int i = 0; i < eneBulletList.size(); i++) {
                eneBulletList.get(i).paintSelf(objMove);
            }
            //boss机列表
            for (int i = 1; i < bossPlaneList.size(); i++) {
                bossPlaneList.get(i).paintSelf(objMove);
                bossPlaneX = bossPlaneList.get(i).getX();
                bossPlaneY = bossPlaneList.get(i).getY();
                bossBulletGo = 1;
            }
            //boss机子弹集合
            for (int i = 0; i < bossBulletList.size(); i++) {
                bossBulletList.get(i).paintSelf(objMove);
            }
            repaint();
            count ++;
            try {
                scorePanel();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                Thread.sleep(35);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void FlyObjectCreate(){
        int rEne = r.nextInt(400);
        //敌机列表
        if (count % 15 == 0){
            enePlaneList.add(new enePlaneObj(enemyPlane1 , rEne , 0 , 64 , 64 , 0 , 3));
        }
        //我方战机子弹列表
        if (count % 9 == 0){
            bulletList.add(new Bullet(bullet001, getX() - 10 , getY() - 38, 20 , 30 , 0 , -5));
        }
        //敌机子弹列表
        if (count % 15 == 0){
            eneBulletList.add(new eneBulletObject(eneBullet , eneBulletX + 28, eneBulletY + 32 , 9 , 21, 0 , 5));
        }
        //boss机
        if (count % 901 == 0){
            bossPlaneList.add(new bossPlane(plane0 , 80 , -50 , 259 , 196 , 0 , 1));
        }
        if(count % 65 == 0){
           if(bossBulletGo == 1){
               bossBulletList.add(new BossBullet(bossBullet , bossPlaneX + 16, bossPlaneY + 95, 20 , 24 , 0 , 5));
               bossBulletList.add(new BossBullet(bossBullet , bossPlaneX + 83, bossPlaneY + 125, 20 , 24 , 0 , 5));
               bossBulletList.add(new BossBullet(bossBullet , bossPlaneX + 150, bossPlaneY + 95, 20 , 24 , 0 , 5));
           }

        }
    }

    public void scorePanel() throws InterruptedException {
        objMove.setColor(Color.RED);
        objMove.setFont(new Font("Strasua" , Font.BOLD , 18));
        objMove.drawString("SCORE" , 12 , 52);
        objMove.drawString(String.valueOf(newSc.score) , 80 , 52);
        objMove.setColor(Color.RED);
        objMove.setFont(new Font("Strasua" , Font.BOLD , 18));
        objMove.drawString("LIFE" , 12 , 76);
        objMove.drawString(String.valueOf(playerPlane01.life) , 76 , 76);
        if(playerPlane01.life <= 0){
            objMove.drawImage(explode , playerPlane01.getX() , playerPlane01.getY() , null);
            playerPlane01.setX(-100);
            playerPlane01.setY(100);
            objMove.drawString("GAME OVER" , 180 , 500);
            try {
                Thread.sleep(900000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

}

三、运行结果

   启动界面

 

   游戏运行界面

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值