小游戏制作——飞机大战
java 实现
耗时四天,通过借鉴学习别人,到自己写代码。比较费头发。但最终也还是肝了出来。本来还想弄一个 菜单栏,用该改变战机和子弹,但迫于时间有限。能先写到这里了。等过段时间,我再来完善它!
1.首先 我将英雄机,敌机,子弹,玩家。都分别当做对象来处理。单独写.java文件。
2. 写一个窗口(GUI编程)。存放所有的对象。并行多线程,因为敌机 英雄机 子弹,都需要同时运行。不断检测敌机是否被子击中,英雄机是否碰到敌机。所以:这些对象 都要继承 Thread 重写 run 方法
3. 事件监听器也有写,在英雄机碰到敌机时触发,弹出窗口Gameover 并且关闭所有的窗口。结束进程。
4. 因为 敌机和子弹,在窗口中都会同时出现多个。我使用了vector 集合用来存放对象。 敌机和子弹都会消失,使用集合的 remove 方法就可以。
vector 和 list 的区别:
vector:连续存储结构:vector是可以实现动态增长的对象数组,支持对数组高效率的访问和在数组尾端的删除和插入操作,在中间和头部删除和插入相对不易,需要挪动大量的数据。
它与数组最大的区别就是vector不需程序员自己去考虑容量问题,库里面本身已经实现了容量的动态增长,而数组需要程序员手动写入扩容函数进形扩容。
list:非连续存储结构:list是一个双链表结构,支持对链表的双向遍历。每个节点包括三个信息:元素本身,指向前一个元素的节点(prev)和指向下一个元素的节点(next)。
因此list可以高效率的对数据元素任意位置进行访问和插入删除等操作。由于涉及对额外指针的维护,所以开销比较大。
5. 对方向键 的键值 做出了解。 玩家通过方向键来操控英雄机。需要,switch 语句进行识别 玩家按了哪个键。但同时,英雄机的移动范围也是有限的。不能移出窗口。
6. 将所有的java文件 存放在同一目录下,来自同一个包。
其余的小点:我在代码中有注释。大家多加理解吧!不理解可以私信我哦!
GameFrame.java 文件 窗口文件
package VacationTest.PlaneFight.src;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;
import java.util.Vector;
public class GameFrame extends JFrame {
//对英雄机和敌机作提前声明
HeroPlane heroplane;
EnemyPlane enemyPlane;
// 定义子弹集合
Vector<bullet> bullets = new Vector<>();
//敌机集合
Vector<EnemyPlane> enemys = new Vector<>();
GameFrame frame;
public GameFrame() {
frame = this ;// 后面 敌机的线程中要使用
// 创建英雄机
heroplane = new HeroPlane();
//启动英雄机线程
heroplane.start();
// 设置窗体的宽高
this.setSize(500, 760);
this.setTitle("飞机大战---小帅制作");
this.setResizable(false);//设置 用户是否可以调整窗口的大小 这里设置为 否
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);//设置窗口 相对于屏幕的位置,null 指:处于屏幕中央
// 窗口可见
this.setVisible(true);
// 新建线程,让 画笔 不断 重复
new Thread(new Runnable() {//内部类。
@Override
public void run() {
while (true) {
repaint();//不断重复画
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//产生敌机的线程
new Thread(new Runnable(){
//产生随机数
Random r = new Random();
@Override
//重写run 方法
public void run(){
while(true){
EnemyPlane enemyPlane = new EnemyPlane(r.nextInt(500), 0,frame);// 随机产生敌机,并创建敌机对象
enemyPlane.start(); // 启动线程
//随机产生敌机
enemys.add(enemyPlane); // 将 敌机对象 添加到 enemy 集合中
try{
Thread.sleep(500);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}).start();
}
/**
* 在窗口上画图片,需要不断重复的画,使用API中 paint 画笔 重写其中的方法
*
* @param g
*/
public void paint(Graphics g) {
//System.out.println("绘制画板");
// 画背景
BufferedImage image = (BufferedImage) this.createImage(this.getSize().width, this.getSize().height);
// 高效缓存画笔
Graphics pen = image.getGraphics();
pen.drawImage(new ImageIcon("G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\Background.jpg").getImage(),0, 0, null);
// 画英雄机
pen.drawImage(heroplane.img, heroplane.x, heroplane.y, heroplane.width, heroplane.height, null);
// 飞机发射子弹
for (int i = 0; i < bullets.size(); i++) {
//System.out.println("bullet");
// 实例化 子弹对象 b
bullet b = bullets.get(i);
if (b.y > 0)
pen.drawImage(b.img, b.x, b.y -= b.speed, b.width, b.height, null);
else
// 子弹超出上边界 移除
bullets.remove(b);
}
//产生敌机
for (int i = 0; i < enemys.size(); i++) {
//实例化 敌机对象 ep
EnemyPlane ep = enemys.get(i);
if (ep.y < 760)
pen.drawImage(ep.img, ep.x, ep.y += ep.speed, ep.width, ep.height, null);
else
enemys.remove(ep);
}
// 生效
g.drawImage(image, 0, 0, null);
}
public static void main(String[] args) {
GameFrame frame = new GameFrame();
Player player = new Player(frame);
//给 玩家注册事件监听器
frame.addKeyListener(player);
}
}
HeroPlane.java 文件 英雄机文件
package VacationTest.PlaneFight.src;
import java.awt.Image;
import javax.swing.ImageIcon;
public class HeroPlane extends Thread {
int x = 230, y = 650;
int width = 50, height = 50;
int speed = 8;
Image img = new ImageIcon(
"G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\HeroPlane.png")
.getImage();
// 定义方向键标志 up down left right
boolean up, down, left, right;
// 两种 构造器
public HeroPlane() {
}
public HeroPlane(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void run() {
while (true) {
// 实现 英雄机的 移动
if (up) {
if (y > 20) {
y -= speed;
} else {
y -= 0;
}
}
if (down) {
if (y < 700)
y += speed;
else
y += 0;
}
if (left) {
if (x > 10)
x -= speed;
else
x -= 0;
}
if (right) {
if (x < 440)
x += speed;
else
x += 0;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
EnemyPlane.java 文件 敌机文件
package VacationTest.PlaneFight.src;
import java.awt.Image;
import java.awt.Rectangle;
import javax.swing.*;
import VacationTest.PlaneFight.src.Gameover.MyFrame;// 导入 游戏结束的 包 自己写的java 文件
public class EnemyPlane extends Thread {
public GameFrame gf;
// 敌机的位置 大小 速度
int x, y;
int width = 50, height = 50;
int speed = 3;
Image img = new ImageIcon(
"G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\EmenyPlane.png")
.getImage();
// 构造器
public EnemyPlane(int x, int y, GameFrame gf) {
super();
this.x = x;
this.y = y;
this.gf = gf;
}
// 构造器
public EnemyPlane(int x, int y, int width, int height, GameFrame gf) {
super();
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.gf = gf;
}
// 重写run方法 在线程启动时 执行
public void run() {
while (true) {
if (hit()) {
// System.out.println("hit.............");
// 敌机被击毁后,速度变为0 图片更换为 爆炸图片
this.speed = 0;
this.img = new ImageIcon(
"G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\boom3.png")
.getImage();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 子弹击毁 移除敌机
gf.enemys.remove(this);
break;
}
// 敌机超出下边界 移除敌机
if (this.y > 760) {
gf.enemys.remove(this);
break;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (crash()) {
this.speed = 0;
this.img = new ImageIcon().getImage();
new MyFrame(); //实例化MyFrame对象
gf.enemys.remove(this);
gf.heroplane.img = new ImageIcon(
"G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\HeroPlaneBoom.png")
.getImage();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//gf.heroplane.addActionListener(new broken());
System.exit(0);
}
}
}
// 检测碰撞
public boolean hit() {
// Swing技术中,已经实现相关算法
// 给出敌机的矩形
Rectangle myrect = new Rectangle(this.x, this.y, this.width, this.height);
Rectangle rect = null;// 给出子弹的矩形
for (int i = 0; i < gf.bullets.size(); i++) {
bullet b = gf.bullets.get(i);
rect = new Rectangle(b.x, b.y, b.width, b.height);
// 碰撞检测
if (myrect.intersects(rect)) {
return true;
}
}
return false;
}
// 检测 英雄机和 敌机碰撞
public boolean crash() {
Rectangle myrect = new Rectangle(this.x, this.y, this.width, this.height);
Rectangle rect2 = new Rectangle(gf.heroplane.x, gf.heroplane.y, gf.heroplane.width, gf.heroplane.height);
if (myrect.intersects(rect2)) {
return true;
}
return false;
}
}
bullet.java文件 子弹文件
package VacationTest.PlaneFight.src;
import java.awt.Image;
import javax.swing.ImageIcon;
public class bullet {
int x;
int y;
int width=30;
int height=40;
int speed = 15;
Image img = new ImageIcon("G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\bullet2.png").getImage();
public bullet(int x,int y){
this.x = x;
this.y = y;
}
public bullet(int x,int y ,int width , int height){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
Player.java 文件 玩家文件
package VacationTest.PlaneFight.src;
import java.awt.event.*;
public class Player extends KeyAdapter{
//传入 frame 对象 也就是 整个窗体中的所有属性值 使用 对象名.方法 进行调用
GameFrame frame;
public Player(GameFrame frame){
this.frame = frame;
}
/**
* 定义一个玩家,操作键盘的上下左右。以及 发射子弹 空格
* 38 40 37 39 对应 上下左右
* 重写 keyPressed 和 keyReleased 方法 并使用监听器 判断玩家按哪个键
*/
public void keyPressed(KeyEvent e){
int keycode = e.getKeyCode();
//System.out.println(keycode);//利用该语句 可以 知道 键盘上的按键 值是多少。
switch(keycode){
case 38: frame.heroplane.up = true;break;
case 40: frame.heroplane.down = true;break;
case 37: frame.heroplane.left = true;break;
case 39:frame.heroplane.right = true;break;
case 32:addBullet();break;
}
}
public void keyReleased(KeyEvent e){
int keycode = e.getKeyCode();
switch(keycode){
case 38: frame.heroplane.up = false;break;
case 40: frame.heroplane.down = false;break;
case 37: frame.heroplane.left = false;break;
case 39:frame.heroplane.right = false;break;
}
}
// 发射子弹方法 在 键值为 32 时 触发
public void addBullet(){
frame.bullets.add(new bullet(frame.heroplane.x+15, frame.heroplane.y-20));
}
}
Gameover.java文件 游戏结束文件
package VacationTest.PlaneFight.src;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
public class Gameover{
static GameFrame frame;
public static class MyFrame extends JFrame { //创建新类,继承自JFrame
private static final long serialVersionUID = 1L;
public MyFrame() {
Container container = getContentPane(); //创建一个容器
container.setLayout(null);
//JLabel jl = new JLabel("这是一个JFrame窗体"); //在窗体中设置标签
//jl.setHorizontalAlignment(SwingConstants.CENTER); //将标签的文字至于标签中间的位置
//container.add(jl); //将标签添加到容器中
JButton jb = new JButton(""); //定义一个按钮
ImageIcon img = new ImageIcon("G:\\Users\\Administrator\\eclipse-workspace\\test\\src\\VacationTest\\PlaneFight\\Image\\Gameover.jpg");
img.setImage(img.getImage().getScaledInstance(350,150,0));
jb.setBounds(0, 0, 350, 150); //设置按钮的大小
jb.setIcon(img);
jb.addActionListener(new ActionListener() { //为按钮添加点击事件
@Override
public void actionPerformed(ActionEvent e){
try {
Thread.sleep(1500);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.exit(0);
}
});
container.add(jb);
setSize(360,180);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setVisible(true);
setLocationRelativeTo(null);//设置窗口 相对于屏幕的位置,null 指:处于屏幕中央
}
}
}
在代码中使用的图片,以及素材,已经放在百度网盘里了。
注意: 使用的图片路径 要改。
https://pan.baidu.com/s/1L70YtfqrBg8iWqFxmxB1jA
提取码:p6o2
Java程序员如今深陷技术迭代放缓与行业需求收缩的双重困境,职业发展空间正被新兴技术浪潮持续挤压。面对当前Java程序员可能面临的“发展瓶颈”或行业挑战,更积极的应对策略可以围绕技术升级、方向转型、能力拓展三个核心展开,而非被动接受“不行”的标签,通过调查对比,我发现人工智能大模型是个很好的出路。
技术升级与转型机会
-
突破传统Java开发边界:大模型技术的普及为Java开发者提供了新的机遇,使他们能够突破传统企业级开发的局限,进入人工智能这一高增长领域。通过学习大模型集成,Java开发者可以转型为AI应用开发者,拓展职业发展空间。
-
技术栈升级:Java社区积极拥抱大模型技术,推出了多个开源项目和框架,如Deeplearning4j、DJL(Deep Java Library)等。这些工具为Java开发者提供了丰富的资源,使他们能够更方便地构建和部署基于大模型的应用。
发挥Java在企业级应用中的优势
-
稳定性与可靠性:Java作为企业级应用的主流语言,其稳定性和可靠性在大模型应用中同样得到体现。Java的强类型系统和严谨的工程化特性,在构建可靠的大模型应用时提供了额外保障。
-
跨平台性:Java的“一次编写,到处运行”特性使其能够轻松部署到不同操作系统和硬件环境中。这一特性在大型模型的部署和集成中尤为重要,可以降低部署复杂性和成本。
-
多线程处理能力:Java强大的多线程处理能力特别适合大模型的推理部署场景,可以高效处理并发请求,提升系统性能。
说真的,这两年看着身边一个个搞Java、C++、前端、数据、架构的开始卷大模型,挺唏嘘的。大家最开始都是写接口、搞Spring Boot、连数据库、配Redis,稳稳当当过日子。
结果GPT、DeepSeek火了之后,整条线上的人都开始有点慌了,大家都在想:“我是不是要学大模型,不然这饭碗还能保多久?”
先给出最直接的答案:一定要把现有的技术和大模型结合起来,而不是抛弃你们现有技术!掌握AI能力的Java工程师比纯Java岗要吃香的多。
即使现在裁员、降薪、团队解散的比比皆是……但后续的趋势一定是AI应用落地!大模型方向才是实现职业升级、提升薪资待遇的绝佳机遇!
如何学习AGI大模型?
作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
2025最新版优快云大礼包:《AGI大模型学习资源包》免费分享**
一、2025最新大模型学习路线
一个明确的学习路线可以帮助新人了解从哪里开始,按照什么顺序学习,以及需要掌握哪些知识点。大模型领域涉及的知识点非常广泛,没有明确的学习路线可能会导致新人感到迷茫,不知道应该专注于哪些内容。
我们把学习路线分成L1到L4四个阶段,一步步带你从入门到进阶,从理论到实战。

L1级别:AI大模型时代的华丽登场
L1阶段:我们会去了解大模型的基础知识,以及大模型在各个行业的应用和分析;学习理解大模型的核心原理,关键技术,以及大模型应用场景;通过理论原理结合多个项目实战,从提示工程基础到提示工程进阶,掌握Prompt提示工程。

L2级别:AI大模型RAG应用开发工程
L2阶段是我们的AI大模型RAG应用开发工程,我们会去学习RAG检索增强生成:包括Naive RAG、Advanced-RAG以及RAG性能评估,还有GraphRAG在内的多个RAG热门项目的分析。

L3级别:大模型Agent应用架构进阶实践
L3阶段:大模型Agent应用架构进阶实现,我们会去学习LangChain、 LIamaIndex框架,也会学习到AutoGPT、 MetaGPT等多Agent系统,打造我们自己的Agent智能体;同时还可以学习到包括Coze、Dify在内的可视化工具的使用。

L4级别:大模型微调与私有化部署
L4阶段:大模型的微调和私有化部署,我们会更加深入的探讨Transformer架构,学习大模型的微调技术,利用DeepSpeed、Lamam Factory等工具快速进行模型微调;并通过Ollama、vLLM等推理部署框架,实现模型的快速部署。

整个大模型学习路线L1主要是对大模型的理论基础、生态以及提示词他的一个学习掌握;而L3 L4更多的是通过项目实战来掌握大模型的应用开发,针对以上大模型的学习路线我们也整理了对应的学习视频教程,和配套的学习资料。
二、大模型经典PDF书籍
书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础。(书籍含电子版PDF)

三、大模型视频教程
对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识。

四、大模型项目实战
学以致用 ,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。

五、大模型面试题
面试不仅是技术的较量,更需要充分的准备。
在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

391

被折叠的 条评论
为什么被折叠?



