【Java小项目】--- 飞机大战(源码+注释)

2年前 (2022) 程序员胖胖胖虎阿
248 0 0

【Java小项目】--- 飞机大战(源码+注释)
【Java小项目】--- 飞机大战(源码+注释)


【Java小项目】--- 飞机大战(源码+注释)


前言:

“前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默
经过小新缜密的思考与亲身体验,忍不住分享一下给大家。有人工智能兴趣的朋友们,推荐大家一起学习 🎉点击直接访问🎉
里面有丰富的人工智能学习资料,真正做到从入门到入土,还不快来一起学习🎏🎏🎏


个人名片:

🐼作者简介:一名大一在校生
🐻‍❄️个人主页:小新爱学习.
🐼个人WeChat:hmmwx53
🕊️系列专栏:零基础学java ----- 重识c语言
🐓每日一句:青山一片云雾心安即归处。


文章目录

    • 构思
      • 主类(ShootGame)
      • 英雄机(Hero)
      • 飞行物(FlyingObject)
      • 子弹(Bullet)
      • 奖励蜜蜂(Bee)类
      • 敌飞机类(AirPlane)
      • 奖励接口
      • 计分接口
    • 源码图片获取,微信私

构思

首先,要把整体的游戏框架和内容构思出来(根据预先构思游戏里存在的组件内容和游戏功能抽象出指定类)。以我的小游戏为例:

  • 1.主界面框架类:
    显示开始界面

  • 2.弹出界面类:
    JDialog 窗体的功能是从一个窗体中弹出另一个窗体,就像是在使用 IE 浏览器时弹出的确定对话框,JDialog 窗体与 JFrame 窗体形式基本相同,设置窗体的特性时调用的方法名称都基本相同,如设置窗体大小、窗体关闭状态等

  • 3.游戏面板类:GamePanel (extends JPanel)
    真正显示飞机大战动态游戏画面,并且还添加了按钮JButton用于控制游戏开始暂停。

  • 4.玩家飞机类:Hero
    移动玩家飞机、画玩家飞机等其他与玩家飞机相关的方法

  • 5.敌机类:AirPlane
    移动敌机、画敌机

  • 6.子弹类
    移动子弹、绘制子弹

  • 7碰撞类:Collision
    检测各种碰撞情况

  • 8.主类:Main
    开启程序

主类(ShootGame)

package cn.tede.shoot;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.TimerTask;

//import static java.util.concurrent.locks.StampedLock.STATE;


public class ShootGame extends JPanel {
    public static final int WIDTH =400;
    public static final int HEIGHT =654;
    private int state;
    public static final int START = 0;
    public static final int RUNNING = 1;
    public static final int PAUSE = 2;
    public static final int GAME_OVER =4;

    public static BufferedImage background;
    public static BufferedImage start;
    public static BufferedImage airplane;
    public static BufferedImage bee;
    public static BufferedImage bullet;
    public static BufferedImage hero0;
    public static BufferedImage hero1;
    public static BufferedImage pause;
    public static BufferedImage gameover;

    private FlyingObject[] flyings = {}; //敌机数组
    private Bullet [] bullets = {}; //子弹数组
    private Hero hero = new Hero();//英雄鸡

    private Timer timer;//定时器
    private int intervel = 1000/100; //时间间隔,十毫秒

    private int score = 0;//得分
//    public ShootGame(){
        flyings  = new FlyingObject[2];
        flyings[0] = new AirPlane();
        flyings[1] = new Bee();
        bullets = new Bullet[1];
        bullets[0] = new Bullet(180,300);
//    }
    static{//静态代码块
        try {
            background= ImageIO.read(ShootGame.class.getResource("background.png"));
            start= ImageIO.read(ShootGame.class.getResource("start.png"));
            airplane = ImageIO.read(ShootGame.class.getResource("airplane.png"));
            bee = ImageIO.read(ShootGame.class.getResource("bee.png"));
            bullet = ImageIO.read(ShootGame.class.getResource("bullet.png"));
            //bullet = ImageIO.read(ShootGame.class.getResource("B1.png"));
            //hero0= ImageIO.read(ShootGame.class.getResource("C.png"));
            hero0= ImageIO.read(ShootGame.class.getResource("hero0.png"));
            hero1 = ImageIO.read(ShootGame.class.getResource("hero1.png"));
            pause= ImageIO.read(ShootGame.class.getResource("pause.png"));
            gameover = ImageIO.read(ShootGame.class.getResource("gameover.png"));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void paint(Graphics g) {
        g.drawImage(background,0,0,null);//画背景图片
        paintHero(g);
        paintBullets(g);
        paintFlyingObject(g);
        paintScore(g);//画分数
       // paintPause(g);
        paintState(g);


    }

    /**
     * 画游戏状态
     *
     */
    public void paintState(Graphics g){
        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;
        }
    }

    /**
     * 画分数
     * @param g
     */
    public void paintScore(Graphics g){
        Font font = new Font(Font.SANS_SERIF, Font.BOLD,4);
        g.setColor(new Color(0xffff0));//设置字体

        g.drawString("SCORE"+score,10,25);
        g.drawString("LIFE"+hero.getLife(),10,45);
    }
    //画英雄鸡
    public void  paintHero(Graphics g){
        g.drawImage(hero.getImage(),hero.getX(),hero.getY(),null);
    }
    //画子弹
    public void paintBullets(Graphics g){
        for(int i = 0;i < bullets.length; i++){
            Bullet b = bullets[i];
            g.drawImage(b.getImage(),b.getX(),b.getY(),null);
        }
    }
    //画飞行物
    public void paintFlyingObject(Graphics g){
        for(int i = 0; i< flyings.length;i++){
            FlyingObject f = flyings[i];
            g.drawImage(f.getImage(),f.getX(),f.getY(),null);
        }
    }
//    //画暂停
//    public void paintPause(Graphics g){
//        g.drawImage(pause,0,0,null);
//    }

    //随机生成飞行物
    public static FlyingObject nextOne(){
        //返回 飞行物对象
        Random random = new Random();
        int type = random.nextInt(20);//生成随机数0-19
        if(type == 0){
            return new Bee();
        }else{
            return new AirPlane();
        }
    }
    int flyEnterIndex = 0;
    //飞行物入场
    public void enterAction () {

        flyEnterIndex++;
        if (flyEnterIndex % 40 == 0) {//每调用40次该方法
            FlyingObject obj = nextOne();//随机生成一个飞行物
            flyings = Arrays.copyOf(flyings, flyings.length + 1);//扩容
            flyings[flyings.length - 1] = obj;//放在最后一位
        }
    }


    /*
    实现飞行物移动
     */
    public void stepAction() {
        for (int i = 0; i < flyings.length; i++){
            FlyingObject f =  flyings[i];
            f.step();
        }
        for(int i = 0;i<bullets.length;i++){
            /**
             * 子弹走
             *
             */
            Bullet b = bullets[i];
            b.step();
//            bullets[i].step();
        }
        hero.step();
    }
    int shootIndex = 0;
    //射击
    public void shootAction() {
        //调用30次该方法发射一次子弹,
        //英雄级打出子弹
        //扩容
        //追加数组
        shootIndex++;
        if (shootIndex % 30 == 0) {//每调用30次该方法
            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 bangAction() {
        for (int i = 0; i< bullets.length; i++){
            Bullet b = bullets[i];
            bang(b);
        }
    }

    private void bang(Bullet bullet) {
        int index = -1;
        for (int i = 0; i <flyings.length;i++){
            FlyingObject obj = flyings[i];
            if(obj.shootBy(bullet)){
                index = i;
                break;
            }
        }
        if(index != -1) {
            //击中
            FlyingObject one = flyings[index];//记录被击中的飞行物
            FlyingObject temp = flyings[index];//被击中的飞行物与最后一个飞行物交换
            flyings[index] = flyings[flyings.length - 1];
            flyings[flyings.length - 1] = temp;
            //删除最后一个飞行物(被击中的飞行物)
            flyings = Arrays.copyOf(flyings, flyings.length - 1);

            //检测one的类型,若果是敌人就加分


            if (one instanceof Enemy) {
                Enemy e = (Enemy) one;
                score += e.getScore();
            }
            if (one instanceof Award) {
                Award a = (Award) one;
                int type = a.getType();
                switch (type) {
                    case Award.DOUBLE_FIRE:
                        hero.addDoubleFire();
                        break;
                    case Award.LIFE:
                        hero.addLife();
                        break;
                }
            }
        }
        //如果one的类型就奖励,则设置奖励
    }

    /**
     * 删除越界的飞行物和子弹,小蜜蜂,飞机
     */

    public void outOfBoundsAction() {
        int index = 0;
        FlyingObject[] flyingLives = new FlyingObject[flyings.length];//没有碰撞的飞行物
        for (int i = 0; i < flyings.length; i++) {
            FlyingObject f = flyings[i];
            if (!f.outOfBounds()) {
                flyingLives[index++] = f;//没有越界的存储到或者的数组
            }
        }
        flyings = Arrays.copyOf(flyingLives, 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;
            }
        }
        bullets = Arrays.copyOf(bulletLives,index);
    }

    /**
     * 检测游戏是否结束
     */
    public boolean isGameOver() {
        for (int i = 0; i < flyings.length; i++) {//遍历所有飞行物
            int index = -1;//没有发生碰撞
            FlyingObject obj = flyings[i];
            if(hero.hit(obj)){//检查英雄鸡与飞行物是否碰撞
                hero.subtractLife();//减命
                hero.setDoubleFire(0);//双倍火力清零
                index = i;//将碰撞飞行物的下标给到index
            }
            if(index!=-1){
                FlyingObject t = flyings[index];
                flyings[index] =  flyings[flyings.length - 1];
                flyings[flyings.length - 1] = t;//发生碰撞的元素和最后一个元素交换
                flyings = Arrays.copyOf(flyings,flyings.length-1);
            }
        }
        return hero.getLife() <= 0;
    }

    /**
     * 检查游戏是否结束
     */
    public void checkGameOverAction() {
        if(isGameOver()){//如果已经结束
            state = GAME_OVER;//改变状态为结束

        }
    }
    public void action(){
        //鼠标监听事件
        MouseAdapter i = new MouseAdapter(){
            public void mouseMoved(MouseEvent e) {//鼠标移动
                if(state == RUNNING) {
                    int x = e.getX();
                    int y = e.getY();
                    hero.moveTo(x, y);
                }
            }
            public void mouseEntered(MouseEvent e){//鼠标进入
                if(state == PAUSE){
                    state = RUNNING;
                }
            }

            @Override
            public void mouseExited(MouseEvent e) {//鼠标退出
                if(state!=GAME_OVER&&state!=START){
                    state = PAUSE;//游戏装态不是GAMEOVER ,鼠标离开窗口 ,设置暂停
                }
            }

            @Override
            public void mouseClicked(MouseEvent mouseEvent) {
                //鼠标点击事件
                switch(state){
                    case START:
                        state = RUNNING;
                        break;
                    case GAME_OVER://当状态是结束的时候,点击鼠标,会重新初始化各个对象,状态变为开始
                        flyings = new FlyingObject[0];
                        bullets = new Bullet[0];
                        hero = new Hero();
                        score = 0;
                        state  = START;


                }
            }
        };
        this.addMouseListener(i);//处理鼠标点击事件
        this.addMouseMotionListener(i);//处理鼠标滑动操作
        //启动执行代码
        java.util.Timer timer = new java.util.Timer();
        timer.schedule(new TimerTask() {
            public void run() {
                if(state == RUNNING){
                    enterAction();//飞行物入场
                    stepAction();//飞行物走一步
                    shootAction();
                    bangAction();
                    isGameOver();
                    checkGameOverAction();//检查游戏结束
                    outOfBoundsAction();
                }
                repaint();//重绘,调用paint方法

            }
        }, intervel ,intervel);//10毫秒以后,每隔10毫秒执行一次
    }
    public static void main(String[] args){
        JFrame frame = new JFrame("飞机大战");//画框
        ShootGame game = new ShootGame();
        frame.add(game);
        frame.setSize(WIDTH, HEIGHT);//窗口的大小
        frame.setAlwaysOnTop(true);//窗口在最上边
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//点x关闭
        frame.setLocationRelativeTo(null);//设置窗体的初始记录
        frame.setVisible(true);//尽快调用paint方法
        game.action();




    }
}

英雄机(Hero)

package cn.tede.shoot;

import java.awt.image.BufferedImage;

//英雄鸡
public class Hero extends FlyingObject {

    BufferedImage[] images = {};
    int index = 0;

    private int doubleFire;//双倍火力的子弹数量
    private int life;//命的数量

    public Hero() {
        life = 3;
        doubleFire = 0;
        this.image = ShootGame.hero0;
        images = new BufferedImage[]{ShootGame.hero0, ShootGame.hero1};
        width = image.getWidth();
        height = image.getHeight();
        x = 150;
        y = 400;
    }

    @Override
    public void step() {
        if (images.length > 0) {
            image = images[index++ / 10%images.length];
        }
    }

    @Override
    public boolean outOfBounds() {
        return false;
    }

    @Override//重写
    public boolean hitColumn() {
        return false;
    }

    //发射子弹
    public Bullet[] shoot() {
        int xStep = width / 4;
        int yStep = 20;
        if (doubleFire > 0) {//双倍火力
            Bullet[] bullets = new Bullet[5];//2
            bullets[0] = new Bullet(x + xStep, y - yStep);
            bullets[1] = new Bullet(x + 3 * xStep, y - yStep);
            bullets[2] = new Bullet(x + 2 * xStep, y - yStep);
            bullets[3] = new Bullet(x + 0 * xStep, y - yStep);
            bullets[4] = new Bullet(x + 4 * xStep, y - yStep);

            doubleFire -= 2;
            return bullets;
        } else {
            Bullet[] bullets = new Bullet[1];
            bullets[0] = new Bullet(x + 2 * xStep, y - yStep);
            return bullets;
        }
    }

    /**
     *
     * @param x:鼠标x坐标位置
     * @param y;鼠标y坐标位置
     */
    public void moveTo(int x, int y) {
        this.x = x- width/2;//hero.x+width/2;
        this.y = y - height/2;

    }
    public void addDoubleFire(){
        doubleFire += 40;
    }
    public void addLife(){
        life++;
    }
    //获取英雄鸡命数
     public int getLife(){
        return life;
     }

//    public boolean outOfBounds(){
//        return false;
//    }
    //减命
    public void subtractLife(){
        life--;
    }
    //重新设计双倍火力值
    public void setDoubleFire(int doubleFire){
        this.doubleFire = doubleFire;
    }
    //碰撞的算法
    public boolean hit(FlyingObject other){
        int x1 = other.x - this.width/2 ;
        int x2 = other.x + this.width/2 + this.width;
        int y1 = other.y - this.height/2 ;
        int y2 = other.y + other.height + other.height/2;
        return this.x + this.width/2>x1
                &&this.x+this.width/2<x2
                &&this.y+this.height/2>y1
                &&this.y+this.height/2<y2;

    }
}

飞行物(FlyingObject)

package cn.tede.shoot;
//父类
import java.awt.image.BufferedImage;

public abstract class FlyingObject {
    protected int x;//x坐标
    protected int y;//y坐标
    protected int width;//宽
    protected int height;//高
    protected BufferedImage image;//图片

    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 BufferedImage getImage() {
        return image;
    }

    public void setImage(BufferedImage image) {
        this.image = image;
    }
    public abstract void step();
    public boolean shootBy(Bullet bullet){
        int x= bullet.x;
        int y = bullet.y;
        return this.x<x&&x<this.x+width&&this.y<y && y<this.y+height;
    }

    /**
     * 检查是否出界
     * @return
     */
    public abstract  boolean outOfBounds();//

    /**
     * 检测是否碰墙
     */
    public abstract boolean hitColumn();
}

子弹(Bullet)

package cn.tede.shoot;

/**
 * 子弹
 */
public class Bullet extends FlyingObject{
    private int speed = 3;//移动速度
    public Bullet(int x,int y){
        this.x = x;
        this.y = y;
        this.image = ShootGame.bullet;



    }

    @Override
    public void step() {
        y -= speed;


    }

    @Override
    public boolean outOfBounds() {
        return y<-height;
    }

    @Override
    public boolean hitColumn() {
        return y<-height;
    }
}

奖励蜜蜂(Bee)类

package cn.tede.shoot;

import java.util.Random;

//蜜蜂
public class Bee extends FlyingObject implements Award{

    private int xSpeed = 1;//x坐标的移动速度
    private int ySpeed = 2;//y坐标的移动速度
    private  int awardType;//奖励类型
    public Bee(){
        this.image = ShootGame.bee;
        width = image.getWidth();
        height = image.getHeight();
        y = - height;
        //y = 200;
        x= (int)Math.random()*(ShootGame.WIDTH - width);
        Random r =new Random();
        //int x = r.nextInt(ShootGame.WIDTH - width);
        //x = 100;
        awardType = r.nextInt(2);

    }

    @Override
    public int getType() {//奖励类型
        return awardType;
    }

    @Override
    public void step() {
        x+= xSpeed;
        y+= ySpeed;
        if(x>ShootGame.WIDTH - width){
            xSpeed = -1;
        }
        if(x<0){
            xSpeed = 1;
        }
    }

    @Override
    public boolean outOfBounds() {
        return y>ShootGame.HEIGHT;
    }

    @Override
    public boolean hitColumn() {
        return false;
    }
}

敌飞机类(AirPlane)

package cn.tede.shoot;

public class AirPlane extends FlyingObject implements Enemy{
    private int speed = 2;//敌人飞机移动速度2
    public AirPlane(){
        this.image = ShootGame.airplane;
        width = image.getWidth();
        height = image.getHeight();
        y= -height;
        x = (int)(Math.random()*(ShootGame.WIDTH - width));
//        x = 300;
//        y = 190;
    }

    @Override
    public int getScore() {
        return 5;
    }

    @Override
    public void step() {
        y+=speed;
    }

    @Override
    public boolean outOfBounds() {
        return y>ShootGame.HEIGHT;
    }

    @Override
    public boolean hitColumn() {
        return y>ShootGame.HEIGHT;
    }
}

奖励接口

package cn.tede.shoot;

/**
 * 奖励
 */
public interface Award {
    int DOUBLE_FIRE = 0;//双倍火力
    int LIFE = 1;//一条命

    /**
     * 获得奖励的类型为上面的0或者1
     * @return
     */
    int getType();
}

计分接口

ackage cn.tede.shoot;

/**
 * 敌人
 */
public interface Enemy {
    int getScore();
}

【Java小项目】--- 飞机大战(源码+注释)
【Java小项目】--- 飞机大战(源码+注释)

源码图片获取,微信私


版权声明:程序员胖胖胖虎阿 发表于 2022年9月22日 下午4:48。
转载请注明:【Java小项目】--- 飞机大战(源码+注释) | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...