java.swing 飞机大战小游戏

上午没事刷到网上最近炒热了一些简单的小游戏和爱心代码,单身8个月了,对爱心代码不是很感冒,所以想蹭个热度,写一个飞机大站来玩玩。

首先,分析小游戏需要那些技术与怎么设计:

窗体,因为是java小游戏,那么就需要用到java的swing或者是Fx包里的相关图形化方法。

多线程,因为不可能是只有我们的飞机在飞,敌方也有飞机,子弹也需要飞行。

图片读取:需要将图片放入窗体中,所以需要借助画布,但是前提是我们需要将图片解析出来。

实体设计:越成熟的游戏设计的敌方飞机与我方飞机的功能与属性越多,这都需要基于实体实现。


那么基于以上几个点,我们首先就是建立一个可视化的窗体出来:

借助所谓的JFrame窗体类实现(也可继承来实现):

public static void main(String[] args) throws IOException {
            JFrame frame = new JFrame();
            GamePanel gamePanel = new GamePanel();
            frame.add(gamePanel);
            frame.setSize(576, 840);
            frame.setTitle("战机");
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
            frame.setDefaultCloseOperation(3);
            gamePanel.move();
            frame.addMouseListener(gamePanel);
            frame.addMouseMotionListener(gamePanel);
    }

因为是一个窗体,所以我们需要借助画布对象来给窗体内部添加一些元素。也需要借助鼠标监听的相关接口对鼠标事件进行业务重写。

这里我们直接挂出来(相关代码的释疑都在注释里):

画布类:

package com.hlc.Game;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import static java.awt.Font.BOLD;


public class GamePanel extends JPanel implements MouseListener, MouseMotionListener {

    Image backGround, boss, zu, me,mePlus, ziDan, destroy, startGame;//图片资源
    int state;//控制游戏状态开关 变量 0未开始,1开始,2暂停,3退出
    int mark = 0, count = 0;//分数与计数器
    int mouseX = 180, mouseY = 500, blood = 100;//我方战斗机坐标X,Y与战斗机血量。

    boolean boom = false;//爆炸开关 显示爆炸图片的控制开关
    int badAirX, badAirY;//存储爆炸敌方飞机坐标便于画出爆炸图片
    List<BadAir> badAirs = new LinkedList<>();//存储敌机对象
    List<ZiDan> ziDans = new LinkedList<>();//存储子弹对象


    public GamePanel() throws IOException {
        state = 0;
        mark = 0;
        backGround = ImageIO.read(new File("D:\\java项目\\Game\\Image\\back.png"));
        boss = ImageIO.read(new File("D:\\java项目\\Game\\Image\\boss.png"));
        startGame = ImageIO.read(new File("D:\\java项目\\Game\\Image\\start.png"));
        me = ImageIO.read(new File("D:\\java项目\\Game\\Image\\mePlus.png"));
        mePlus = ImageIO.read(new File("D:\\java项目\\Game\\Image\\me.png"));
        zu = ImageIO.read(new File("D:\\java项目\\Game\\Image\\zu.png"));
        ziDan = ImageIO.read(new File("D:\\java项目\\Game\\Image\\ziDan.png"));
        destroy = ImageIO.read(new File("D:\\java项目\\Game\\Image\\destroy.png"));
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.setFont(new Font("仿宋", BOLD, 20));
        g.setColor(Color.YELLOW);
        /*初始游戏状态*/
        if (state == 0) {
            g.drawImage(backGround, 0, 0, null);
            g.drawString("分数:" + mark + "", 0, 20);
            g.drawImage(boss, 204, 0, null);
            g.drawImage(startGame, 258, 300, null);
            g.drawString("开始游戏", 248, 400);
            g.drawImage(mePlus, 237, 500, null);
        }
        /*开始游戏状态*/
        else if (state == 1) {
            g.drawImage(backGround, 0, 0, null);
            g.drawString("分数:" + mark + "", 0, 20);
            if(mark > 50){
                g.drawImage(mePlus,mouseX-51,mouseY-63,null);
            }
            else
                g.drawImage(me,mouseX-23,mouseY-28,null);

            if (boom) {
                g.drawImage(destroy, badAirX, badAirY, null);
                boom = false;
            }

            for (int i = 0; i < ziDans.size(); i++) {
                ziDans.get(i).drawZiDan(g);
            }

            for (int i = 0; i < badAirs.size(); i++) {
                badAirs.get(i).drawPanel(g);
            }
        }
        /*暂停游戏状态*/
        else if (state == 2) {
            g.drawImage(backGround, 0, 0, null);
            g.drawString("分数:" + mark + "", 0, 20);
            g.drawImage(boss, 156, 0, null);
            g.drawImage(startGame, 210, 300, null);
            g.drawString("开始游戏", 200, 400);
            g.drawImage(me, 189, 500, null);
        }
        /*退出游戏状态(数据清空,等待重新开始游戏)*/
        else {
            state = 0;
            repaint();
        }

    }

    public void move() {
        new Thread() {
            @Override
            public void run() {
                super.run();
                while (true) {
                    if (state == 1) {
                        count++;//计数器自增开始

                        if (count % 3 == 0) {
                            ziDans.add(new ZiDan(mouseX,mouseY,ziDan));//创建新子弹
                        }
                        for (int i = 0;i<ziDans.size();i++){
                            ziDans.get(i).setY(ziDans.get(i).getY()-10);//发射子弹,超出窗体外则删除子弹对象
                            if (ziDans.get(i).getY()<0){
                                ziDans.remove(i);
                            }
                        }

                        if (count%21 == 0){
                            badAirs.add(new BadAir(zu));//创建敌机
                        }else if(count % 72 == 0){
                            badAirs.add(new BadAir(boss));
                        }

                        for (int i =0;i<badAirs.size();i++){
                            badAirs.get(i).setY(badAirs.get(i).getY()+3);//运动敌机,到达我方阵地则重新准备新局
                            if (badAirs.get(i).getY()>700){
                                state = 3;
                                mark = 0;
                                blood = 100;
                            }
                        }

                        GameJudgeDead judgeDead = new GameJudgeDead();//初始化判断碰撞对象

                        for (int i = 0;i<ziDans.size();i++){
                            ZiDan ziDan = ziDans.get(i);
                            for (int j=0;j<badAirs.size();j++){
                                BadAir badAir = badAirs.get(j);
                                if (judgeDead.judgeBoomZiDan(ziDan,badAir)){
                                    mark+=2;
                                    badAirX = badAir.getX();
                                    badAirY = badAir.getY();
                                    boom = true;
                                    ziDans.remove(i);
                                    badAirs.remove(j);
                                    break;
                                }
                            }
                        }

                        for (int i=0;i<badAirs.size();i++){
                            if (judgeDead.judgeBoomAir(badAirs.get(i),mouseX,mouseY)){
                                badAirX = badAirs.get(i).getX();
                                badAirY = badAirs.get(i).getY();
                                boom = true;
                                blood -= 30;
                                if (blood <= 0) {
                                    state = 3;
                                    mark = 0;
                                    blood = 100;
                                }
                            }
                        }
                    }
                    repaint();
                    try{
                        Thread.sleep(20);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        if (state == 0) {
            state = 1;
        } else if (state == 1) {
            state = 2;
        } else if (state == 2) {
            state = 1;
        } else {
            state = 0;
        }
    }
.........接口方法存根省略..........
    @Override
    public void mouseMoved(MouseEvent e) {
        mouseX = e.getX();
        mouseY = e.getY();
    }
}

这里需要注意几个问题,之前用webp格式的图片下载之后强行改后缀为png之后再内部怎么写都不能加载出来图片显示,这是一个问题,因为浏览器对图片进行了压缩解码,所以一定要下载原图!!!

接下来我们挂出来碰撞判断类:

public class GameJudgeDead {

    public boolean judgeBoomZiDan(ZiDan ziDan, BadAir badAir) {
        return badAir.getX() < ziDan.getX() && badAir.getY() + badAir.height > ziDan.getY() && badAir.getX() + badAir.width > ziDan.getX();
    }

    public boolean judgeBoomAir(BadAir badAir, int mouseX, int mouseY) {
        mouseX = mouseX - 51;
        mouseY = mouseY - 63;
        return badAir.getX() < mouseX && badAir.getY() + badAir.height > mouseY && badAir.getX() + badAir.width > mouseY;
    }
}

这里面你需要计算碰撞的条件,以及里面的坐标代表的意思,尤其是你切换图片之后对应的尺寸会变化,所以最好用实体。

敌机实体:

public class BadAir {
    int X;
    int Y;
    Image badAir;
    int height;
    int width;

    public BadAir( Image badAir) {
        X =(int) (Math.random()*480);
        Y = -30;
        this.badAir = badAir;
        height = badAir.getHeight(null);
        width = badAir.getWidth(null);
    }

    void drawPanel(Graphics g){
        g.drawImage(badAir,X-27,Y-20,null);
    }


    public int getX() {
        return X;
    }

    public void setX(int x) {
        X = x;
    }

    public int getY() {
        return Y;
    }

    public void setY(int y) {
        Y = y;
    }

}

注意这里将图片的尺寸写入到实体属性中去了,方便后续因为图片的切换来。

子弹实体类

public class ZiDan {
    int x,y;
    Image ZiDan;
    public ZiDan(int mouseX,int mouseY,Image ZiDan){
        this.x = mouseX;
        this.y = mouseY;
        this.ZiDan = ZiDan;
    }
    public void drawZiDan(Graphics g){
        g.drawImage(ZiDan,x,y,null);
    }

    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;
    }
}

这里没有给敌机添加子弹。

OK拜拜!!!

 

 

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ForestSpringH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值