本次实现的是一个具备任务分配、入侵者检测与攻击、自主巡逻功能的智能无人机可视化平台,采用多线程机制保证无人机、任务、入侵者的并发运行。整个项目共包含7个核心类,下面逐类进行详细解析。
1. Drone 类(无人机核心实体)
该类是无人机的实体定义,封装了无人机的位置、速度、尺寸、状态等属性,同时提供了绘制、移动、状态修改的核心方法。
java
package duoxiancheng.xq0129.dronev4;
import java.awt.*;
/**
* @author xuqiang
* @date 2026/1/22 16:07
* @description 无人机实体类,封装属性与核心行为(绘制、移动)
*/
public class Drone {
int x,y; // 无人机坐标(左上角)
int speedx,speedy; // 横、纵方向速度
int size; // 无人机主体尺寸
int state; // 无人机状态(0=巡逻,1=攻击/任务执行,2=补充弹药)
int stateSize; // 无人机状态指示灯尺寸
int scanSize; // 无人机雷达扫描范围尺寸
// 构造方法:初始化无人机核心属性,默认赋值尺寸相关常量
public Drone(int x,int y,int state,int speedx,int speedy){
this.x=x;
this.y=y;
this.state=state;
this.speedx=speedx;
this.speedy=speedy;
this.size=30; // 无人机主体固定尺寸30
this.stateSize=15; // 状态指示灯固定尺寸15
this.scanSize=100; // 雷达扫描范围固定尺寸100(圆形)
}
// 绘制无人机:雷达→主体→状态指示灯,分层绘制实现可视化
public void drawDrone(Graphics bg) {
// 1. 绘制半透明蓝色雷达扫描范围(第四个参数60是透明度,实现半透效果)
Color radarColor = new Color(0, 0, 255, 60);
bg.setColor(radarColor);
bg.fillOval(x, y, scanSize, scanSize);
// 2. 绘制无人机绿色主体(偏移35像素,让主体位于雷达中心)
Color bodyColor = new Color(64, 195, 66);
bg.setColor(bodyColor);
bg.fillOval(x + 35, y + 35, size, size);
// 3. 绘制状态指示灯,根据state切换颜色(核心:状态与颜色绑定)
Color stateColor;
switch (state) {
case 1: // 攻击状态/任务执行状态 - 红色
stateColor = Color.RED;
break;
case 0: // 巡逻状态 - 黄色
stateColor = Color.YELLOW;
break;
case 2: // 补充弹药状态 - 灰色
stateColor = Color.GRAY;
break;
default: // 默认巡逻状态,防止异常状态无显示
stateColor = Color.YELLOW;
break;
}
bg.setColor(stateColor);
bg.fillOval(x + 42, y + 42, stateSize, stateSize); // 偏移42像素,让指示灯位于主体中心
}
// 无人机移动方法:边界检测→位置修正→坐标更新,防止卡墙
public void move() {
// 1. 先判断边界,反转速度(左右边界200~1000,上下边界175~775)
boolean hitX = false;
boolean hitY = false;
if (x < 200 || (x + scanSize) > 1000) { // 雷达右边界不超过1000,避免超出红色区域
speedx = -speedx; // 碰到左右边界,横向速度反转
hitX = true;
}
if (y < 175 || (y + scanSize) > 775) { // 雷达下边界不超过775,避免超出红色区域
speedy = -speedy; // 碰到上下边界,纵向速度反转
hitY = true;
}
// 2. 如果碰到了边界,先修正位置再移动,避免卡墙(核心:边界修正逻辑)
if (hitX) {
x = Math.max(200, Math.min(1000 - scanSize, x)); // 强制将x限制在有效区间内
}
if (hitY) {
y = Math.max(175, Math.min(775 - scanSize, y)); // 强制将y限制在有效区间内
}
// 3. 更新坐标,实现移动
x += speedx;
y += speedy;
}
// 新增:方便外部修改无人机状态的方法(提供状态设置入口,解耦外部调用)
public void setState(int state) {
this.state = state;
}
// 新增:获取当前状态的方法(提供状态查询入口,支持外部逻辑判断)
public int getState() {
return this.state;
}
}
Drone 类关键点
- 属性封装:包含位置(x/y)、速度(speedx/speedy)、尺寸(size/scanSize)、状态(state)三大类核心属性,尺寸相关属性在构造方法中默认赋值,保证一致性。
- 分层绘制 :按照「雷达→主体→状态指示灯」的层级绘制,雷达设置半透明效果,状态指示灯根据
state值切换颜色,实现状态可视化区分。 - 安全移动 :包含边界检测、位置修正、坐标更新三步逻辑,
Math.max()与Math.min()结合避免无人机卡墙,提升运行流畅性。 - 状态访问器 :提供
setState()和getState()方法,封装state属性的读写,符合面向对象封装原则,方便外部类(如TaskThread)进行状态控制。 - 坐标偏移:无人机主体和指示灯通过坐标偏移实现居中显示,让可视化效果更规整。
2. Intruder 类(入侵者核心实体)
该类是入侵者的实体定义,封装了入侵者的位置、速度、尺寸、血量等属性,提供绘制和移动方法,同时支持血量可视化与死亡判定。
java
package duoxiancheng.xq0129.dronev4;
import java.awt.*;
/**
* @author xuqiang
* @date 2026/1/22 16:31
* @description 入侵者实体类,封装属性与核心行为(绘制、移动、血量管理)
*/
public class Intruder {
int x,y; // 入侵者坐标(左上角)
int speedx,speedy; // 横、纵方向速度
int size; // 入侵者主体尺寸
int blood; // 入侵者血量(100为满血,≤0为死亡)
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=45; // 入侵者主体固定尺寸45,不依赖传入参数
this.blood=100; // 满血初始化为100
}
// 绘制入侵者:主体→血条,死亡后不进行绘制(核心:血量判定与可视化)
public void drawIntruder(Graphics g){
if(blood <= 0){ // 血量≤0判定为死亡,不绘制任何内容
return;
}
// 1. 绘制入侵者黑色主体
g.setColor(Color.BLACK);
g.fillOval(x,y,size,size);
// 2. 绘制红色边框,增强辨识度
g.setColor(Color.RED);
g.drawOval(x-1,y-1,size+2,size+2);
// 3. 绘制血条背景(红色)
g.setColor(Color.RED);
g.fillRect(x,y+size+5,size,6);
// 4. 绘制当前血量(绿色),按比例计算血条宽度(核心:血量比例换算)
int bloodWidth = (int)((blood/100.0)*size); // 满血对应血条宽度=入侵者尺寸
g.setColor(Color.GREEN);
g.fillRect(x,y+size+5,bloodWidth,6);
}
// 入侵者移动方法:死亡后停止移动,边界检测后速度反转
public void move(){
if(blood <= 0){ // 死亡后不再执行移动逻辑,节省资源
return;
}
// 边界检测:整体窗口范围(5~1200,25~950),碰到边界反转速度
if(x < 5 || (x+size+5) > 1200){
speedx = -speedx;
}
if(y < 25 || (y+size+5) > 950){
speedy = -speedy;
}
// 更新坐标,实现移动
x += speedx;
y += speedy;
}
}
Intruder 类关键点
- 血量机制 :初始血量为100,
blood≤0时判定为死亡,停止绘制和移动,减少无效计算。 - 血条可视化 :采用「红色背景+绿色当前血量」的双层血条设计,通过
(blood/100.0)*size实现血量与血条宽度的比例换算,直观展示入侵者存活状态。 - 独立边界 :入侵者的移动边界为整个窗口(51200,25950),与无人机的有效区域(2001000,175775)区分,符合业务逻辑。
- 固定尺寸 :入侵者主体尺寸固定为45,构造方法中忽略传入的
size参数,保证所有入侵者可视化效果一致。 - 边框增强:在主体外围绘制红色边框,提升入侵者在窗口中的辨识度,方便观察无人机与入侵者的交互。
3. Task 类(任务核心实体)
该类是任务的实体定义,封装了任务的位置、状态、血量等属性,提供绘制方法与属性访问器/修改器,支持任务的分配、执行与完成判定。
java
package duoxiancheng.xq0129.dronev4;
import java.awt.*;
/**
* @author xuqiang
* @date 2026/1/29 16:29
* @description 任务实体类,封装属性与绘制方法,支持任务生命周期管理
*/
public class Task {
int x; // 任务坐标(左上角)
int y; // 任务坐标(左上角)
int state; // 任务状态(0=未分配,1=已分配,2=已完成)
int blood; // 任务血量(1为初始,≤0为完成)
// 构造方法:初始化任务坐标与状态,默认血量为1
public Task(int x, int y, int state) {
this.x = x;
this.y = y;
this.state = state;
this.blood = 1; // 任务初始血量为1,扣至≤0即完成
}
// 绘制任务:完成后标记状态为2并停止绘制,未完成绘制黑色圆形
public void draw(Graphics g){
if(blood <= 0){ // 任务血量≤0判定为完成,标记状态为2并停止绘制
this.state = 2;
return;
}
// 绘制任务黑色圆形主体,尺寸40
g.setColor(Color.BLACK);
g.fillOval(x,y,40,40);
}
// 属性访问器与修改器:封装所有属性,提供外部读写入口(符合面向对象封装原则)
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 int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public int getBlood() {
return blood;
}
public void setBlood(int blood) {
this.blood = blood;
}
}
Task 类关键点
- 任务生命周期 :通过
state属性管理任务的三个状态(0=未分配、1=已分配、2=已完成),通过blood属性控制任务完成条件,形成「创建→分配→执行→完成」的完整生命周期。 - 简化完成逻辑 :任务初始血量为1,
blood≤0时自动标记为已完成(state=2),停止绘制,逻辑简洁高效。 - 完整访问器 :为所有属性提供
getXXX()和setXXX()方法,封装属性读写,方便TaskThread进行任务状态与血量的修改和查询。 - 固定可视化:未完成的任务绘制为40尺寸的黑色圆形,样式统一,方便无人机识别与追踪。
- 坐标绑定:任务坐标通过鼠标点击传入,限定在无人机有效区域内,保证任务的可执行性。
4. DroneUI 类(窗口界面核心,程序入口)
该类是整个平台的窗口界面载体,基于Swing的JFrame实现,负责初始化窗口、创建组件、管理集合、绑定监听器与启动多线程,是程序的入口与核心调度者。
java
package duoxiancheng.xq0129.dronev4;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
/**
* @author xuqiang
* @date 2026/1/22 18:53
* @description 窗口界面类,程序入口,负责界面初始化、组件绑定与线程启动
*/
public class DroneUI extends JFrame {
// 三大核心集合:管理所有无人机、入侵者、任务(全局共享,供多线程访问)
ArrayList<Drone> droneList = new ArrayList<>();
ArrayList<Intruder> intruderList = new ArrayList<>();
ArrayList<Task> taskList = new ArrayList<>();// 任务集合,存储所有创建的任务
public DroneUI(){
// 1. 窗口基础配置(标题、尺寸、关闭方式、居中显示)
setTitle("智能无人机平台");
setSize(1200,1000);
setDefaultCloseOperation(EXIT_ON_CLOSE); // 关闭窗口时退出整个程序
setLocationRelativeTo(null); // 窗口居中显示
// 2. 底部按钮面板创建(存放生产无人机、入侵者按钮)
JPanel btnPanel = new JPanel();
btnPanel.setBackground(Color.LIGHT_GRAY);
JButton createDroneBtn = new JButton("生产无人机");
btnPanel.add(createDroneBtn);
JButton createIntryderBtn = new JButton("生产入侵者");
btnPanel.add(createIntryderBtn);
// 3. 面板布局:按钮面板放在窗口底部(BorderLayout.SOUTH)
add(btnPanel,BorderLayout.SOUTH);
setVisible(true); // 显示窗口
Graphics g = this.getGraphics(); // 获取窗口绘图上下文,供线程绘制使用
// 4. 多线程创建:无人机线程(负责绘制与交互)、任务线程(负责任务分配与执行)
DroneThread dt = new DroneThread(g);
TaskThread tpt = new TaskThread();// 任务线程,处理任务相关逻辑
// 5. 监听器创建与绑定:绑定按钮事件与鼠标点击事件
DroneListener droneL = new DroneListener();
droneL.taskList = taskList;// 给监听器注入任务集合,支持鼠标创建任务
createDroneBtn.addActionListener(droneL); // 绑定「生产无人机」按钮点击事件
createIntryderBtn.addActionListener(droneL); // 绑定「生产入侵者」按钮点击事件
this.addMouseListener(droneL);// 绑定窗口鼠标点击事件,支持创建任务
// 6. 集合注入:将全局集合注入到监听器与线程中,实现数据共享(核心:多线程数据共享)
droneL.droneList = droneList;
dt.droneList = droneList;
droneL.intruderList = intruderList;
dt.intruderList = intruderList;
dt.taskList = taskList;
tpt.droneList = droneList;// 任务线程注入无人机集合
tpt.taskList = taskList;// 任务线程注入任务集合
// 7. 启动多线程:开始执行无人机逻辑与任务逻辑
dt.start();
tpt.start();// 启动任务线程
}
// 重写paint方法:调用父类paint方法,保证窗口重绘时的基础渲染(避免窗口闪烁)
public void paint(Graphics g){
super.paint(g);
}
// 程序主方法:入口函数,创建DroneUI实例启动程序
public static void main(String[] args){
new DroneUI();
}
}
DroneUI 类关键点
- 全局集合管理 :创建
droneList、intruderList、taskList三个ArrayList集合,用于存储所有无人机、入侵者、任务,为多线程数据共享提供载体。 - 界面布局 :采用
BorderLayout布局,底部创建灰色按钮面板,存放「生产无人机」和「生产入侵者」两个功能按钮,界面简洁清晰。 - 多线程调度 :创建
DroneThread(无人机线程)和TaskThread(任务线程),并完成集合注入,最终调用start()方法启动线程,实现并发逻辑。 - 监听器绑定 :创建
DroneListener监听器,绑定按钮点击事件与鼠标点击事件,同时注入全局集合,实现「生产实体」与「创建任务」的功能触发。 - 窗口基础配置 :设置窗口标题、尺寸、关闭方式与居中显示,获取窗口绘图上下文供线程使用,重写
paint()方法保证窗口重绘稳定性。 - 程序入口 :
main()方法中直接创建DroneUI实例,启动整个平台,无需额外配置,运行便捷。
5. DroneListener 类(事件监听器,处理用户交互)
该类实现了ActionListener与MouseListener接口,负责处理用户的按钮点击事件(生产无人机、入侵者)与鼠标点击事件(创建任务),是用户与程序的交互桥梁。
java
package duoxiancheng.xq0129.dronev4;
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;
/**
* @author xuqiang
* @date 2026/1/22 16:32
* @description 事件监听器类,处理按钮点击与鼠标点击事件,实现用户交互
*/
public class DroneListener implements ActionListener, MouseListener {
ArrayList<Drone> droneList; // 无人机集合,接收外部注入
ArrayList<Intruder> intruderList; // 入侵者集合,接收外部注入
ArrayList<Task> taskList; // 任务集合,接收外部注入
Random random = new Random(); // 随机数生成器,用于生成随机坐标与速度
@Override
public void actionPerformed(ActionEvent e) {
String ac = e.getActionCommand(); // 获取按钮点击命令文本
if(ac.equals("生产无人机")){
// 1. 生成无人机随机坐标:限定在无人机有效区域(200~900,175~675)
int x = 200+random.nextInt(700);
int y = 175+random.nextInt(500);
// 2. 生成随机速度(-2~2)
int speedx = random.nextInt(5)-2;
int speedy = random.nextInt(5)-2;
// 3. 保证速度非0:避免无人机静止不动(核心:防止无效无人机)
while (true){
if(speedx != 0 || speedy != 0){
break;
}
speedx = random.nextInt(5)-2;
speedy = random.nextInt(5)-2;
}
// 4. 创建无人机实例,加入无人机集合(初始状态0=巡逻)
Drone drone = new Drone(x,y,0,speedx,speedy);
droneList.add(drone);
}else if(ac.equals("生产入侵者")){
// 1. 生成入侵者随机坐标:窗口全局范围
int x = random.nextInt(1150)+5;
int y = random.nextInt(879)+25;
int intruderSize = 45;
// 2. 保证入侵者不在无人机有效区域内:避免初始就被无人机攻击(核心:业务逻辑隔离)
while (true){
if(x + intruderSize <= 200 || x>=1000 || y+intruderSize <= 175 || y>=775){
break;
}
x = random.nextInt(1150)+5;
y = random.nextInt(879)+25;
}
// 3. 生成随机速度(-2~2)
int speedx = random.nextInt(5)-2;
int speedy = random.nextInt(5)-2;
// 4. 保证速度非0:避免入侵者静止不动
while (true) {
if (speedx != 0 || speedy != 0) {
break;
}
speedx = random.nextInt(5) - 2;
speedy = random.nextInt(5) - 2;
}
// 5. 创建入侵者实例,加入入侵者集合
Intruder itd = new Intruder(x,y,speedx,speedy,intruderSize);
intruderList.add(itd);
}
}
// 鼠标点击事件:未实现(本次使用鼠标按下事件创建任务)
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {// 鼠标按下事件:创建任务(核心:任务创建逻辑)
int x = e.getX(); // 获取鼠标点击横坐标
int y = e.getY(); // 获取鼠标点击纵坐标
// 1. 限定任务创建区域:无人机有效区域内,避免无效任务
if (x >= 200 && x <= 1000 - 40 && y >= 175 && y <= 775 - 40) {
// 2. 创建未分配状态(state=0)的任务,与业务逻辑一致
Task task = new Task(x,y,0);
taskList.add(task);
System.out.println("生成任务:(" + x + "," + y + ")"); // 控制台打印,方便调试
}
}
// 鼠标释放事件:未实现
@Override
public void mouseReleased(MouseEvent e) {
}
// 鼠标进入窗口事件:未实现
@Override
public void mouseEntered(MouseEvent e) {
}
// 鼠标退出窗口事件:未实现
@Override
public void mouseExited(MouseEvent e) {
}
}
DroneListener 类关键点
- 双接口实现 :同时实现
ActionListener(处理按钮事件)和MouseListener(处理鼠标事件),统一管理用户交互,简化代码结构。 - 无人机生产逻辑 :随机生成有效区域内的坐标与非0速度,初始状态为巡逻(
state=0),创建后加入droneList集合,保证无人机可被线程调度。 - 入侵者生产逻辑 :随机生成全局坐标,且保证初始不在无人机有效区域内,生成非0速度,创建后加入
intruderList集合,实现业务逻辑隔离。 - 任务创建逻辑 :通过
mousePressed()事件触发,限定在无人机有效区域内创建未分配任务(state=0),控制台打印调试信息,方便追踪任务创建情况。 - 非0速度保证 :通过
while循环过滤速度全为0的情况,避免无人机或入侵者静止不动,保证程序运行的有效性。 - 区域限定:所有实体的创建都做了区域限定,避免无效实体创建,提升程序的稳定性与业务合理性。
6. DroneThread 类(无人机核心线程,处理绘制、移动与交互)
该类是核心业务线程,继承Thread类,负责无人机、入侵者、任务的绘制,无人机与入侵者的交互,无人机碰撞检测,以及画面的刷新,是程序可视化与业务交互的核心。
java
package duoxiancheng.xq0129.dronev4;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
/**
* @author xuqiang
* @date 2026/1/22 18:53
* @description 无人机核心线程,负责绘制、移动、交互与画面刷新
*/
public class DroneThread extends Thread{
ArrayList<Drone> droneList; // 无人机集合,接收外部注入
ArrayList<Intruder> intruderList; // 入侵者集合,接收外部注入
ArrayList<Task> taskList;// 任务集合,接收外部注入
Graphics g; // 窗口绘图上下文,用于最终画面绘制
// 构造方法:传入窗口绘图上下文
public DroneThread(Graphics g){
this.g=g;
}
public void run(){
// 无限循环:保证线程持续运行,实现实时刷新
while (true) {
// 1. 创建缓冲图片:双缓冲技术,避免窗口闪烁(核心:解决界面闪烁问题)
BufferedImage img = new BufferedImage(1200,950,2);
Graphics bg = img.getGraphics();
// 2. 绘制背景与有效区域:白色背景+红色有效区域边框
bg.setColor(Color.WHITE);
bg.fillRect(0,0,1200,950);
bg.setColor(Color.RED);
bg.drawRect(200,175,800,600);
// 3. 绘制并移动所有无人机
for (int j = 0; j < droneList.size(); j++) {
Drone drone = droneList.get(j);
drone.drawDrone(bg);
drone.move();
}
// 4. 绘制所有任务
for (int i = 0; i < taskList.size(); i++) {
Task t = taskList.get(i);
t.draw(bg);
}// 任务绘制,与无人机绘制分离,逻辑清晰
// 5. 绘制并移动所有入侵者
for (int i = 0; i < intruderList.size(); i++) {
Intruder intruder = intruderList.get(i);
intruder.drawIntruder(bg);
intruder.move();
}
// 6. 无人机雷达扫描入侵者:检测到后调整方向并切换攻击状态(核心:无人机与入侵者交互逻辑)
if(droneList.size()>0){
for (int k = 0; k < droneList.size(); k++) {
Drone drone = droneList.get(k);
// 遍历无人机雷达范围内的所有像素点
for (int i = drone.x; i < drone.x+ drone.scanSize ; i++) {
for(int j = drone.y;j < drone.y + drone.scanSize;j++) {
// 限定在有效区域内,避免无效扫描
if(i<=1000 && i>=200 && j<=775 && j>=175) {
int colorNum = img.getRGB(i, j);
Color c = new Color(colorNum);
// 检测黑色像素(入侵者主体),判定为扫描到入侵者
if((c.getRed()+c.getBlue()+c.getGreen())/3 < 10){
// 遍历入侵者,确认扫描到的有效入侵者(满血)
for (int l = 0; l < intruderList.size(); l++) {
Intruder itr = intruderList.get(l);
if(itr.blood > 0 && i<itr.x+itr.size && i>=itr.x && j<itr.y+itr.size && j>= itr.y){
// 计算无人机到入侵者的方向向量
int dx = itr.x - drone.x;
int dy = itr.y - drone.y;
double distance = Math.sqrt(dx*dx + dy*dy);
if (distance > 0) {
// 归一化方向向量,再乘以固定速度3,调整无人机移动方向
drone.speedx = (int) (dx / distance * 3);
drone.speedy = (int) (dy / distance * 3);
// 巡逻状态切换为攻击状态
if (drone.getState() == 0) {
drone.setState(1);
}
}
break; // 找到对应入侵者后跳出循环,提升效率
}
}
}
}
}
}
}
}
// 7. 无人机状态优先级更新:任务>入侵者>巡逻(核心:状态优先级逻辑)
for (Drone d : droneList) {// 遍历所有无人机,更新状态
// 第一步:判断是否有未完成的已分配任务(优先级最高)
boolean hasUnfinishedTask = false;
for (Task task : taskList) {
if (task.getState() == 1 && task.getBlood() > 0) {
int disToTask = (int) Math.sqrt((task.getX() - d.x) * (task.getX() - d.x) + (task.getY() - d.y) * (task.getY() - d.y));
if (disToTask <= 125) { // 任务追踪范围125像素
hasUnfinishedTask = true;
break;
}
}
}
// 第二步:如果没有任务,再判断是否有有效入侵者
boolean hasValidIntruder = false;
if (!hasUnfinishedTask) {
for (Intruder intruder : intruderList) {
if (intruder.blood > 0) {
int dis = (int) Math.sqrt((d.x - intruder.x) * (d.x - intruder.x) + (d.y - intruder.y) * (d.y - intruder.y));
if (dis <= 100) { // 入侵者检测范围100像素
hasValidIntruder = true;
break;
}
}
}
}
// 第三步:根据优先级更新状态
if (hasUnfinishedTask) {
d.setState(1); // 保留任务执行状态
} else if (hasValidIntruder) {
d.setState(1); // 无任务,有入侵者,进入攻击状态
} else {
d.setState(0); // 无任务无入侵者,恢复巡逻状态
}
}// 状态更新逻辑结束
// 8. 入侵者扣血逻辑:被攻击状态无人机扫描到后扣血(核心:入侵者血量消耗逻辑)
for (int i = 0; i < intruderList.size(); i++) {
Intruder intruder = intruderList.get(i);
if (intruder.blood <= 0){
continue;
}
boolean flag = false;
// 遍历入侵者主体像素点,检测是否被无人机扫描
for (int j = intruder.x; j < intruder.x+45 ; j++) {
for (int k = intruder.y; k < intruder.y+45 ; k++) {
int colorNum = img.getRGB(j,k);
Color c = new Color(colorNum);
int gray = (c.getBlue()+c.getRed()+c.getGreen())/3;
// 检测无人机绿色主体像素,判定为被无人机扫描
if(gray<200 && gray>0 && c.getRed()<150){
flag = true;
break;
}
}
if(flag){
break;
}
}
if(flag && intruder.blood > 0){
// 确认有攻击状态的无人机在攻击范围内
boolean isAttacking = false;
for (Drone d : droneList) {
if (d.getState() == 1) {
int dis = (int) Math.sqrt((d.x - intruder.x) * (d.x - intruder.x) + (d.y - intruder.y) * (d.y - intruder.y));
if (dis <= 100) { // 攻击范围100像素内
isAttacking = true;
break;
}
}
}
if(isAttacking){
intruder.blood--; // 每帧扣1血,实现血量持续消耗
}
}
}
// 9. 无人机碰撞检测:避免无人机重叠(核心:碰撞检测与分离逻辑)
if (droneList.size() > 1) {
for (int i = 0; i < droneList.size(); i++) {
Drone d1 = droneList.get(i);
for (int j = i + 1; j < droneList.size(); j++) {
Drone d2 = droneList.get(j);
// 判定是否碰撞(距离<50)
if (Math.abs(d1.x - d2.x) < 50 && Math.abs(d1.y - d2.y) < 50) {
// 轻微推开:每次只移1,避免碰撞后弹开幅度过大
d1.x += d1.x > d2.x ? 1 : -1;
d1.y += d1.y > d2.y ? 1 : -1;
d2.x -= d1.x > d2.x ? 1 : -1;
d2.y -= d1.y > d2.y ? 1 : -1;
// 边界保护:推开后仍限定在有效区域内
d1.x = Math.max(200, Math.min(1000 - 100, d1.x));
d1.y = Math.max(175, Math.min(775 - 100, d1.y));
d2.x = Math.max(200, Math.min(1000 - 100, d2.x));
d2.y = Math.max(175, Math.min(775 - 100, d2.y));
}
}
}
}
// 10. 绘制缓冲图片到窗口,实现画面刷新
g.drawImage(img,0,0,null);
try {
Thread.sleep(1); // 线程休眠1毫秒,控制刷新帧率,减少资源消耗
}catch (InterruptedException e){
throw new RuntimeException(e);
}
}
}
}
DroneThread 类关键点
- 双缓冲技术 :创建
BufferedImage作为缓冲画布,先在缓冲画布上完成所有绘制,再一次性绘制到窗口,彻底解决界面闪烁问题,提升可视化流畅度。 - 分层绘制逻辑:按照「背景→无人机→任务→入侵者」的顺序绘制,逻辑清晰,避免绘制覆盖导致的显示异常。
- 雷达扫描交互:通过遍历雷达范围内的像素点,检测入侵者的黑色主体,计算方向向量调整无人机移动方向,同时切换攻击状态,实现无人机对入侵者的自动追踪与攻击。
- 状态优先级:遵循「任务>入侵者>巡逻」的状态优先级,保证无人机优先执行任务,再处理入侵者,最后恢复巡逻,符合业务逻辑。
- 入侵者扣血:检测到无人机绿色主体后,确认攻击状态无人机在攻击范围内,实现入侵者血量持续消耗,直到死亡。
- 碰撞检测与分离:检测无人机之间的距离,碰撞后进行轻微推开,并做边界保护,避免无人机重叠与卡墙,提升运行稳定性。
- 无限循环与休眠 :通过
while(true)保证线程持续运行,Thread.sleep(1)控制刷新帧率,平衡流畅度与资源消耗。
7. TaskThread 类(任务核心线程,处理任务分配与执行)
该类是任务专属线程,继承Thread类,负责任务的自动分配(给最近的巡逻无人机)、无人机对任务的追踪、任务完成判定与无人机状态恢复,是任务生命周期的核心调度者。
java
package duoxiancheng.xq0129.dronev4;
import java.util.ArrayList;
/**
* @author xuqiang
* @date 2026/1/29 16:34
* @description 任务核心线程,负责任务分配、追踪与完成判定
*/
public class TaskThread extends Thread {
ArrayList<Drone> droneList; // 无人机集合,接收外部注入
ArrayList<Task> taskList; // 任务集合,接收外部注入
public void run() {
// 无限循环:持续处理任务相关逻辑
while (true) {
try {
Thread.sleep(30); // 休眠30毫秒,降低任务调度频率,减少资源消耗
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// 1. 任务自动分配:将未分配任务(state=0)分配给最近的巡逻无人机(核心:任务分配逻辑)
for (int i = 0; i < taskList.size(); i++) {
Task t = taskList.get(i);
if (t.getState() == 0) { // 只处理未分配的任务
int min = 1000; // 初始化最小距离为1000(大于最大有效距离)
int index = -1; // 初始化目标无人机索引为-1(无有效无人机)
// 遍历所有无人机,寻找最近的巡逻状态无人机(state=0)
for (int j = 0; j < droneList.size(); j++) {
Drone d = droneList.get(j);
// 只选择巡逻状态的无人机,不干扰攻击/补给状态的无人机(核心:任务分配约束)
if (d.getState() == 0) {
int dis = (int) Math.sqrt((t.getX() - d.x) * (t.getX() - d.x) + (t.getY() - d.y) * (t.getY() - d.y));
if (dis < min) {
min = dis;
index = j;
}
}
}
// 找到可用无人机后,分配任务并设置追踪速度
if (index != -1) {
Drone drone = droneList.get(index);
// 标记任务为已分配(state=1)、无人机为攻击/任务执行状态(state=1)
t.setState(1);
drone.setState(1);
int dx = t.getX() - drone.x;
int dy = t.getY() - drone.y;
double distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// 1. 先计算原始的x/y方向速度(未强转,保留小数)
double rawSpeedX = (dx / distance) * 3;
double rawSpeedY = (dy / distance) * 3;
// 2. 独立处理x方向速度:绝对值<1则强制设±1,否则正常强转(核心:解决单一方向卡壳)
if (Math.abs(rawSpeedX) < 1) {
drone.speedx = dx > 0 ? 1 : (dx < 0 ? -1 : 0);
} else {
drone.speedx = (int) rawSpeedX;
}
// 3. 独立处理y方向速度:和x方向逻辑完全一致,彻底解决单一方向卡壳
if (Math.abs(rawSpeedY) < 1) {
drone.speedy = dy > 0 ? 1 : (dy < 0 ? -1 : 0);
} else {
drone.speedy = (int) rawSpeedY;
}
} else {
// 距离为0,已抵达目标,速度置0
drone.speedx = 0;
drone.speedy = 0;
}
}
}
}
// 2. 任务完成判定:无人机抵达任务区域后扣减任务血量,完成后恢复无人机巡逻状态(核心:任务完成逻辑)
if (taskList.size() > 0) {
for (int i = 0; i < droneList.size(); i++) {
Drone d = droneList.get(i);
if (d.getState() == 1) { // 只处理攻击/任务执行状态无人机
Task targetTask = null;
int min = 1000;
// 第一步:找到当前无人机最近的、已分配的任务(专属目标)
for (int j = 0; j < taskList.size(); j++) {
Task t = taskList.get(j);
if (t.getState() == 1) {
int dx = t.getX() - d.x;
int dy = t.getY() - d.y;
int dis = (int) Math.sqrt(dx * dx + dy * dy);
if (dis < min) {
min = dis;
targetTask = t;
}
}
}
// 第二步:只处理专属目标,判断是否抵达并扣血
if (targetTask != null) {
int droneCenterX = d.x + d.scanSize / 2; // 无人机中心坐标(雷达中心)
int droneCenterY = d.y + d.scanSize/ 2;
int targetCenterX = targetTask.getX() + 20; // 任务中心坐标
int targetCenterY = targetTask.getY() + 20;
// 计算圆心距离的平方(避免开方,提升性能)
double dx = droneCenterX - targetCenterX;
double dy = droneCenterY - targetCenterY;
double distanceSquard = dx * dx + dy * dy;
// 雷达半径50 + 目标半径20,平方后为70*70=4900(攻击范围判定)
boolean inAttackRange = distanceSquard <= 4900;
if (inAttackRange) {
d.speedx = 0;
d.speedy = 0; // 抵达任务区域后停止移动
targetTask.setBlood(targetTask.getBlood() - 1); // 扣减任务血量
// 任务血量为0,标记完成并恢复无人机巡逻状态
if (targetTask.getBlood() <= 0) {
targetTask.setState(2);
d.setState(0);
// 重置巡逻随机速度,确保非0(与生产无人机时逻辑一致)
do {
d.speedx = (int) (Math.random() * 5 - 2);
d.speedy = (int) (Math.random() * 5 - 2);
} while (d.speedx == 0 && d.speedy == 0);
}
}
}
}
}
}
}
}
}
TaskThread 类关键点
- 任务自动分配 :只将未分配任务(
state=0)分配给最近的巡逻无人机(state=0),不干扰其他状态的无人机,保证分配的合理性与高效性。 - 防卡壳速度计算:独立处理x、y方向速度,绝对值<1时强制设为±1,解决无人机在单一方向上无法移动的卡壳问题,提升任务追踪的流畅性。
- 专属目标追踪:为每个无人机匹配最近的已分配任务作为专属目标,避免多无人机争抢同一个任务,提升任务执行效率。
- 高效距离判定:使用圆心距离的平方进行攻击范围判定,避免开方运算,提升程序运行性能。
- 任务完成与状态恢复 :任务完成后,自动将无人机状态恢复为巡逻(
state=0),并重置随机非0速度,让无人机回归正常巡逻,形成任务执行的闭环。 - 低频率调度:线程休眠30毫秒,降低任务调度频率,在保证任务响应性的同时,减少系统资源消耗。
总结
- 技术亮点:双缓冲技术解决界面闪烁、状态优先级保证业务逻辑、防卡壳速度计算提升流畅性、碰撞检测避免实体重叠。
- 关键业务闭环:(各实体生命周期完整)