《飞机大战游戏》实训项目(Java GUI实现)(设计模式)(简易)
目录
一、最终实现后,效果如下。
(1)简单介绍本游戏项目(待完善)
(2)运行效果图(具体大家自己可以试)
初始运行情况。
手动更换背景图。
通过子弹攻击敌机,累计游戏分数。由变量"score"控制。
二、各个类的代码如下
(1)启动类(主类)
(2)自定义的"窗口"类(Frame)extends"JFrame"
(3)自定义"内容面板"类(Panel)extends"JPanel"
(4)"敌机"类(EnemyPlane)
(5)"本人飞机"类(Plane)
(6)"子弹"类(Fire)
一、最终实现后,效果如下。
(1)简单介绍本游戏项目(待完善)
- 只是学校的简单的实训项目,里面还可以进行很多内容可以补充或者完善。
- 里面有一个功能,博主实现的时候,"大"的敌机左右移动时,存在"摇摇晃晃"的情况。所以这里博主把这一部分的代码注释了,只让其"y的坐标值"变化。
- "小"敌机移动速度快,"大"敌机移动速度慢。
- 游戏界面的背景图,不会随着时间而进行改变(大家可以完善)。
- "自己飞机"的键盘移动操作不是很流畅,需要完善。
- "敌机"没有血量,自己操控的飞机没有血量,没有游戏结束"game over"的触发。
- 只有子弹击中敌机的判定。当子弹的坐标与敌机坐标满足条件,就触发方法,将敌机remove()。
- 子弹与敌机的创建都用到了线程的知识。并且通过"W"(上)、"S"(下)、"A"(左)、"D"(右)或者鼠标进行操控自己的飞机,进行攻击"x坐标指定范围内"、"y坐标为0"生成的敌机。
- 基本的技术用到了Java GUI(可视化)提供的类"Panel"、"JFrame",以及其下的方法实现。
- 当运行到一定的时间,该实训项目会出现报错地方(敌机生成线程、子弹生成线程)。
(2)运行效果图(具体大家自己可以试)
初始运行情况。
手动更换背景图。
通过子弹攻击敌机,累计游戏分数。由变量"score"控制。
二、各个类的代码如下
(1)启动类(主类)
package ui;/*** @Title: Main* @Author HeYouLong* @Package ui* @Date 2024/9/12 上午8:33* @description:*/ public class Main {public static void main(String[] args) {Frame frame = new Frame();Panel panel = new Panel(frame);frame.add(panel);panel.begin();panel.fireBegin();frame.setVisible(true);} }
(2)自定义的"窗口"类(Frame)extends"JFrame"
- "JFrame"类是 Java Swing 图形用户界面工具包中的一个非常重要的类,它代表了一个窗口,是顶级容器之一。在 Swing 应用程序中,几乎所有的 GUI 组件都直接或间接地包含在一个"JFrame"窗口中。
- JFrame 提供了窗口的基本功能,如标题栏、最小化/最大化按钮、关闭按钮以及可调整大小的边框。但是,JFrame 本身不包含任何可视化组件(如按钮、文本框等);这些组件必须被添加到 JFrame 的内容面板(ContentPane)中,而内容面板默认是一个 "JPanel"。
package ui;import javax.swing.*;/*** @Title: Frame* @Author HeYouLong* @Package ui* @Date 2024/9/12 上午8:32* @description:*/ public class Frame extends JFrame {public Frame(){setTitle("设计模式课程飞机大战");setSize(512,768);setLocationRelativeTo(null);//居中setResizable(false);//不准随便改变窗口大小setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口——>退出进程} }
(3)自定义"内容面板"类(Panel)extends"JPanel"
- "JPanel" 类是 Java Swing 图形用户界面工具包中的一个非常重要的类,它继承自 JComponent 并实现了 Container 接口。JPanel 是一种轻量级的容器,可以用来组织和管理其他 GUI 组件(如按钮、文本框、标签等)。与 JFrame 不同的是,JPanel 本身不是一个顶级容器,它必须被添加到某个顶级容器(如 JFrame、JDialog 或 JApplet)中才能显示。
- 这个类的内容比较多,因为是"内容面板"嘛。
package ui;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; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List;/*** @Title: Panel* @Author HeYouLong* @Package ui* @Date 2024/9/12 上午8:38* @description:*/ public class Panel extends JPanel {private BufferedImage bg = GetImg.getImg("bg5.jpg");private Plane plane;private List<EnemyPlane> enemyPlaneList = new ArrayList<>();private List<Fire> fires = new ArrayList<>();//敌机public void begin() {new Thread() {public void run() {while (true) {CreateEp(); //创建敌机 todoMoveEp(); //敌机移动 todohit(); //子弹碰撞try {Thread.sleep(20);} catch (InterruptedException e) {throw new RuntimeException(e);}repaint();//画敌机}}}.start();}private static int score=0;//判断子弹与敌机是否碰撞private void hit() {for (int i = 0; i < enemyPlaneList.size(); i++) {EnemyPlane enemyPlane = enemyPlaneList.get(i);for (int j = 0; j < fires.size(); j++) {Fire fire = fires.get(j);if(fire.x+fire.image.getWidth()/2>enemyPlane.getX() && fire.x<enemyPlane.getX()+enemyPlane.getImg().getWidth() && fire.y+fire.image.getHeight()/2>enemyPlane.getY() && fire.y<enemyPlane.getY()+enemyPlane.getImg().getHeight()){enemyPlaneList.remove(i);fires.remove(j);score++;}}}}//子弹的线程public void fireBegin() {new Thread() {public void run() {while (true) {//创建子弹fireCreate();//子弹移动fireMove();//休息线程try {Thread.sleep(10);} catch (InterruptedException e) {throw new RuntimeException(e);}//画子弹repaint();}}}.start();}private void fireMove() {for (int i = 0; i < fires.size(); i++) {Fire fire = fires.get(i);fire.y=fire.y-10;}}private static int index = 0;private void fireCreate() {index++;if (index >= 12) {Fire fire = new Fire(plane);fires.add(fire);index = 0;}}private void MoveEp() {for (int i = 0; i < enemyPlaneList.size(); i++) {EnemyPlane enemyPlane = enemyPlaneList.get(i);enemyPlane.move();}}private static int count = 0;private void CreateEp() {count++;if (count >= 12) {EnemyPlane enemyPlane = new EnemyPlane();enemyPlaneList.add(enemyPlane);count = 0;}}public Panel(Frame frame) {plane = new Plane();//鼠标操作mouse();//键盘操作 todokey(frame);}private void key(Frame frame) {KeyAdapter keyAdapter = new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {super.keyPressed(e);int i = e.getKeyCode();//获得按的键if (i == KeyEvent.VK_A || i == KeyEvent.VK_LEFT) {plane.setX(plane.getX() - 30);if (plane.getX() <= 0) {plane.setX(0);}} else if (i == KeyEvent.VK_D || i == KeyEvent.VK_RIGHT) {plane.setX(plane.getX() + 30);if (plane.getX() >= 395) {plane.setX(395);}} else if (i == KeyEvent.VK_W || i == KeyEvent.VK_UP) {plane.setY(plane.getY() - 30);if (plane.getY() <= 0) {plane.setY(0);}} else if (i == KeyEvent.VK_S || i == KeyEvent.VK_DOWN) {plane.setY(plane.getY() + 30);if (plane.getY() >= 635) {plane.setY(635);}}repaint();}};frame.addKeyListener(keyAdapter);}private void mouse() {MouseAdapter mouseAdapter = new MouseAdapter() {@Overridepublic void mouseMoved(MouseEvent e) {super.mouseMoved(e);plane.setX(e.getX() - plane.getImage().getWidth() / 2);plane.setY(e.getY() - plane.getImage().getHeight() / 2);//重新画repaint();}};addMouseListener(mouseAdapter);addMouseMotionListener(mouseAdapter);}@Overridepublic void paint(Graphics g) {super.paint(g);g.drawImage(bg, 0, 0, null); //本人飞机初始位置g.drawImage(plane.getImage(), plane.getX(), plane.getY(), null); //画敌机for (int i = 0; i < enemyPlaneList.size(); i++) {EnemyPlane enemyPlane = enemyPlaneList.get(i);g.drawImage(enemyPlane.getImg(), enemyPlane.getX(), enemyPlane.getY(), null);}//画子弹for (int i = 0; i < fires.size(); i++) {Fire fire = fires.get(i);g.drawImage(fire.image,fire.x, fire.y,fire.image.getWidth()/2,fire.image.getHeight()/2, null);}//画分数g.setColor(Color.white);Font font = new Font("黑体", Font.PLAIN, 22);g.setFont(font);g.drawString("当前游戏分数:"+score, 10, 20);} }
(4)"敌机"类(EnemyPlane)
(控制初始敌机生成的初始x、y坐标位置,控制出现边界,不同类型飞机移动速度等等)
package ui;import java.awt.image.BufferedImage; import java.util.Random;/*** @Title: EnemyPlane* @Author HeYouLong* @Package ui* @Date 2024/9/13 上午10:26* @description:*/ public class EnemyPlane {private int x;private int y;private int z;private BufferedImage img;public void move(){final int MOVE_SPEED = 10; // 固定的移动速度final int ENEMY_WIDTH = this.img.getWidth(); // 敌机图像的宽度if(z<10){y=y+14;return;}else{/*Random random = new Random();int i = random.nextInt(2);if(i==0){x -= MOVE_SPEED; // 假设z也影响移动速度,这里简单地使用z的模和加数来调整if (x <= 0) {x = 512-ENEMY_WIDTH; // 防止敌机移出屏幕左侧}}else {// 向右移动x += MOVE_SPEED; // 同上,调整移动速度if (x >= 512-this.img.getWidth()) {x = 0;}}*/y=y+8;}}public EnemyPlane() {Random random = new Random();int i = random.nextInt(15)+1;String j = i<10?"0"+i:i+"";//文件名String imgName = "ep"+j+".png";this.img=GetImg.getImg(imgName);//随机图片this.y=0;this.z=i;this.x=random.nextInt(512-this.img.getWidth());}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 BufferedImage getImg() {return img;}public void setImg(BufferedImage img) {this.img = img;}public int getZ() {return z;}public void setZ(int z) {this.z = z;} }
(5)"本人飞机"类(Plane)
(设置初始位置、选定飞机图片、getter()、setter())
package ui;import java.awt.image.BufferedImage;/*** @Title: Plane* @Author HeYouLong* @Package ui* @Date 2024/9/12 上午9:05* @description:*/ public class Plane {private int x;private int y;private BufferedImage image;public Plane() {x=200;y=500;image = GetImg.getImg("hero.png");}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 BufferedImage getImage() {return image;}public void setImage(BufferedImage image) {this.image = image;} }
(6)"子弹"类(Fire)
(子弹的初始坐标与飞机的坐标要进行适配,也就是有联系。选定子弹图片)
package ui;import java.awt.image.BufferedImage;/*** @Title: Fire* @Author HeYouLong* @Package ui* @Date 2024/9/20 上午10:34* @description:*/ //子弹类 public class Fire {BufferedImage image;int x;int y;public Fire(Plane plane) {image = GetImg.getImg("fire.png");//子弹的坐标x=plane.getX()+plane.getImage().getWidth()/2-image.getWidth()/2/2;y=plane.getY()-image.getHeight()/2/2;} }
相关文章:

《飞机大战游戏》实训项目(Java GUI实现)(设计模式)(简易)
目录 一、最终实现后,效果如下。 (1)简单介绍本游戏项目(待完善) (2)运行效果图(具体大家自己可以试) 初始运行情况。 手动更换背景图。 通过子弹攻击敌机,累…...

计算机毕业设计 基于 Hadoop平台的岗位推荐系统 SpringBoot+Vue 前后端分离 附源码 讲解 文档
🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…...

【数据结构与算法】LeetCode:二分查找
文章目录 二分查找二分查找搜索插入位置 (Hot 100)x 的平方根搜索二维矩阵(Hot 100)在排序数组中查找元素的第一个和最后一个位置 (Hot 100)搜索旋转排序数组 (Hot 100)寻找旋转排序…...
专题·大模型安全 | 生成式人工智能的内容安全风险与应对策略
正如一枚硬币的两面,生成式人工智能大模型(以下简称“生成式大模型”)在助力内容生成的同时也潜藏风险,成为虚假信息传播、数据隐私泄露等问题的温床,加剧了认知域风险。与传统人工智能(AI)相比…...
CORS跨域+Nginx配置、Apache配置
CORS(Cross-Origin Resource Sharing,跨源资源共享)是一种机制,它使用额外的HTTP头部来告诉浏览器允许一个网页运行的脚本从不同于它自身来源的服务器上请求资源(例如字体、JavaScript、CSS等)。这是一种安…...

文件查找和打包压缩【1.7】
文件查找和打包压缩【1.7】 八、文件查找和打包压缩8.1 文件查找8.1.1 locate8.1.2 findfind8.1.2.1 指定搜索目录层级8.1.2.2 先处理文件再处理目录8.1.2.3 根据文件名和inode查找8.1.2.4 根据属主属组查找8.1.2.5 根据文件类型查找8.1.2.6 空文件或目录8.1.2.7 组合条件8.1.2…...
速盾:cdn一般多长时间清理下缓存?
CDN(Content Delivery Network)是一种网络加速技术,通过将网站的静态资源(如图片、视频、CSS、JavaScript等)分布到全球各地的服务器节点上,从而提高用户访问这些资源的速度和体验。CDN还具备缓存功能&…...

react hooks--useRef
基本用法 在类组件中获取一个dom元素实例,可以通过React.CreateRef或者回调函数的方式去获取。语法:const refContainer useRef(initialValue);使用场景:在 React 中进行 DOM 操作时,用来获取 DOM作用:返回一个带有 …...
GPT对话知识库——将寄存器中的一位数据读到变量中需要什么步骤?C语言中掩码的作用。
目录 1,问: 1,答: 1. 确定目标寄存器地址 2. 定位目标位 位操作的基本步骤: 3. 示例代码 示例步骤: 4. 详细解释步骤 5. 举例 6. 常见用法 总结 注: C语言中掩码的作用:…...
【计算机网络】运输层协议解析
前言 运输层直接为应用进程间的逻辑通信提供服务。运输层向高层用户屏蔽了下面网络核心细节(如网络拓扑、路由选择协议等)它使应用进程看见的就好像是在两个运输层实体之间有一条端到端的逻辑通信信道。 UDP与TCP对比 UDP: 无连接 支持一对…...

Redis存储原理
前言 我们从redis服务谈起,redis是单reactor,命令在redis-server线程处理。还有若干读写IO线程负责IO操作(redis6.0之后,Redis之pipeline与事务)。此外还有一个内存池线程负责内存管理、一个后台文件线程负责大文件的关…...

PHP、Java等其他语言转Go时选择GoFly快速快速开发框架指南
概要 经过一年多的发展GoFly快速开发框架已被一千多家科技企业或开发者用于项目开发,它的简单易学得到其他语言转Go首选框架。且企业版的发展为GoFly社区提供资金,这使得GoFly快速框架得到良好的发展,GoFly技术团队加大投入反哺科技企业和开…...
【MySQL】获取最近7天和最近14天的订单数量,使用MySQL详细写出,使用不同的方法
1. 获取最近7天和最近14天的订单数量,使用MySQL详细写出,使用不同的方法 要获取最近7天和最近14天的订单数量,我们可以使用不同的方法来优化查询性能。以下是两种方法: 1.1 方法一:使用日期计算 SELECTSUM(CASE WHE…...
WebView2新增、修改、删除、禁用右键菜单相关操作。
参考链接:WebView2操作右键菜单...

使用vue创建项目
一、安装环境 二、创建vue框架(创建文件夹,摁shift鼠标右键 打开) 1、项目配置 2、新增目录 三、路径别名配置 输入/ ,VSCode会联想出src下的所有子目录和文件,统一文件路径访问时不容易出错 四、ElementPlus配置 1、组件分为…...

Apache CVE-2021-41773 漏洞攻略
漏洞简介 该漏洞是由于Apache HTTP Server 2.4.49版本存在⽬录穿越漏洞,在路径穿越⽬录 <Directory/>Require all granted</Directory>允许被访问的的情况下(默认开启),攻击者可利⽤该路径穿越漏洞读取到Web⽬录之外的其他⽂件在…...

【redis-02】深入理解redis中RBD和AOF的持久化
redis系列整体栏目 内容链接地址【一】redis基本数据类型和使用场景https://zhenghuisheng.blog.csdn.net/article/details/142406325【二】redis的持久化机制和原理https://zhenghuisheng.blog.csdn.net/article/details/142441756 如需转载,请输入:htt…...

亚马逊IP关联揭秘:发生ip关联如何处理
在亚马逊这一全球领先的电商平台上,IP关联是一个不可忽视的问题,尤其是对于多账号运营的卖家而言。本文将深入解析亚马逊IP关联的含义、影响以及应对策略,帮助卖家更好地理解和应对这一问题。 什么是亚马逊IP关联? 亚马逊IP关联…...
jQuery Mobile 弹窗
jQuery Mobile 弹窗 引言 在移动设备上,弹窗是一种常见的用户界面元素,用于显示信息、获取用户输入或提供特定功能。jQuery Mobile 是一个流行的移动框架,它提供了丰富的组件来帮助开发者创建响应式的移动界面。本文将重点介绍如何在 jQuery Mobile 中使用弹窗(Popup)组…...

【macOS】【zsh报错】zsh: command not found: python
【macOS】【zsh Error】zsh: command not found: python 本地已经安装了Python,且能在Pycharm中编译Python程序并运行。 但是,在macOS终端,运行Python,报错。 首先要确认你在macOS系统下,是否安装了Python。 如果安…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...