java.swing 飞机大战小游戏

news2025/8/2 17:41:40

上午没事刷到网上最近炒热了一些简单的小游戏和爱心代码,单身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拜拜!!!

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/16081.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python如何使用PyMySQL连接数据库

1&#xff1a;为什么要连接数据库呢&#xff1f; 做接口自动化测试的时候&#xff0c;我们需要校验数据是否正常入库&#xff0c;数据是否正确&#xff0c;来做断言处理&#xff1b;有的时候需要修改数据&#xff0c;去执行其他场景的测试用例&#xff1b;有的时候需要删除数据…

DOX-HSA/HGB/FITC/Glu人血清蛋白/血红蛋白/荧光素/葡萄糖修饰阿霉素

小编今天分享给大家的科研知识是DOX-HSA/HGB/FITC/Glu人血清蛋白/血红蛋白/荧光素/葡萄糖修饰阿霉素&#xff0c;来看&#xff01; DOX-HSA人血清蛋白偶联阿霉素相关&#xff1a; 采用阿霉素(Doxorubicin,DOX)与人血清白蛋白(HSA)经化学交联获得的偶联物。本品经过滤,溶于PBS…

Chapter4 利用机器学习解决分类和回归问题

目录 4.1 机器学习和神经网络基本概念 4.1.1 感知器 4.1.2 前向传播 4.1.3 反向传播 4.1.4 过拟合和欠拟合 4.2 利用神经网络解决回归问题 4.2.1 问题介绍 4.2.2 利用pytorch解析数据 4.2.2 利用pytorch定义网络结构 4.2.3 开始训练 4.2.4 将模型进行保存 4.3 利用p…

云中马在A股上市:总市值约为40亿元,叶福忠为实际控制人

11月18日&#xff0c;浙江云中马股份有限公司&#xff08;下称“云中马”&#xff0c;SH:603130&#xff09;在上海证券交易所主板上市。本次上市&#xff0c;云中马的发行价为19.72元/股&#xff0c;发行数量为3500万股&#xff0c;募资总额约为6.90亿元&#xff0c;募资金额约…

码农必备?清华大学开源了一款写代码神器。。。

程序员宝藏库&#xff1a;https://gitee.com/sharetech_lee/CS-Books-Store 提升程序员编码效率&#xff0c;是一个经久不衰的话题&#xff0c;从最初用纯文本编辑器到后来代码自动补全&#xff0c;再到后来基于AI智能补全代码&#xff0c;开发者效率的确在不断提升。 关于新工…

这就是程序员眼中的函数吗?(一)

小叮当的任意门1. 函数是什么&#xff1f;2. C语言中的函数分类1. 库函数2. 自定义函数3. 函数的参数1. 实际参数&#xff08;实参&#xff09;2. 形式参数&#xff08;形参&#xff09;4. 函数的调用1. 传值调用2. 传址调用练习1. 写一个函数可以判断一个数是不是素数三级标题…

5分钟实现「视频检索」:基于内容理解,无需任何标签

Notebook 教程&#xff1a;text-video retrieval 「视频检索」任务就是输入一段文本&#xff0c;检索出最符合文本描述的视频。随着各类视频平台的兴起和火爆&#xff0c;网络上视频的数量呈现井喷式增长&#xff0c;「视频检索」成为人们高效查找视频的一项新需求。传统的视频…

Matlab点云处理及可视化第1期—基于KD树的邻域点搜索(柱状邻域、球状邻域及KNN)

目录 1 概述 2 代码实现 3 可视化验证 数据及完整代码获取方式&#xff1a; 观前提示&#xff1a;本文文字内容请勿直接用于论文写作&#xff0c;否则后果自负。 特别提示&#xff1a;《Matlab点云处理及可视化》系列文章旨在为初入点云处理领域的朋友提供一份较为权威、可…

MR直播(混合现实直播)做一场高品质企业培训

阿酷TONY / 2022-11-18 / 长沙 MR&#xff0c;是英文Mixed Reality两个单词的缩写&#xff0c;中文翻译为混合现实。 MR混合现实直播技术是通过在现实环境中引入虚拟场景信息&#xff0c;增强用户体验的真实感&#xff0c;具有真实性、实时互动性等特点。 MR直播解决方案是深…

基于springboot农产品交易平台的设计与实现

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于特色农产品电商平台 当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了特色农产品电商平台&#xff0c;它彻底…

软件需求分析——需求的理论基础

如果有兴趣了解更多相关内容&#xff0c;可以来我的个人网站看看&#xff1a;瞳孔空间 一&#xff1a;需求的涵义 研究对象&#xff1a;软件加强型系统中的软件 软件加强型系统&#xff1a;泛指由计算机技术支持的互相联系着的一组人类活动组成的系统。与物理设备和人类社会…

linux网络协议栈源码分析 - 传输层(TCP的输出)

1、TCP write系统调用(tcp_sendmsg) 1.1、write系统调用 socket的write系统调用栈: write最终调用tcp_sendmsg发送消息。 1.2、tcp_sendmsg报文分段 tcp_sendmsg主要是对用户的消息按MSS进行分段、添加到发送队列并将用户数据拷贝到分段里面&#xff0c;根据相关判断设置PSH标…

[附源码]SSM计算机毕业设计超市收银系统论文JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

学生台灯是灯管的好还是led的好?分享学生专用台灯第一品牌

给学生使用的话肯定是led灯更好的&#xff0c;主要是对眼睛有保护作用的&#xff0c;灯管一般当做主要照明灯具是可以的&#xff0c;在家中客厅里&#xff0c;卧室就是灯管&#xff0c;使用led灯是想要补足亮度的&#xff0c;全光谱的国AA级台灯&#xff0c;更健康、更适应人类…

计算机网络---ARP、DHCP与ICMP

&#xff08;一&#xff09;IP 地址与硬件地址 IP地址是网络层使用的地址&#xff0c;它是分层次等级的。硬件地址是数据链路层使用的地址&#xff08;MAC地址&#xff09;&#xff0c;它是平面式的。在网络层及网络层之上使用IP地址&#xff0c;IP地址放在IP数据报的首部&…

并肩刘德华,对战周杰伦,腾格尔老师线上演唱会即将拉开帷幕

在刚刚结束的第三十五届金鸡奖上面&#xff0c;著名爱国艺人刘德华&#xff0c;又一次出现在大众的视野当中。来自香港的天王刘德华&#xff0c;是一个著名的音乐人和演员&#xff0c;他拳拳的爱国之情&#xff0c;也感动了无数的粉丝。 刘德华作为中国华语乐坛的中坚力量&…

22071班(11月18日)

1.在串口工具进行输入&#xff1a; echo 1 > /dev/myled0 ---->led1灯点亮 echo 0 > /dev/myled0 ---->led1灯熄灭 echo 1 > /dev/myled1 ---->led1灯点亮 echo 0 > /dev/myled1 ---->led1灯熄灭 echo 1 > /dev/myled2 ----…

【附源码】计算机毕业设计JAVA校园跑腿平台

【附源码】计算机毕业设计JAVA校园跑腿平台 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JAVA mybati…

什么是PaaS平台

PaaS平台概述 PaaS平台通常是基于IaaS平台构建的&#xff0c;PaaS平台和IaaS平台最大的差别是需求即服务。所有的管理都是以服务为粒度的&#xff0c;在IaaS以资源管理为中心的平台上提供了更高层次的抽象。 PaaS的本质 &#xff08;1&#xff09;运维自动化&#xff0c;故障…

统计聚类法的基本步骤:

统计聚类法的基本步骤&#xff1a; 1>形成数据框 2>计算距离阵 计算n个样品两两间的距离D。 3>进行系统聚类 (I&#xff09;构造n个类,每个类只包含一个样品; (2&#xff09;合并距离最近的两类为一新类; (3&#xff09;计算新类与当前各类的距离,若类个数为1,…