java实现飞机大战,(源码在文章末尾噢,超级详细的注释)

发布于:2023-01-18 ⋅ 阅读:(529) ⋅ 点赞:(0)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

我参考过B站尚学堂老师的飞机大战的课程,根据老师的上课,总结一下


提示:以下是本篇文章正文内容,下面案例可供参考

一、基本介绍

要实现飞机大战,需要哪些功能要实现呢?
1.窗口的绘制
2.图片和字体的绘制
3.背景图片的循环移动
4.鼠标控制飞机的移动位置
5.子弹的批量生成
6.敌机在随机位置的批量生成
7.子弹和飞机的碰撞检测
8.爆炸效果动画的实现
9.计分面板的实现
10.游戏的暂停功能
11.游戏的通关设置
12.血条绘制
13.双缓存解决画面闪动
14.集合的使用和优化

二、效果图

请添加图片描述
请添加图片描述
在这里插入图片描述
在这里插入图片描述

三、源码分析

1.首先绘制游戏的主类gamewin

代码如下(示例):

package com.game;

import com.game.obj.*;
import com.game.utils.gameutils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class gamewin extends JFrame {
    //游戏状态 0未开始 1进行中 2暂停 3游戏通过 4游戏失败
    public static int state=0;//游戏的默认状态
    //计分数
    public static  int score=0;
    Image offSreenimage=null;
    int width=600;
    int height=600;
    //游戏的重绘次数
    int count=1;
    //敌机出现的数量
    int enemyCount=0;

    //背景图图像的移动
    Bgobj bgobj=new Bgobj(gameutils.bgimg,0,-400,2);
    //我方飞机的对象
    public Planeobj planeobj =new Planeobj(gameutils.planeimg,290,550,20,30,0,this);
    //boss对象
    public Bossobj bossobj =null;
    public void launch(){
        //设置窗口是否可见
        this.setVisible(true);
        //设置窗口大小
        this.setSize(width,height);
        //设置窗口位置
        this.setLocationRelativeTo(null);
        //设置窗口标题
        this.setTitle("飞机大战");

        gameutils.gameobjList.add(bgobj);
        gameutils.gameobjList.add(planeobj);

        //鼠标点击
        this.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {

                //在未开始并且点击鼠标左键,
                if(e.getButton()==1&&state==0){
                    state=1;
                    repaint();
                }
            }
        });

        //游戏的暂停功能
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                //按下空格键,空格键的代码为32
                if(e.getKeyCode() == 32){
                    switch (state){
                        case 1:
                            state=2;
                            break;
                        case 2:
                            state=1;
                            break;
                        default:
                    }
                }
            }
        });
        while(true){
            if(state==1){
                create();
                repaint();
            }

            try {
                Thread.sleep(25);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Override
    public void paint(Graphics g) {
        if(offSreenimage==null){
            offSreenimage=createImage(width,height);
        }
        //获取offScrenimage的画笔对象
        Graphics gimage=offSreenimage.getGraphics();
        //填充一个宽六百,高六百的区域
        gimage.fillRect(0,0,width,height);
        //游戏未开始
        if(state==0){
            gimage.drawImage(gameutils.bgimg,0,0,null);
            gimage.drawImage(gameutils.bossimg,200,100,null);
            gimage.drawImage(gameutils.explodeimg,270,370,null);
            gameutils.drawWord(gimage,"点击开始游戏",Color.yellow,40,180,300);
//            gimage.setColor(Color.yellow);
//            gimage.setFont(new Font("仿宋",Font.BOLD,40));
//            gimage.drawString("点击开始游戏",180,300);

        }
        //游戏开始
        if(state==1){
            gameutils.gameobjList.addAll(gameutils.explodeobjList);

            for(int i=0;i<gameutils.gameobjList.size();i++){
                gameutils.gameobjList.get(i).paintself(gimage);
            }
            gameutils.gameobjList.removeAll(gameutils.removeobjList);
        }
        //游戏失败
        if(state==3) {
            gimage.drawImage(gameutils.explodeimg, planeobj.getX() - 35, planeobj.getY() - 50, null);
            gameutils.drawWord(gimage,"GAME OVER",Color.red,40,180,300);
//            gimage.setColor(Color.red);
//            gimage.setFont(new Font("仿宋", Font.BOLD, 40));
//            gimage.drawString("GAME OVER", 180, 300);
        }
        //游戏通关
        if(state==4) {
            gimage.drawImage(gameutils.explodeimg, bossobj.getX() + 35, bossobj.getY() + 50, null);
            gameutils.drawWord(gimage, " Game Win", Color.red, 40, 180, 300);
        }
        gameutils.drawWord(gimage,score+"分",Color.green,40,30,100);
        //把新图片一次性绘制到主窗口中
        g.drawImage(offSreenimage,0,0,null);
        count++;
    }
    //创建方法用来批量生成子弹和敌机
     void create(){
        //我方子弹  除以10是为了控制子弹的速率
        if(count%10==0){
            gameutils.shellobjList.add(new Shellobj(gameutils.shellimg,planeobj.getX()+4,planeobj.getY()-16,14,29,5,this));
            gameutils.gameobjList.add(gameutils.shellobjList.get(gameutils.shellobjList.size()-1));
        }
        //敌方战机
        if(count%15==0){
            gameutils.enemyobjList.add(new Enemyobj(gameutils.enemyimg,(int)(Math.random()*12)*50,0,50,50,5,this));
            gameutils.gameobjList.add(gameutils.enemyobjList.get(gameutils.enemyobjList.size()-1));
            enemyCount++;
        }
        //敌方boss子弹
         //直到boss出现的时候才会生成子弹
         if(count%15==0 && bossobj !=null){
             gameutils.bulletobjList.add(new Bulletobj(gameutils.bulletimg,bossobj.getX()+75,bossobj.getY()+80,15,25,5,this));
             gameutils.gameobjList.add(gameutils.bulletobjList.get(gameutils.bulletobjList.size()-1));
         }
         if( enemyCount>30 && bossobj == null ){
             bossobj=new Bossobj(gameutils.bossimg,250,20,155,100,5,this);
             gameutils.gameobjList.add(bossobj);
         }
    }

    public static void main(String[] args) {
        gamewin Gamewin=new gamewin();
        Gamewin.launch();
    }

}

2.绘制工具类gameutils

一些图片,比如子弹图片、敌方boss背景图片之类的需要绘制在gameutils中:

package com.game.utils;

import com.game.obj.*;

import java.awt.*;
import java.util.ArrayList;
import java.util.List;

public class gameutils {
    //背景图片
    public static Image bgimg =Toolkit.getDefaultToolkit().getImage("image/背景.jpeg");
    //boss图片
    public static Image bossimg =Toolkit.getDefaultToolkit().getImage("image/boss.png");
    //爆炸图片
    public static Image explodeimg =Toolkit.getDefaultToolkit().getImage("image/explode/e11.gif");
    //我方飞机图片
    public static Image planeimg =Toolkit.getDefaultToolkit().getImage("image/plane.png");
    //我方子弹图片
    public static Image shellimg =Toolkit.getDefaultToolkit().getImage("image/shell.png");
    //敌方boss子弹图片
    public static Image bulletimg =Toolkit.getDefaultToolkit().getImage("image/boss子弹.png");
    //敌方飞机的图片
    public static Image enemyimg =Toolkit.getDefaultToolkit().getImage("image/enemy.png");
    //要删除元素的集合
    public static List<Gameobj> removeobjList =new ArrayList<>();

    //所有物体游戏的集合
    public static List<Gameobj> gameobjList =new ArrayList<>();
    //我方子弹的集合
    public static List<Shellobj> shellobjList =new ArrayList<>();
    //敌方飞机的集合
    public static List<Enemyobj> enemyobjList =new ArrayList<>();
    //敌方boss方子弹的集合
    public static List<Bulletobj> bulletobjList =new ArrayList<>();
    //爆炸图片的集合
    public static List<Explodeobj> explodeobjList =new ArrayList<>();
    //绘制字符串的工具类
    public static  void drawWord(Graphics gImage,String str,Color color,int size,int x,int y){
        gImage.setColor(color);
        gImage.setFont(new Font("仿宋",Font.BOLD,size));
        gImage.drawString(str,x,y);
    }

}

3.新建obj文件夹,绘制游戏物体的父类Gameobj

package com.game.obj;

import com.game.gamewin;

import java.awt.*;
//游戏类父类的编写
public class Gameobj {
    Image img;
    int x;
    int y;
    int width;
    int height;
    double speed;//移动速度
    gamewin frame;//窗口的引用

    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 Gameobj(int x, int y) {
        this.x = x;
        this.y = y;
    }

    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 getSpeed() {
        return speed;
    }

    public void setSpeed(double speed) {
        this.speed = speed;
    }

    public gamewin getFrame() {
        return frame;
    }

    public void setFrame(gamewin frame) {
        this.frame = frame;
    }
    //有参构造和无参构造函数
    public Gameobj() {
    }

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

    public Gameobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
        this.img = img;
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.speed = speed;
        this.frame = frame;
    }
    //绘制自身
    public void paintself(Graphics gImage){
        gImage.drawImage(img,x,y,null);
    }
    //绘制矩形的方法用来碰撞检测
    public Rectangle getrect(){
        return new Rectangle(x,y,width,height);
    }
}

绘制Bgobj,实现背景的移动和循环出现

package com.game.obj;

import com.game.gamewin;

import java.awt.*;
//游戏类父类的编写
public class Gameobj {
    Image img;
    int x;
    int y;
    int width;
    int height;
    double speed;//移动速度
    gamewin frame;//窗口的引用

    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 Gameobj(int x, int y) {
        this.x = x;
        this.y = y;
    }

    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 getSpeed() {
        return speed;
    }

    public void setSpeed(double speed) {
        this.speed = speed;
    }

    public gamewin getFrame() {
        return frame;
    }

    public void setFrame(gamewin frame) {
        this.frame = frame;
    }
    //有参构造和无参构造函数
    public Gameobj() {
    }

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

    public Gameobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
        this.img = img;
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.speed = speed;
        this.frame = frame;
    }
    //绘制自身
    public void paintself(Graphics gImage){
        gImage.drawImage(img,x,y,null);
    }
    //绘制矩形的方法用来碰撞检测
    public Rectangle getrect(){
        return new Rectangle(x,y,width,height);
    }
}

绘制我方战斗机类Planeobj

package com.game.obj;

import com.game.gamewin;

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class Planeobj extends Gameobj {
    @Override
    public Image getImg() {
        return super.getImg();
    }

    public Planeobj() {
        super();
    }

    public Planeobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
        super(img, x, y, width, height, speed, frame);
        //飞机随着鼠标的移动而移动
        this.frame.addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                 Planeobj.super.x=e.getX()-11;
                 Planeobj.super.y=e.getY()-16;
            }
        });
    }

    @Override
    public void paintself(Graphics gImage) {
        super.paintself(gImage);
        //y-=speed;
        if(this.frame.bossobj !=null && this.getrect().intersects(this.frame.bossobj.getrect())){
            gamewin.state=3;
        }
    }

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

绘制战斗机子弹类Shellobj

package com.game.obj;

import com.game.gamewin;
import com.game.utils.gameutils;

import java.awt.*;

public class Shellobj extends Gameobj{
    @Override
    public Image getImg() {
        return super.getImg();
    }

    public Shellobj() {
        super();
    }

    public Shellobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
        super(img, x, y, width, height, speed, frame);
    }

    @Override
    public void paintself(Graphics gImage) {
        super.paintself(gImage);
        y-=speed;
//        我方子弹的越界消失,条件y<0时,,改变后的坐标为-100,100
        if(y<0){
            this.x=-100;
            this.y=100;
            gameutils.removeobjList.add(this);

        }


    }

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

绘制敌方战斗机类Enemyobj

package com.game.obj;

import com.game.gamewin;
import com.game.utils.gameutils;

import java.awt.*;

public class Enemyobj extends Gameobj{

    public Enemyobj() {
        super();
    }

    public Enemyobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
        super(img, x, y, width, height, speed, frame);
    }

    @Override
    public void paintself(Graphics gImage) {
        super.paintself(gImage);
        y+=speed;
        //敌我飞机的碰撞检测
        if(this.getrect().intersects(this.frame.planeobj.getrect())){
            gamewin.state=3;
        }
        //敌方飞机超出窗口,判断条件y>600,调整坐标为-200,200
        if(y>600){
            this.x=-200;
            this.y=200;
            gameutils.removeobjList.add(this);
        }
        //子弹和敌方飞机碰撞的检测,
        for (Shellobj shellobj: gameutils.shellobjList)
            {if(this.getrect().intersects(shellobj.getrect())){
            //子弹击中敌方飞机爆炸图
            Explodeobj explodeobj=new Explodeobj(x,y);
            gameutils.explodeobjList.add(explodeobj);
            gameutils.removeobjList.add(explodeobj);
//            shellobj.setX(-100);
//            shellobj.setY(100);
            //改变当前敌机的坐标
            this.x=-200;
            this.y=200;
            gameutils.removeobjList.add(shellobj);
            gameutils.removeobjList.add(this);
            //加分数
            gamewin.score++;
        }

        }
    }

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

绘制敌方Boss类Bossobj

package com.game.obj;

import com.game.gamewin;
import com.game.utils.gameutils;

import java.awt.*;

public class Bossobj extends Gameobj{

    //定义敌方boss的生命值
    int life=30;
    public Bossobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
        super(img, x, y, width, height, speed, frame);
    }

    @Override
    public void paintself(Graphics gImage) {
        super.paintself(gImage);
        //控制敌方boss在整个窗口中
        if(x>550 || x<0){
            speed=-speed;
        }
        x+=speed;
        for(Shellobj shellobj: gameutils.shellobjList){
            //检测子弹和敌方boss碰撞
            if(this.getrect().intersects(shellobj.getrect())){
                shellobj.setX(-100);
                shellobj.setY(100);
                gameutils.removeobjList.add(shellobj);

                life--;

            }
            if(life<=0){
                gamewin.state=4;//表明游戏通关
            }
            //血条的白色背景
            gImage.setColor(Color.WHITE);
            gImage.fillRect(20,40,100,30);
            //血条的绘制
            gImage.setColor(Color.red);
            gImage.fillRect(20,40,life*100/10,30);
            //一个整数除以另一个整数,如果结果为小于一,它会算为0
//            gImage.fillRect(20,40,life/10 *100,50);

        }
    }

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

绘制敌方boss子弹类Bulletobj

package com.game.obj;

import com.game.gamewin;
import com.game.utils.gameutils;

import java.awt.*;

public class Bulletobj extends Gameobj{
    public Bulletobj(Image img, int x, int y, int width, int height, double speed, gamewin frame) {
        super(img, x, y, width, height, speed, frame);
    }

    @Override
    public void paintself(Graphics gImage) {
        super.paintself(gImage);
        y+=speed;
        //敌方boss子弹超出窗口,判断为y>600,调整坐标为-300,300
        if(y>600){
            this.x=-300;
            this.y=300;
            gameutils.removeobjList.add(this);
        }
        //敌方boss子弹和我方飞机的碰撞检测
        if(this.getrect().intersects(this.frame.planeobj.getrect())){
            gamewin.state=3;
        }

    }

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

绘制爆炸类Explodeobj

package com.game.obj;

import java.awt.*;

public class Explodeobj extends Gameobj{

    static Image[] pic=new Image[16];
    //爆炸图只显示一次
    int explodeCount=0;
    static {
        for (int i=0;i<pic.length;i++){
            pic[i]=Toolkit.getDefaultToolkit().getImage("image/explode/e"+(i+1)+".gif");
        }
    }
    public Explodeobj(int x, int y) {
        super(x, y);
    }

    @Override
    public void paintself(Graphics gImage) {

        if(explodeCount<16){
            //绘制数组中的图片
            img=pic[explodeCount];
            super.paintself(gImage);
            explodeCount++;
        }
    }
}

总结

希望以上内容能够对大家有所帮助,我也是根据B站课程一个个慢慢敲上去的,在过程中可能会有有多细节需要注意,无法达到理想效果,会大大降低大家的自信心,希望大家有任何问题,都可以咨询我噢,虽然我很菜,但我一定尽我所能。加油(⊙o⊙)噢噢!!!
好嘞,资源在这噢

链接: java飞机大战源码
提取码:1234


网站公告

今日签到

点亮在社区的每一天
去签到