跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaAIjava算法

智能仿真无人机平台多线程实现:任务分配与碰撞规避

综述由AI生成智能仿真无人机平台基于 Java Swing 构建,采用多线程机制实现无人机、入侵者与任务的并发运行。核心功能包括自主巡逻、入侵者检测攻击及任务自动分配。通过双缓冲技术优化渲染性能,利用像素扫描实现雷达探测与碰撞规避,结合状态优先级逻辑确保任务执行效率。代码涵盖七大核心类,完整展示了实体生命周期管理与交互逻辑。

PgDevote发布于 2026/4/10更新于 2026/5/2319 浏览

本次实现的是一个具备任务分配、入侵者检测与攻击、自主巡逻功能的智能无人机可视化平台,采用多线程机制保证无人机、任务、入侵者的并发运行。整个项目共包含 7 个核心类,下面逐类进行详细解析。

1. Drone 类(无人机核心实体)

该类是无人机的实体定义,封装了无人机的位置、速度、尺寸、状态等属性,同时提供了绘制、移动、状态修改的核心方法。

package duoxiancheng.xq0129.dronev4;
import java.awt.*;

/**
 * @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 类关键点
  1. 属性封装:包含位置(x/y)、速度(speedx/speedy)、尺寸(size/scanSize)、状态(state)三大类核心属性,尺寸相关属性在构造方法中默认赋值,保证一致性。
  2. 分层绘制:按照「雷达→主体→状态指示灯」的层级绘制,雷达设置半透明效果,状态指示灯根据 state 值切换颜色,实现状态可视化区分。
  3. 安全移动:包含边界检测、位置修正、坐标更新三步逻辑,Math.max() 与 Math.min() 结合避免无人机卡墙,提升运行流畅性。
  4. 状态访问器:提供 setState() 和 getState() 方法,封装 state 属性的读写,符合面向对象封装原则,方便外部类(如 TaskThread)进行状态控制。
  5. 坐标偏移:无人机主体和指示灯通过坐标偏移实现居中显示,让可视化效果更规整。

2. Intruder 类(入侵者核心实体)

该类是入侵者的实体定义,封装了入侵者的位置、速度、尺寸、血量等属性,提供绘制和移动方法,同时支持血量可视化与死亡判定。

package duoxiancheng.xq0129.dronev4;
import java.awt.*;

/**
 * @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 类关键点
  1. 血量机制:初始血量为 100,blood≤0 时判定为死亡,停止绘制和移动,减少无效计算。
  2. 血条可视化:采用「红色背景 + 绿色当前血量」的双层血条设计,通过 (blood/100.0)*size 实现血量与血条宽度的比例换算,直观展示入侵者存活状态。
  3. 独立边界:入侵者的移动边界为整个窗口(51200,25950),与无人机的有效区域(2001000,175775)区分,符合业务逻辑。
  4. 固定尺寸:入侵者主体尺寸固定为 45,构造方法中忽略传入的 size 参数,保证所有入侵者可视化效果一致。
  5. 边框增强:在主体外围绘制红色边框,提升入侵者在窗口中的辨识度,方便观察无人机与入侵者的交互。

3. Task 类(任务核心实体)

该类是任务的实体定义,封装了任务的位置、状态、血量等属性,提供绘制方法与属性访问器/修改器,支持任务的分配、执行与完成判定。

package duoxiancheng.xq0129.dronev4;
import java.awt.*;

/**
 * @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 类关键点
  1. 任务生命周期:通过 state 属性管理任务的三个状态(0=未分配、1=已分配、2=已完成),通过 blood 属性控制任务完成条件,形成「创建→分配→执行→完成」的完整生命周期。
  2. 简化完成逻辑:任务初始血量为 1,blood≤0 时自动标记为已完成(state=2),停止绘制,逻辑简洁高效。
  3. 完整访问器:为所有属性提供 getXXX() 和 setXXX() 方法,封装属性读写,方便 TaskThread 进行任务状态与血量的修改和查询。
  4. 固定可视化:未完成的任务绘制为 40 尺寸的黑色圆形,样式统一,方便无人机识别与追踪。
  5. 坐标绑定:任务坐标通过鼠标点击传入,限定在无人机有效区域内,保证任务的可执行性。

4. DroneUI 类(窗口界面核心,程序入口)

该类是整个平台的窗口界面载体,基于 Swing 的 JFrame 实现,负责初始化窗口、创建组件、管理集合、绑定监听器与启动多线程,是程序的入口与核心调度者。

package duoxiancheng.xq0129.dronev4;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;

/**
 * @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 类关键点
  1. 全局集合管理:创建 droneList、intruderList、taskList 三个 ArrayList 集合,用于存储所有无人机、入侵者、任务,为多线程数据共享提供载体。
  2. 界面布局:采用 BorderLayout 布局,底部创建灰色按钮面板,存放「生产无人机」和「生产入侵者」两个功能按钮,界面简洁清晰。
  3. 多线程调度:创建 DroneThread(无人机线程)和 TaskThread(任务线程),并完成集合注入,最终调用 start() 方法启动线程,实现并发逻辑。
  4. 监听器绑定:创建 DroneListener 监听器,绑定按钮点击事件与鼠标点击事件,同时注入全局集合,实现「生产实体」与「创建任务」的功能触发。
  5. 窗口基础配置:设置窗口标题、尺寸、关闭方式与居中显示,获取窗口绘图上下文供线程使用,重写 paint() 方法保证窗口重绘稳定性。
  6. 程序入口:main() 方法中直接创建 DroneUI 实例,启动整个平台,无需额外配置,运行便捷。

5. DroneListener 类(事件监听器,处理用户交互)

该类实现了 ActionListener 与 MouseListener 接口,负责处理用户的按钮点击事件(生产无人机、入侵者)与鼠标点击事件(创建任务),是用户与程序的交互桥梁。

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;

/**
 * @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 类关键点
  1. 双接口实现:同时实现 ActionListener(处理按钮事件)和 MouseListener(处理鼠标事件),统一管理用户交互,简化代码结构。
  2. 无人机生产逻辑:随机生成有效区域内的坐标与非 0 速度,初始状态为巡逻(state=0),创建后加入 droneList 集合,保证无人机可被线程调度。
  3. 入侵者生产逻辑:随机生成全局坐标,且保证初始不在无人机有效区域内,生成非 0 速度,创建后加入 intruderList 集合,实现业务逻辑隔离。
  4. 任务创建逻辑:通过 mousePressed() 事件触发,限定在无人机有效区域内创建未分配任务(state=0),控制台打印调试信息,方便追踪任务创建情况。
  5. 非 0 速度保证:通过 while 循环过滤速度全为 0 的情况,避免无人机或入侵者静止不动,保证程序运行的有效性。
  6. 区域限定:所有实体的创建都做了区域限定,避免无效实体创建,提升程序的稳定性与业务合理性。

6. DroneThread 类(无人机核心线程,处理绘制、移动与交互)

该类是核心业务线程,继承 Thread 类,负责无人机、入侵者、任务的绘制,无人机与入侵者的交互,无人机碰撞检测,以及画面的刷新,是程序可视化与业务交互的核心。

package duoxiancheng.xq0129.dronev4;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

/**
 * @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 类关键点
  1. 双缓冲技术:创建 BufferedImage 作为缓冲画布,先在缓冲画布上完成所有绘制,再一次性绘制到窗口,彻底解决界面闪烁问题,提升可视化流畅度。
  2. 分层绘制逻辑:按照「背景→无人机→任务→入侵者」的顺序绘制,逻辑清晰,避免绘制覆盖导致的显示异常。
  3. 雷达扫描交互:通过遍历雷达范围内的像素点,检测入侵者的黑色主体,计算方向向量调整无人机移动方向,同时切换攻击状态,实现无人机对入侵者的自动追踪与攻击。
  4. 状态优先级:遵循「任务>入侵者>巡逻」的状态优先级,保证无人机优先执行任务,再处理入侵者,最后恢复巡逻,符合业务逻辑。
  5. 入侵者扣血:检测到无人机绿色主体后,确认攻击状态无人机在攻击范围内,实现入侵者血量持续消耗,直到死亡。
  6. 碰撞检测与分离:检测无人机之间的距离,碰撞后进行轻微推开,并做边界保护,避免无人机重叠与卡墙,提升运行稳定性。
  7. 无限循环与休眠:通过 while(true) 保证线程持续运行,Thread.sleep(1) 控制刷新帧率,平衡流畅度与资源消耗。

7. TaskThread 类(任务核心线程,处理任务分配与执行)

该类是任务专属线程,继承 Thread 类,负责任务的自动分配(给最近的巡逻无人机)、无人机对任务的追踪、任务完成判定与无人机状态恢复,是任务生命周期的核心调度者。

package duoxiancheng.xq0129.dronev4;
import java.util.ArrayList;

/**
 * @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 类关键点
  1. 任务自动分配:只将未分配任务(state=0)分配给最近的巡逻无人机(state=0),不干扰其他状态的无人机,保证分配的合理性与高效性。
  2. 防卡壳速度计算:独立处理 x、y 方向速度,绝对值<1 时强制设为±1,解决无人机在单一方向上无法移动的卡壳问题,提升任务追踪的流畅性。
  3. 专属目标追踪:为每个无人机匹配最近的已分配任务作为专属目标,避免多无人机争抢同一个任务,提升任务执行效率。
  4. 高效距离判定:使用圆心距离的平方进行攻击范围判定,避免开方运算,提升程序运行性能。
  5. 任务完成与状态恢复:任务完成后,自动将无人机状态恢复为巡逻(state=0),并重置随机非 0 速度,让无人机回归正常巡逻,形成任务执行的闭环。
  6. 低频率调度:线程休眠 30 毫秒,降低任务调度频率,在保证任务响应性的同时,减少系统资源消耗。
总结
  1. 技术亮点:双缓冲技术解决界面闪烁、状态优先级保证业务逻辑、防卡壳速度计算提升流畅性、碰撞检测避免实体重叠。
  2. 关键业务闭环:
    • 无人机【巡逻→任务/入侵者响应→执行→恢复巡逻】
    • 任务【创建→分配→执行→完成】
    • 入侵者【创建→被攻击→死亡】

目录

  1. 1. Drone 类(无人机核心实体)
  2. Drone 类关键点
  3. 2. Intruder 类(入侵者核心实体)
  4. Intruder 类关键点
  5. 3. Task 类(任务核心实体)
  6. Task 类关键点
  7. 4. DroneUI 类(窗口界面核心,程序入口)
  8. DroneUI 类关键点
  9. 5. DroneListener 类(事件监听器,处理用户交互)
  10. DroneListener 类关键点
  11. 6. DroneThread 类(无人机核心线程,处理绘制、移动与交互)
  12. DroneThread 类关键点
  13. 7. TaskThread 类(任务核心线程,处理任务分配与执行)
  14. TaskThread 类关键点
  15. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • LlamaFactory v0.9.4 发布:支持正交微调与多模态模型升级
  • 思源黑体 NotoSansSC-Regular.otf 介绍与核心特点
  • 基于 ChatGLM-6B 的医疗领域大模型微调实战指南
  • GitHub Copilot Agent 模式配置与使用技巧
  • 基于昇腾 Atlas 部署 llama.cpp 实战
  • MATLAB 智能代码生成工具 Copilot_AI 功能介绍
  • 基于 Vue3 的大文件分片加密与断点续传实现方案
  • 算法与数据结构:并查集(Union-Find)
  • 六大核心芯片 MCU/SOC/DSP/FPGA/NPU/GPU 区别与应用解析
  • Docker Compose 多服务部署:日志集中管理实战方案(基础与进阶)
  • Cute_Animal_For_Kids_Qwen_Image 儿童专属 AI 绘画工具使用指南
  • 基于 Node.js 的 Claude AI 本地环境配置指南
  • 旋转矩阵、齐次变换矩阵、欧拉角与四元数相互转换 C++ Python 实现
  • Obsidian Skills 官方实战指南:从入门到精通
  • Flutter 三方库 flutter_dropzone 的鸿蒙化适配指南
  • OpenClaw 技术解析:让大模型从对话走向执行
  • C++ 手写线程池全流程:核心设计、线程安全与死锁解析
  • Python 第三方库 Pandas Timestamp 类及属性用法精讲
  • Openclaw 结合飞书多机器人配置实战指南
  • OpenCode 开源 AI 编程助手使用指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online