Java经典飞机大战游戏

版权声明:文章版权归作者所有,未经允许,请勿转载 https://blog.csdn.net/tongshuyang/article/details/83214814

《飞机大战》这款小游戏相信许多朋友早就已经玩过,但是作为小白,学习过程中就是要拿各种经典项目来练手,飞机大战就是老师拿来让我们练手的一个小项目。老师给我们提供了素材包,让我们自由发挥,刚开始真的是没什么头绪,不过这几天的确学习到一些东西,随着慢慢尝试,终于背景动了起来,飞机动了起来,子弹动了起来,可以消灭敌机了,到这也算实现了最底层的功能,这里把代码和我理解的注释写下来,算是对学习过程的记录,也希望可以帮到其他朋友。

一、建立模板类,创建敌机和子弹的模板

敌机模板类Dj.java代码:

package model;

import java.awt.Graphics;
import java.awt.Image;

import javax.swing.ImageIcon;

public class Dj {
    int x,y;
    String icon;
    
    public Dj(String icon) { //参数为敌机图片路径
        this.icon=icon;
        x=(int)(Math.random()*360)+10; //随机生成x坐标
        y=-30;
     }
    
    //画敌机
    public void drawPlane(Graphics g) {
        Image plane=new ImageIcon(icon).getImage();
        g.drawImage(plane, x-15, y-15, null);

    }

    //x,y的get和set方法
    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;
    }

}

子弹模板类Zd.java代码:

package model;

import java.awt.Graphics;
import java.awt.Image;

import javax.swing.ImageIcon;

public class Zd {
    int x, y;

    //构造方法
    public Zd(int a, int b) { //参数为英雄机坐标
        
        this.x=a;
        this.y=b;
        
    }
    
    //画子弹
    public void drawZd(Graphics g) {
        Image zd=new ImageIcon("src/images/bullet_7.png").getImage();
        g.drawImage(zd, x-19, y-80, null);

    }

    //x,y的get和set方法
    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;
    }

}

二、创建碰撞判断类Crash

碰撞判断类Crash.java代码:

package model;

public class Crash {

    // 判断子弹和敌机碰撞
    public boolean Boom(Zd z, Dj d) {
        int zx, zy, dx, dy;
        boolean crash = false;

        //子弹坐标
        zx = z.getX();
        zy = z.getY();
        
        //敌机坐标
        dx = d.getX();
        dy = d.getY();

        if (dx < zx && zy - dy < 30 && dx + 30 > zx) {
            crash = true; //如果相撞返回真值

        }
        return crash;

    }

    //飞机相撞
    public boolean Boom2(Dj d, int x, int y) {
        int dx, dy;
        boolean crash = false;
        
        //敌机坐标
        dx = d.getX();
        dy = d.getY();
        
        //英雄机坐标
        x = x - 50;
        y = y - 80;

        //相撞条件
        if (dx > x+20 && y - dy < 20 && dx < x + 60) {
            crash = true; //如果相撞返回真值

        }
        return crash;

    }

}

三、创建画布类GamePanel

在画布类中创建敌机和子弹模板对象,并在画布上画出来,在新线程循环中改变坐标重画使其移动,获取鼠标坐标画出英雄机,循环遍历子弹和敌机集合,调用Crash类中的方法判断是否相撞
画布类GamePanel.java代码:

package panel;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

import model.Crash;
import model.Dj;
import model.Zd;

public class GamePanel extends JPanel implements MouseMotionListener, MouseListener {
    /**
     * 
     */
    private static final long serialVersionUID = 1682690307762671162L;
    int bx, by, x, y, dx, dy, score = 0,count=0,state; //背景坐标bx,by,英雄机坐标x,y,敌机坐标dx,dy,分数score,计数器count,运行状态state
    Image bg; //背景图
    boolean db = false; //敌机爆炸图片绘图开关
    List<Zd> zd = new ArrayList<Zd>(); //存储子弹对象
    List<Dj> dj = new ArrayList<Dj>(); //存储敌机对象
    
    //运行状态常量
    public static final int START=1;
    public static final int RUNNING=2;
    public static final int PAUSE=3;
    public static final int OVER=4;

    //构造方法
    public GamePanel() {
        state=START;
        bx = 0;
        by = -5350;
        bg = new ImageIcon("src/images/background_1.png").getImage();

    }

    //重写paint方法
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        if(state==RUNNING){
            String sc = "分数:" + String.valueOf(score);
            g.drawImage(bg, bx, by, null); //画出背景
            g.drawRoundRect(0, 0, 120, 30, 5, 5); //分数框
            g.setFont(new Font("TimesRoman", Font.BOLD, 24));
            g.setColor(Color.RED);
            g.drawString(sc, 2, 20); //画出分数

            Image hero = new ImageIcon("src/images/plane_2.png").getImage(); 
            g.drawImage(hero, x - 50, y - 80, null);  //画出英雄机

            if (db) { //在敌机爆炸时画出爆炸图片
                Image boom = new ImageIcon("src/images/boom1.png").getImage();
                g.drawImage(boom, dx, dy, null);
                db = false;
            }

            for (int i = 0; i < zd.size(); i++) {
                zd.get(i).drawZd(g);  //画出所有子弹

            }

            for (int j = 0; j < dj.size(); j++) {
                dj.get(j).drawPlane(g); //画出所有敌机

            }
        }else if(state==START){ //开始界面
            Image start=new ImageIcon("src/images/start.png").getImage();
            g.drawImage(start, 0, 0, 400, 650, null);
        }else if(state==OVER){ //结束界面
            Image over=new ImageIcon("src/images/over.png").getImage();
            g.drawImage(over, 0, 0, 400, 650, null);
        }else if(state==PAUSE){ //暂停界面
            Image pause=new ImageIcon("src/images/pause.png").getImage();
            g.drawImage(pause, 0, 0, 400, 650, null);
        }
        

    }

    // 移动类
    public void Move() {
        new Thread() {
            @Override
            public void run() {
                super.run();
                
                while (true) {
                    if(state==RUNNING){
                        
                        // 背景移动
                        count++;
                        by += 2;
                        if (by > 0) {
                            by = -5350;
                            bg = new ImageIcon("src/images/background_2.png").getImage();
                        }

                        // 创建子弹
                        if (count % 3 == 0) {
                            zd.add(new Zd(x, y));
                        } 
                        for (int a = 0; a < zd.size(); a++) {
                            zd.get(a).setY(zd.get(a).getY() - 30); //改变子弹坐标,使子弹移动
                            if (zd.get(a).getY() < 0) { //判断子弹越界
                                zd.remove(a);

                            }
                        }

                        // 创建敌机
                        if (count % 21 == 0) {
                            dj.add(new Dj("src/images/e4.png"));
                        }else if (count % 31 == 0) {
                            dj.add(new Dj("src/images/e5.png"));
                        }else if (count % 41 == 0) {
                            dj.add(new Dj("src/images/e6.png"));
                        }
                        for (int b = 0; b < dj.size(); b++) {
                            dj.get(b).setY(dj.get(b).getY() + 3); //改变敌机坐标,使敌机移动
                            if (dj.get(b).getY() > 650) { //判断敌机越界
                                state=OVER; //游戏结束

                            }

                        }

                        // 子弹和敌机碰撞
                        Crash crash = new Crash();
                        for (int j = 0; j < zd.size(); j++) {
                            Zd z = zd.get(j);
                            for (int i = 0; i < dj.size(); i++) {
                                Dj d = dj.get(i);
                                if (crash.Boom(z, d)) { //调用Crash对象的Boom方法判断是否相撞
                                    score += 2; //分数加2
                                    dx = dj.get(i).getX(); //敌机坐标
                                    dy = dj.get(i).getY();
                                    db = true; //敌机爆炸
                                    dj.remove(i); //从集合中删除敌机
                                    zd.remove(j); //从集合中删除子弹
                                    break;
                                }
                            }
                        }
                        
                        //判断飞机相撞
                        for (int i = 0; i < dj.size(); i++) {
                            Dj d = dj.get(i);
                            if (crash.Boom2(d, x, y)) {
                                dx = dj.get(i).getX();
                                dy = dj.get(i).getY();
                                db = true;
                                state=OVER; //游戏结束
                            }
                        }
                    }

                    
                    repaint(); //重画
                    try {
                        Thread.sleep(20); //线程休眠
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    //鼠标点击事件
    @Override
    public void mouseClicked(MouseEvent e) {
        if(state==START||state==PAUSE){
            state=RUNNING;
        }else if (state==RUNNING){
            state=PAUSE;;
        }else if(state==OVER){
            
            //重新开始后初始化参数值
            state=RUNNING;
            score=0;
            count=0;
            bx = 0;
            bg = new ImageIcon("src/images/background_1.png").getImage();
            by = -5350;
            zd = new ArrayList<Zd>();
            dj = new ArrayList<Dj>();
            
        }

    }

    @Override
    public void mousePressed(MouseEvent e) {
        // TODO 自动生成的方法存根

    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO 自动生成的方法存根

    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO 自动生成的方法存根

    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO 自动生成的方法存根

    }

    @Override
    public void mouseDragged(MouseEvent e) {
        // TODO 自动生成的方法存根

    }

    @Override
    public void mouseMoved(MouseEvent e) {
        x = e.getX(); //动态获取鼠标的坐标值
        y = e.getY();

    }

}

四、 创建游戏主线程和游戏窗口

窗口类Game.java代码:

package frame;

import javax.swing.JFrame;

import panel.GamePanel;

public class Game {

    public static void main(String[] args) {
        JFrame j = new JFrame(); //创建窗口
        GamePanel g = new GamePanel(); //创建画布
        j.add(g); //添加画布
        j.setSize(400, 650);
        j.setTitle("PlaneWar"); //设置标题
        j.setLocationRelativeTo(null); //设置居中
        j.setDefaultCloseOperation(3); //默认关闭
        j.setVisible(true); //窗口可见性
        g.Move(); //调用Move方法
        j.addMouseListener(g); //添加监听器
        j.addMouseMotionListener(g);

    }

}

到这里,一个太监版的飞机大战小游戏就完成了。你有你的王者荣耀,我有我的飞机大战,不是很炫,但是很六。

欢迎访问我的网站:学长帮

猜你喜欢

转载自blog.csdn.net/tongshuyang/article/details/83214814