在Java GUI开发领域,多线程协同和实时模拟是极具挑战性的课题。本文将带您从零开始构建一个完整的智能无人机仿真系统,通过多线程技术实现无人机与入侵者的动态交互、智能攻击和状态管理,打造一个具备实战模拟能力的智能无人机平台。
目录
[1.1 项目目标](#1.1 项目目标)
[1.2 核心技术架构](#1.2 核心技术架构)
[2.1 Drone类:无人机实体建模](#2.1 Drone类:无人机实体建模)
[2.2 Intruder类:入侵者实体建模](#2.2 Intruder类:入侵者实体建模)
[2.3 DroneThread类:多线程渲染引擎](#2.3 DroneThread类:多线程渲染引擎)
[2.4 Dronelistener类:事件响应控制器](#2.4 Dronelistener类:事件响应控制器)
[2.5 DroneUI类:主界面与线程管理](#2.5 DroneUI类:主界面与线程管理)
[3.1 线程分工与协作](#3.1 线程分工与协作)
[3.2 线程同步与数据安全](#3.2 线程同步与数据安全)
[3.3 攻击冷却机制](#3.3 攻击冷却机制)
[4.1 Drone](#4.1 Drone)
[4.2 Dronelistener](#4.2 Dronelistener)
[4.3 DroneThread](#4.3 DroneThread)
[4.4 DroneUI](#4.4 DroneUI)
[4.5 Intruder](#4.5 Intruder)
[4.6 Task](#4.6 Task)
[4.7 TaskProThread](#4.7 TaskProThread)
[5.1 项目技术成就总结](#5.1 项目技术成就总结)
[5.1.1 多线程架构的理解与应用](#5.1.1 多线程架构的理解与应用)
[5.1.2 面向对象设计能力提升](#5.1.2 面向对象设计能力提升)
[5.1.3 图形界面开发能力](#5.1.3 图形界面开发能力)
[5.2 对初学者的价值与启示](#5.2 对初学者的价值与启示)
[5.2.1 从理论到实践的跨越](#5.2.1 从理论到实践的跨越)
[5.2.2 问题解决能力的培养](#5.2.2 问题解决能力的培养)
[5.3 未来学习方向](#5.3 未来学习方向)
[5.3.1 技术深化方向](#5.3.1 技术深化方向)
[5.3.2 项目扩展方向](#5.3.2 项目扩展方向)
一、项目概述与核心设计
1.1 项目目标
本系统旨在实现一个完整的无人机作战仿真平台,主要功能包括:
-
无人机自主巡逻:无人机在指定区域内随机巡逻,具备边界检测和方向切换
-
入侵者智能生成:随机生成入侵者,避免出现在防守区域内
-
动态攻击系统:无人机自动检测并攻击入侵者,具备完整的血量计算和伤害机制
-
多线程协同架构:使用多线程技术实现界面渲染、逻辑处理和事件响应的并发执行
-
可视化状态管理:通过颜色和图形直观展示无人机和入侵者的状态
1.2 核心技术架构
系统采用MVC(模型-视图-控制器)架构模式,将数据模型、界面显示和逻辑控制分离:
智能无人机仿真系统架构:
├── 数据模型层(Model)
│ ├── Drone.java # 无人机实体类
│ ├── Intruder.java # 入侵者实体类
│ └── Task.java # 任务实体类(保留结构)
├── 控制层(Controller)
│ ├── Dronelistener.java # 事件监听器
│ └── TaskProThread.java # 任务处理线程
├── 视图层(View)
│ ├── DroneUI.java # 主界面
│ └── DroneThread.java # 渲染线程
└── 多线程协同层
├── 主线程(UI事件)
├── 渲染线程(60FPS)
└── 逻辑处理线程(异步)
二、核心类功能详解
2.1 Drone类:无人机实体建模
Drone类是系统的核心,负责定义无人机的所有属性和行为:
java
// 无人机状态定义
int state; // 0:巡逻 1:攻击入侵者 2:处理任务
// 空间属性
int x, y; // 当前位置坐标
int size = 30; // 无人机尺寸
int scanSize = 150; // 扫描范围半径
int attackRange = 80; // 攻击范围半径
// 移动属性
int speedx, speedy; // 基础速度
int runSpeedx, runSpeedy; // 实际运行速度
// 战斗属性
int attackPower = 5; // 攻击力
Intruder targetIntruder = null; // 当前攻击目标
关键方法解析:
-
drawDrone() 方法:可视化无人机状态
-
蓝色半透明圆:扫描范围(150像素半径)
-
红色半透明圆:攻击范围(80像素半径,仅攻击时显示)
-
绿色实心圆:无人机主体(30像素直径)
-
中心小圆:状态指示灯(红=巡逻,紫=攻击,绿=任务)
-
-
move() 方法:智能移动逻辑
-
巡逻模式:按预设速度移动,边界反弹
-
攻击模式:计算与目标的向量,智能追踪
-
到达攻击范围后停止移动,准备攻击
-
-
attackTarget() 方法:攻击逻辑
-
计算与目标的欧几里得距离
-
在攻击范围内时,调用入侵者的takeDamage()方法
-
每次攻击造成5点伤害
-
2.2 Intruder类:入侵者实体建模
Intruder类定义了入侵者的属性和行为,包含完整的血量系统:
java
// 生命值系统
int maxBlood = 100; // 最大血量
int blood = 100; // 当前血量
boolean isAlive = true; // 存活状态
// 移动系统
int x, y; // 当前位置
int speedx, speedy; // 移动速度
int size = 45; // 入侵者尺寸
// 视觉系统
Color本体颜色 = Color.BLACK; // 黑色圆形主体
Color血量条背景 = Color.RED; // 红色血量背景
Color当前血量 = Color.GREEN; // 绿色当前血量
血量系统实现细节:
-
血量条绘制:在入侵者上方绘制20像素宽的血量条
-
红色背景表示最大血量
-
绿色前景按比例显示当前血量
-
显示具体数值:
当前血量/最大血量
-
java
public void takeDamage(int damage) {
if (isAlive) {
blood -= damage;
if (blood <= 0) {
blood = 0;
isAlive = false;
System.out.println("入侵者被消灭!");
}
}
}
- 移动逻辑:在屏幕边界内随机反弹移动,避免越界
2.3 DroneThread类:多线程渲染引擎
DroneThread是系统的渲染核心,以60FPS的帧率刷新界面:
java
@Override
public void run() {
while (running) {
// 1. 创建双缓冲图像
BufferedImage img = new BufferedImage(1200, 950, BufferedImage.TYPE_INT_RGB);
Graphics bg = img.getGraphics();
// 2. 清空画布并绘制背景
bg.setColor(Color.WHITE);
bg.fillRect(0, 0, 1200, 950);
// 3. 绘制防守区域(红色边框)
bg.setColor(Color.RED);
bg.drawRect(200, 175, 800, 600);
// 4. 绘制所有游戏实体
drawAllEntities(bg);
// 5. 执行战斗逻辑
performCombatLogic();
// 6. 刷新到屏幕
g.drawImage(img, 0, 0, null);
// 7. 控制帧率(16ms ≈ 60FPS)
Thread.sleep(16);
}
}
关键渲染流程:
-
双缓冲技术 :使用
BufferedImage创建离屏图像,避免画面闪烁 -
分层绘制:按照背景→静态元素→动态实体的顺序绘制
-
实时更新:每帧重新计算所有实体的位置和状态
2.4 Dronelistener类:事件响应控制器
Dronelistener实现了ActionListener和MouseListener接口,负责处理所有用户交互:
java
// 按钮事件处理
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals("生产无人机")) {
// 在防守区域内随机生成无人机
int x = random.nextInt(700) + 200; // 200-900
int y = random.nextInt(500) + 175; // 175-675
// 设置随机速度(-2~2,排除0)
int speedx = adjustSpeed(random.nextInt(5) - 2);
int speedy = adjustSpeed(random.nextInt(5) - 2);
Drone drone = new Drone(x, y, 0, speedx, speedy);
synchronized (droneList) {
droneList.add(drone);
}
}
else if (command.equals("生产入侵者")) {
// 在防守区域外随机生成入侵者
int x, y;
do {
x = random.nextInt(1200 - 205) + 60;
y = random.nextInt(950 - 205) + 60;
} while (isInDefenseArea(x, y)); // 确保不在防守区内
Intruder intruder = new Intruder(x, y,
adjustSpeed(random.nextInt(5) - 2),
adjustSpeed(random.nextInt(5) - 2),
45);
synchronized (intruderList) {
intruderList.add(intruder);
}
}
}
线程安全处理:
-
使用
synchronized关键字保护共享资源 -
避免在遍历集合时直接修改,防止
ConcurrentModificationException
2.5 DroneUI类:主界面与线程管理
DroneUI是系统的入口点,负责初始化界面和启动所有线程:
java
public class DroneUI extends JFrame {
// 共享数据容器
ArrayList<Drone> droneList = new ArrayList<>();
ArrayList<Intruder> intruderList = new ArrayList<>();
ArrayList<Task> taskList = new ArrayList<>();
// 线程引用
private DroneThread droneThread;
private TaskProThread taskProThread;
public DroneUI() {
// 1. 初始化窗口
setTitle("智能无人机平台");
setSize(1200, 1000);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
// 2. 创建控制面板
JPanel btnPanel = new JPanel();
btnPanel.setBackground(Color.LIGHT_GRAY);
JButton btnDrone = new JButton("生产无人机");
JButton btnIntruder = new JButton("生产入侵者");
btnPanel.add(btnDrone);
btnPanel.add(btnIntruder);
add(btnPanel, BorderLayout.SOUTH);
// 3. 显示窗口并等待渲染上下文就绪
setVisible(true);
try { Thread.sleep(100); } catch (InterruptedException e) {}
// 4. 初始化监听器并共享数据
Dronelistener listener = new Dronelistener();
listener.droneList = droneList;
listener.intruderList = intruderList;
listener.taskList = taskList;
// 5. 注册事件监听
btnDrone.addActionListener(listener);
btnIntruder.addActionListener(listener);
// 6. 启动渲染线程
droneThread = new DroneThread(getGraphics());
droneThread.droneList = droneList;
droneThread.intruderList = intruderList;
droneThread.taskList = taskList;
droneThread.start();
// 7. 启动任务处理线程
taskProThread = new TaskProThread();
taskProThread.droneList = droneList;
taskProThread.taskList = taskList;
taskProThread.start();
System.out.println("智能无人机平台启动完成");
}
}
三、多线程协同机制深度解析
3.1 线程分工与协作
系统采用三线程架构,各司其职:
| 线程名称 | 职责 | 运行频率 | 关键操作 |
|---|---|---|---|
| 主线程(AWT-EventQueue) | UI事件响应、组件管理 | 事件驱动 | 按钮点击、窗口操作 |
| 渲染线程(DroneThread) | 图形渲染、战斗逻辑 | 60FPS | 绘制所有实体、计算攻击 |
| 任务线程(TaskProThread) | 任务分配与处理 | 30ms间隔 | 无人机任务分配、状态更新 |
3.2 线程同步与数据安全
在多线程环境下,数据共享需要特别注意线程安全:
java
// 安全的集合遍历与修改
private void removeDeadIntruders() {
synchronized (intruderList) {
for (int i = intruderList.size() - 1; i >= 0; i--) {
if (!intruderList.get(i).isAlive()) {
intruderList.remove(i); // 倒序遍历避免索引错位
}
}
}
}
// 战斗逻辑中的同步处理
private void performCombatLogic() {
// 创建副本避免在迭代时修改原集合
ArrayList<Intruder> intruderCopy;
synchronized (intruderList) {
intruderCopy = new ArrayList<>(intruderList);
}
synchronized (droneList) {
for (Drone drone : droneList) {
// 使用副本进行距离计算
for (Intruder intruder : intruderCopy) {
// 计算距离并判断是否攻击
}
}
}
}
3.3 攻击冷却机制
为了防止攻击频率过高,系统实现了攻击冷却机制:
java
// 在DroneThread类中
private int attackCooldown = 0;
private final int ATTACK_INTERVAL = 10; // 每10帧攻击一次
// 在循环中
attackCooldown--;
if (attackCooldown <= 0) {
drone.attackTarget();
attackCooldown = ATTACK_INTERVAL; // 重置冷却
}
计算说明:假设帧率为60FPS,10帧冷却相当于约166毫秒攻击一次,平衡了游戏性和性能。
四、完整代码
4.1 Drone
java
package yky0206;
import java.awt.*;
import java.awt.*;
public class Drone {
// 属性
int x, y, speedx, speedy, size;
int tindex = -1;
int state; // 0 巡逻 1 跟随/攻击入侵者 2: 处理任务
int stateSize;
int scanSize;
int attackRange = 80; // 攻击范围
int attackPower = 5; // 每次攻击造成的伤害(从2改为5)
int fSpeedx, fSpeedy;
int runSpeedx, runSpeedy;
Intruder targetIntruder = null; // 当前攻击目标
// 构造方法
public Drone(int x, int y, int state, int speedx, int speedy) {
this.x = x;
this.y = y;
this.state = state;
this.size = 30;
this.stateSize = 15;
this.scanSize = 150; // 扩大扫描范围
this.speedy = speedy;
this.speedx = speedx;
runSpeedx = speedx;
runSpeedy = speedy;
}
public void drawDrone(Graphics bg) {
// 计算无人机的中心坐标
int centerX = x + size / 2;
int centerY = y + size / 2;
// 绘制扫描范围(半透明)- 以无人机为中心
Color color1 = new Color(0, 0, 255, 30);
bg.setColor(color1);
bg.fillOval(
centerX - scanSize / 2,
centerY - scanSize / 2,
scanSize,
scanSize
);
// 绘制攻击范围(如果正在攻击)
if (state == 1 && targetIntruder != null) {
Color attackColor = new Color(255, 0, 0, 20);
bg.setColor(attackColor);
bg.fillOval(
centerX - attackRange / 2,
centerY - attackRange / 2,
attackRange,
attackRange
);
}
// 绘制无人机主体
Color color2 = new Color(64, 195, 66);
bg.setColor(color2);
bg.fillOval(x, y, size, size); // 直接使用x,y坐标
// 绘制状态指示灯 - 在无人机中心
Color color3;
switch (state) {
case 0: // 巡逻
color3 = new Color(255, 0, 0);
break;
case 1: // 攻击
color3 = new Color(255, 0, 255);
break;
case 2: // 处理任务
color3 = new Color(0, 255, 0);
break;
default:
color3 = Color.WHITE;
}
bg.setColor(color3);
bg.fillOval(
centerX - stateSize / 2,
centerY - stateSize / 2,
stateSize,
stateSize
);
}
public void move() {
// 状态0:巡逻
if (state == 0) {
runSpeedx = speedx;
runSpeedy = speedy;
// 边界检查
if (x > 300 + 600 || x < 200) {
runSpeedx = -runSpeedx;
speedx = -speedx;
if (x < 200) {
x += size;
} else {
x -= size;
}
}
if (y > 175 + 500 || y < 175) {
runSpeedy = -runSpeedy;
speedy = -speedy;
if (y < 175) {
y += size;
} else {
y -= size;
}
}
}
// 状态1:攻击入侵者
else if (state == 1 && targetIntruder != null && targetIntruder.isAlive()) {
// 计算无人机中心
int droneCenterX = x + size/2;
int droneCenterY = y + size/2;
int intruderCenterX = targetIntruder.getCenterX();
int intruderCenterY = targetIntruder.getCenterY();
// 计算方向向量
int dx = intruderCenterX - droneCenterX;
int dy = intruderCenterY - droneCenterY;
double distance = Math.sqrt(dx * dx + dy * dy);
// 如果不在攻击范围内,就靠近目标
if (distance > attackRange) {
if (distance > 0) {
runSpeedx = (int)(dx / distance * 3);
runSpeedy = (int)(dy / distance * 3);
}
} else {
// 在攻击范围内,停止移动并攻击
runSpeedx = 0;
runSpeedy = 0;
}
}
// 移动
x += runSpeedx;
y += runSpeedy;
}
// 攻击目标
public void attackTarget() {
if (state == 1 && targetIntruder != null && targetIntruder.isAlive()) {
// 计算距离
int droneCenterX = x + size/2;
int droneCenterY = y + size/2;
int intruderCenterX = targetIntruder.getCenterX();
int intruderCenterY = targetIntruder.getCenterY();
int dx = intruderCenterX - droneCenterX;
int dy = intruderCenterY - droneCenterY;
double distance = Math.sqrt(dx * dx + dy * dy);
// 如果在攻击范围内,造成伤害
if (distance <= attackRange) {
targetIntruder.takeDamage(attackPower);
System.out.println("无人机攻击入侵者,造成 " + attackPower + " 点伤害,剩余血量: " + targetIntruder.blood);
}
}
}
// 设置攻击目标
public void setTarget(Intruder intruder) {
this.targetIntruder = intruder;
this.state = 1;
}
// 清除目标
public void clearTarget() {
this.targetIntruder = null;
this.state = 0;
this.runSpeedx = this.speedx;
this.runSpeedy = this.speedy;
}
// 检查目标是否有效
public boolean hasValidTarget() {
return targetIntruder != null && targetIntruder.isAlive();
}
// 获取无人机中心坐标(用于距离计算)
public int getCenterX() {
return x + size / 2;
}
public int getCenterY() {
return y + size / 2;
}
// 修改攻击力的方法(如果需要动态调整)
public void setAttackPower(int power) {
this.attackPower = power;
}
public int getAttackPower() {
return attackPower;
}
}
4.2 Dronelistener
java
package yky0206;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;
public class Dronelistener implements ActionListener, MouseListener {
ArrayList<Task> taskList;
ArrayList<Drone> droneList;
ArrayList<Intruder> intruderList;
Random random = new Random();
@Override
public void actionPerformed(ActionEvent e) {
String ac = e.getActionCommand();
if (ac.equals("生产无人机")) {
int x = random.nextInt(700) + 200;
int y = random.nextInt(500) + 175;
int speedx = random.nextInt(5) - 2; // -2~2
if (speedx == 0) speedx = 1;
int speedy = random.nextInt(5) - 2;
if (speedy == 0) speedy = 1;
Drone drone = new Drone(x, y, 0, speedx, speedy);
droneList.add(drone);
System.out.println("生产无人机,位置: (" + x + ", " + y + ")");
} else if (ac.equals("生产入侵者")) {
int x = random.nextInt(1200 - 205) + 60;
int y = random.nextInt(950 - 205) + 60;
// 确保不在防守区域内
while (x >= 200 && x <= 900 && y >= 175 && y <= 675) {
x = random.nextInt(1200 - 205) + 60;
y = random.nextInt(950 - 205) + 60;
}
int speedx = random.nextInt(5) - 2;
if (speedx == 0) speedx = 1;
int speedy = random.nextInt(5) - 2;
if (speedy == 0) speedy = 1;
Intruder itd = new Intruder(x, y, speedx, speedy, 45);
intruderList.add(itd);
System.out.println("生产入侵者,位置: (" + x + ", " + y + "),血量: " + itd.blood);
}
}
@Override
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
Task task = new Task(x, y, 0);
taskList.add(task);
System.out.println("生成任务,位置: (" + x + ", " + y + ")");
}
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
}
4.3 DroneThread
java
package yky0206;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
public class DroneThread extends Thread {
public ArrayList<Task> taskList;
ArrayList<Drone> droneList;
ArrayList<Intruder> intruderList;
Graphics g;
private boolean running = true;
private int attackCooldown = 0; // 攻击冷却计数器
private final int ATTACK_INTERVAL = 10; // 攻击间隔(帧数)
public DroneThread(Graphics g) {
this.g = g;
}
public void stopThread() {
running = false;
}
@Override
public void run() {
while (running) {
BufferedImage img = new BufferedImage(1200, 950, BufferedImage.TYPE_INT_RGB);
Graphics bg = img.getGraphics();
// 清空画布
bg.setColor(Color.WHITE);
bg.fillRect(0, 0, 1200, 950);
// 绘制防守区域
bg.setColor(Color.RED);
bg.drawRect(200, 175, 800, 600);
// 绘制任务
for (int i = 0; i < taskList.size(); i++) {
Task task = taskList.get(i);
task.draw(bg);
}
// 清理死亡的入侵者
for (int i = intruderList.size() - 1; i >= 0; i--) {
if (!intruderList.get(i).isAlive()) {
intruderList.remove(i);
}
}
// 绘制并移动入侵者
for (Intruder intruder : intruderList) {
intruder.drawIntruder(bg);
intruder.move();
}
// 绘制并移动无人机
for (Drone drone : droneList) {
drone.drawDrone(bg);
drone.move();
}
// 无人机检测和攻击入侵者逻辑
for (Drone drone : droneList) {
// 只有巡逻状态的无人机才会寻找新目标
if (drone.state == 0) {
Intruder nearestIntruder = null;
double minDistance = Double.MAX_VALUE;
// 寻找最近的存活入侵者
for (Intruder intruder : intruderList) {
if (intruder.isAlive()) {
// 使用无人机中心坐标计算距离
int droneCenterX = drone.getCenterX();
int droneCenterY = drone.getCenterY();
int intruderCenterX = intruder.getCenterX();
int intruderCenterY = intruder.getCenterY();
int dx = droneCenterX - intruderCenterX;
int dy = droneCenterY - intruderCenterY;
double distance = Math.sqrt(dx * dx + dy * dy);
// 如果在扫描范围内且更近
if (distance < drone.scanSize && distance < minDistance) {
minDistance = distance;
nearestIntruder = intruder;
}
}
}
// 如果找到入侵者,设置为攻击目标
if (nearestIntruder != null) {
drone.setTarget(nearestIntruder);
System.out.println("无人机锁定入侵者!距离: " + minDistance);
}
}
// 如果无人机有攻击目标
if (drone.hasValidTarget()) {
// 减少攻击冷却
attackCooldown--;
if (attackCooldown <= 0) {
drone.attackTarget();
attackCooldown = ATTACK_INTERVAL; // 重置冷却
}
} else if (drone.state == 1) {
// 目标已死亡或无效,清除目标
drone.clearTarget();
System.out.println("无人机目标丢失,返回巡逻状态");
}
}
// 绘制到屏幕
if (g != null) {
g.drawImage(img, 0, 0, null);
}
try {
Thread.sleep(16); // 约60FPS
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
}
4.4 DroneUI
java
package yky0206;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class DroneUI extends JFrame {
ArrayList<Drone> droneList = new ArrayList<>();
ArrayList<Intruder> intruderList = new ArrayList<>();
ArrayList<Task> taskList = new ArrayList<>();
private DroneThread droneThread;
private TaskProThread taskProThread;
public DroneUI() {
setTitle("智能无人机平台");
setSize(1200, 1000);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
// 按钮面板
JPanel btnPanel = new JPanel();
btnPanel.setBackground(Color.LIGHT_GRAY);
JButton btn = new JButton("生产无人机");
btnPanel.add(btn);
JButton btn1 = new JButton("生产入侵者");
btnPanel.add(btn1);
add(btnPanel, BorderLayout.SOUTH);
setVisible(true);
// 等待窗口显示后获取Graphics
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 创建监听器
Dronelistener droneL = new Dronelistener();
// 设置共享数据
droneL.droneList = droneList;
droneL.intruderList = intruderList;
droneL.taskList = taskList;
// 注册监听器
btn.addActionListener(droneL);
btn1.addActionListener(droneL);
addMouseListener(droneL);
// 启动无人机线程
droneThread = new DroneThread(getGraphics());
droneThread.droneList = droneList;
droneThread.intruderList = intruderList;
droneThread.taskList = taskList;
droneThread.start();
// 启动任务处理线程
taskProThread = new TaskProThread();
taskProThread.droneList = droneList;
taskProThread.taskList = taskList;
taskProThread.start();
System.out.println("智能无人机平台启动完成");
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new DroneUI();
});
}
}
4.5 Intruder
java
package yky0206;
import java.awt.*;
public class Intruder {
int x, y, speedx, speedy, size;
int blood;
int maxBlood;
boolean isAlive = true;
public Intruder(int x, int y, int speedx, int speedy, int size) {
this.x = x;
this.y = y;
this.speedx = speedx;
this.speedy = speedy;
this.size = size;
this.maxBlood = 100;
this.blood = maxBlood;
}
public void drawIntruder(Graphics g) {
if (!isAlive) {
return;
}
// 绘制入侵者本体
g.setColor(Color.BLACK);
g.fillOval(x, y, size, size);
// 绘制血量条背景
g.setColor(Color.RED);
g.fillRect(x - 10, y - 20, size + 20, 8);
// 绘制当前血量
g.setColor(Color.GREEN);
int currentWidth = (int)((blood * 1.0 / maxBlood) * (size + 20));
g.fillRect(x - 10, y - 20, currentWidth, 8);
// 绘制血量数值
g.setColor(Color.BLACK);
g.setFont(new Font("宋体", Font.BOLD, 10));
g.drawString(blood + "/" + maxBlood, x + size/2 - 15, y - 10);
}
public void move() {
if (!isAlive) {
return;
}
// 边界反弹
if (x > 1200 - size - 60 || x < 60) {
speedx = -speedx;
}
if (y > 950 - size - 60 || y < 60) {
speedy = -speedy;
}
x += speedx;
y += speedy;
}
// 受到伤害
public void takeDamage(int damage) {
if (isAlive) {
blood -= damage;
if (blood <= 0) {
blood = 0;
isAlive = false;
System.out.println("入侵者被消灭!");
}
}
}
// 检查是否存活
public boolean isAlive() {
return isAlive;
}
// 获取中心坐标
public int getCenterX() {
return x + size / 2;
}
public int getCenterY() {
return y + size / 2;
}
}
4.6 Task
java
package yky0206;
import java.awt.*;
public class Task {
int x;
int y;
int state; // 0 未被分配 1 被分配 2 已完成
int blood;
public Task(int x, int y, int state) {
this.x = x;
this.state = state;
this.y = y;
blood = 10;
}
public void draw(Graphics g) {
if (blood <= 0) {
state = 2;
return;
}
g.setColor(Color.BLACK);
g.fillRect(x, y, 80, 80);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
4.7 TaskProThread
java
package yky0206;
import java.util.ArrayList;
public class TaskProThread extends Thread {
ArrayList<Drone> droneList;
ArrayList<Task> taskList;
@Override
public void run() {
while (true) {
try {
Thread.sleep(30);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// 处理未分配的任务
for (int i = 0; i < taskList.size(); i++) {
Task t = taskList.get(i);
if (t.state == 0) {
// 找到最近的空闲无人机
int min = Integer.MAX_VALUE;
int index = -1;
for (int j = 0; j < droneList.size(); j++) {
Drone d = droneList.get(j);
if (d.state == 0) { // 只有空闲无人机才考虑
// 使用无人机中心坐标计算距离
int droneCenterX = d.getCenterX();
int droneCenterY = d.getCenterY();
int taskCenterX = t.x + 40; // 任务中心(80x80的任务,中心在40,40)
int taskCenterY = t.y + 40;
int dis = (int) Math.sqrt(
(taskCenterX - droneCenterX) * (taskCenterX - droneCenterX) +
(taskCenterY - droneCenterY) * (taskCenterY - droneCenterY)
);
if (dis < min) {
min = dis;
index = j;
}
}
}
// 分配任务给最近的无人机
if (index != -1) {
Drone drone = droneList.get(index);
drone.tindex = i;
drone.state = 2; // 设为处理任务状态
t.state = 1; // 任务设为已分配
// 计算无人机飞向任务的速度
int droneCenterX = drone.getCenterX();
int droneCenterY = drone.getCenterY();
int taskCenterX = t.x + 40;
int taskCenterY = t.y + 40;
int dx = taskCenterX - droneCenterX;
int dy = taskCenterY - droneCenterY;
// 归一化速度向量
double distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
drone.runSpeedx = (int) (dx / distance * 3); // 固定速度3
drone.runSpeedy = (int) (dy / distance * 3);
}
System.out.println("分配任务给无人机,距离: " + min + ",速度: " + drone.runSpeedx + ", " + drone.runSpeedy);
}
}
}
// 检查任务完成情况
for (int i = 0; i < droneList.size(); i++) {
Drone d = droneList.get(i);
if (d.state == 2 && d.tindex < taskList.size()) {
Task t = taskList.get(d.tindex);
// 检查无人机是否到达任务区域
if (Math.abs(d.x + 15 - t.x) < 40 && Math.abs(d.y + 15 - t.y) < 40) {
d.runSpeedx = 0;
d.runSpeedy = 0;
t.blood--;
if (t.blood <= 0) {
d.tindex = -1;
d.state = 0; // 恢复空闲状态
t.state = 2; // 任务完成
System.out.println("任务完成!");
}
}
}
}
// 清理已完成的任务
for (int i = taskList.size() - 1; i >= 0; i--) {
Task t = taskList.get(i);
if (t.state == 2 && t.blood <= 0) {
taskList.remove(i);
}
}
}
}
}
五、总结与展望
5.1 项目技术成就总结
通过开发这个智能无人机仿真系统,我获得了宝贵的全栈开发经验,主要体现在以下方面:
5.1.1 多线程架构的理解与应用
系统采用三线程协同架构(UI线程、渲染线程、逻辑线程),通过实践深入理解了:
-
线程安全的重要性及
synchronized关键字的正确使用 -
如何避免常见的多线程问题
-
合理的线程分工对程序性能和响应速度的影响
5.1.2 面向对象设计能力提升
通过将系统拆分为6个核心类,我实践了面向对象设计原则:
-
Drone和Intruder类展示了如何封装实体属性和行为 -
DroneThread和TaskProThread体现了单一职责原则 -
类间通过接口和共享数据结构协作,降低了耦合度
5.1.3 图形界面开发能力
完成了一个功能完整的GUI项目:
-
掌握了Swing双缓冲技术消除画面闪烁
-
学会了通过颜色编码和图形元素提供直观状态反馈
-
理解了事件驱动编程模型及其实现方式
5.2 对初学者的价值与启示
5.2.1 从理论到实践的跨越
这个项目展示了如何将课堂上的理论知识转化为实际可运行的代码:
-
算法理论(距离计算、碰撞检测)在具体场景中的应用
-
多线程编程理论在解决实际问题时的具体实现
-
面向对象设计原则在项目架构中的体现
5.2.2 问题解决能力的培养
开发过程中遇到的诸多挑战(如线程安全问题、渲染效率问题、对象状态管理问题)都提供了宝贵的调试和问题解决经验。
5.3 未来学习方向
基于此项目,我认为可以进一步深入以下几个方向的学习:
5.3.1 技术深化方向
-
更高效的空间分区算法:学习四叉树、BSP树等数据结构,优化大规模对象的碰撞检测效率
-
高级AI算法:为无人机和入侵者实现更智能的路径规划和决策逻辑
-
性能优化技术:学习JVM性能调优、内存管理高级技巧
5.3.2 项目扩展方向
-
网络功能:实现多玩家协同作战或对抗模式
-
数据可视化:添加实时数据统计和可视化展示面板
-
配置系统:开发图形化配置界面,支持动态调整游戏参数
这个智能无人机仿真系统不仅是一个技术实践项目,更是一个学习过程的具体体现。通过从零开始构建这样一个系统,我深刻体会到理论知识如何转化为实际能力,也为未来的技术学习之路奠定了坚实基础。
