《智能仿真无人机平台(多线程V3.0)技术笔记》

一、项目概述

本项目基于Java Swing实现了一个可视化的智能无人机平台,核心功能包括无人机巡逻、入侵者生成、无人机扫描追踪入侵者、入侵者血量扣减及状态可视化等。整体架构分为5个核心类,各司其职且协同工作,实现了多线程下的图形动态渲染和逻辑交互。

二、核心类解析

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

该类封装了无人机的属性和行为,核心是无人机的绘制(含状态可视化)、移动逻辑,以及状态控制方法。

java 复制代码
package duoxiancheng.xq0127.dronev3;
import java.awt.*;

public class Drone {
    int x,y; // 无人机坐标
    int speedx,speedy; // 无人机x/y轴移动速度
    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; // 初始化状态(默认0=巡逻)
        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是透明度,0-255)
        Color radarColor = new Color(0, 0, 255, 60);
        bg.setColor(radarColor);
        bg.fillOval(x, y, scanSize, scanSize);

        // 2. 绘制无人机绿色主体圆
        Color bodyColor = new Color(64, 195, 66);
        bg.setColor(bodyColor);
        bg.fillOval(x + 35, y + 35, size, size);

        // 3. 根据状态动态设置中间圆颜色(核心可视化逻辑)
        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);
    }

    // 无人机移动逻辑:边界碰撞检测+位置修正
    public void move() {
        // 1. 标记是否碰到x/y轴边界
        boolean hitX = false;
        boolean hitY = false;
        // x轴边界:左200,右1000(扫描圈右边界)
        if (x < 200 || (x + scanSize) > 1000) {
            speedx = -speedx; // 碰到边界反转x轴速度
            hitX = true;
        }
        // y轴边界:上175,下775(扫描圈下边界)
        if (y < 175 || (y + scanSize) > 775) {
            speedy = -speedy; // 碰到边界反转y轴速度
            hitY = true;
        }

        // 2. 边界位置修正:避免无人机卡墙
        if (hitX) {
            x = Math.max(200, Math.min(1000 - scanSize, x));
        }
        if (hitY) {
            y = Math.max(175, Math.min(775 - scanSize, y));
        }

        // 3. 执行移动
        x += speedx;
        y += speedy;
    }

    // 状态设置方法:供外部修改无人机状态(核心接口)
    public void setState(int state) {
        this.state = state;
    }

    // 状态获取方法:供外部读取无人机状态,暂时未使用
    public int getState() {
        return this.state;
    }
}
关键点:
  • 状态可视化:通过switch语句将state值映射为不同颜色,实现"巡逻黄、攻击红、补充弹药灰"的视觉效果;
  • 边界碰撞:移动逻辑中先判断边界再修正位置,避免无人机卡在边界无法移动;
  • 状态控制接口:setState/getState方法实现了无人机状态的外部可控,是状态动态切换的核心。

2. DroneListener类(事件监听类)

该类实现按钮点击事件监听,负责随机生成无人机和入侵者,控制生成位置、速度的合法性。

java 复制代码
package duoxiancheng.xq0127.dronev3;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;

public class DroneListener implements ActionListener {
    ArrayList<Drone> droneList; // 无人机列表(关联UI层的列表)
    ArrayList<Intruder> intruderList; // 入侵者列表(关联UI层的列表)
    Random random = new Random(); // 随机数生成器

    @Override
    public void actionPerformed(ActionEvent e) {
        String ac = e.getActionCommand(); // 获取按钮点击指令

        if(ac.equals("生产无人机")){
            // 1. 随机生成无人机初始坐标(限定在200-900 x 175-675范围内)
            int x = 200+random.nextInt(700);
            int y = 175+random.nextInt(500);
            // 2. 随机生成移动速度(-2到2之间,避免速度为0)
            int speedx = random.nextInt(5)-2;
            int speedy = random.nextInt(5)-2;
            // 循环确保速度不为0(避免无人机静止)
            while (true){
                if(speedx != 0 || speedy != 0){
                    break;
                }
                speedx = random.nextInt(5)-2;
                speedy = random.nextInt(5)-2;
            }
            // 3. 创建无人机(默认状态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. 确保入侵者生成在指定区域外(200-1000 x 175-775区域外)
            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. 随机生成入侵者速度(避免速度为0)
            int speedx = random.nextInt(5)-2;
            int speedy = random.nextInt(5)-2;
            while (true) {
                if (speedx != 0 || speedy != 0) {
                    break;
                }
                speedx = random.nextInt(5) - 2;
                speedy = random.nextInt(5) - 2;
            }
            // 4. 创建入侵者并加入列表
            Intruder itd = new Intruder(x,y,speedx,speedy,intruderSize);
            intruderList.add(itd);
        }
    }
}
关键点:
  • 速度合法性:通过while循环确保无人机/入侵者速度不为0,避免实体静止;
  • 位置合法性:入侵者生成时限定在指定区域外,保证初始位置符合业务逻辑;
  • 事件解耦:通过监听按钮指令生成实体,将"UI操作"和"实体创建"解耦。

3. DroneThread类(核心业务线程类)

该类是后台线程,负责循环执行无人机/入侵者的绘制、移动、扫描、碰撞检测等核心逻辑,是整个程序的"驱动核心"。

【该类最重要也最复杂】

java 复制代码
package duoxiancheng.xq0127.dronev3;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

public class DroneThread extends Thread{
    ArrayList<Drone> droneList; // 无人机列表(关联UI层)
    ArrayList<Intruder> intruderList; // 入侵者列表(关联UI层)
    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 < intruderList.size(); i++) {
                Intruder intruder = intruderList.get(i);
                intruder.drawIntruder(bg); // 绘制入侵者
                intruder.move(); // 移动入侵者
            }

            // 5. 无人机扫描入侵者逻辑(核心业务)
            if(droneList.size()>0){
                for (int k = 0; k < droneList.size(); k++) {
                    Drone drone = droneList.get(k);
                    boolean foundIntruder = false; // 标记是否检测到存活入侵者

                    // 遍历无人机雷达扫描范围内的每个像素
                    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){
                                            foundIntruder = true; // 标记检测到入侵者
                                            // 计算无人机到入侵者的方向向量
                                            int dx = itr.x - drone.x;
                                            int dy = itr.y - drone.y;
                                            double distance = Math.sqrt(dx*dx + dy*dy);
                                            if (distance > 0) {
                                                // 归一化方向向量,设置无人机向入侵者移动
                                                drone.speedx = (int) (dx / distance * 3);
                                                drone.speedy = (int) (dy / distance * 3);
                                                drone.setState(1); // 切换为攻击状态
                                            }
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    // 未检测到入侵者时,恢复巡逻状态
                    if(!foundIntruder){
                        drone.setState(0);
                    }
                }
            }

            // 6. 入侵者血量扣减逻辑
            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<150 && gray>30 && c.getRed()<100){
                            flag = true;
                            break;
                        }
                    }
                    if(flag){
                        break;
                    }
                }
                // 被扫描到则扣减血量
                if(flag && intruder.blood > 0){
                    intruder.blood--;
                }
            }

            // 7. 无人机碰撞检测:避免无人机重叠
            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) {
                            // 轻微推开,避免重叠
                            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));
                        }
                    }
                }
            }

            // 8. 将缓冲图片渲染到窗口
            g.drawImage(img,0,0,null);
            // 线程休眠1ms:控制帧率,避免CPU占用过高
            try {
                Thread.sleep(1);
            }catch (InterruptedException e){
                throw new RuntimeException(e);
            }
        }
    }
}
关键点:
  • 双缓冲技术:通过BufferedImage绘制后再渲染到窗口,解决Swing绘图闪烁问题;
  • 扫描逻辑:通过像素颜色检测入侵者,实现"视觉扫描"效果,符合无人机雷达的业务逻辑;
  • 状态自动切换:通过foundIntruder标记实现"检测到入侵者→攻击态,未检测到→巡逻态"的自动切换;
  • 碰撞检测:无人机间距离过近时轻微推开,避免视觉重叠,提升交互体验;
  • 帧率控制:Thread.sleep(1)控制循环频率,平衡渲染流畅度和CPU占用。

4. DroneUI类(UI界面类)

该类是程序入口,负责创建窗口、按钮、关联列表和线程,是整个程序的"容器"。

java 复制代码
package duoxiancheng.xq0127.dronev3;

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<>(); // 入侵者列表(全局共享)
    
    public DroneUI(){
        // 1. 窗口基础设置
        setTitle("智能无人机平台"); // 窗口标题
        setSize(1200,1000); // 窗口大小
        setDefaultCloseOperation(EXIT_ON_CLOSE); // 关闭窗口退出程序
        setLocationRelativeTo(null); // 窗口居中

        // 2. 创建按钮面板(底部)
        JPanel btnPanel = new JPanel();
        btnPanel.setBackground(Color.LIGHT_GRAY); // 面板背景色

        // 3. 创建功能按钮
        JButton createDroneBtn = new JButton("生产无人机");
        btnPanel.add(createDroneBtn);
        JButton createIntryderBtn = new JButton("生产入侵者");
        btnPanel.add(createIntryderBtn);

        // 4. 布局管理:按钮面板放在窗口底部
        add(btnPanel,BorderLayout.SOUTH);
        setVisible(true); // 显示窗口
        Graphics g = this.getGraphics(); // 获取窗口绘图上下文

        // 5. 初始化线程和监听器
        DroneThread dt = new DroneThread(g); // 后台业务线程
        DroneListener droneL = new DroneListener(); // 按钮监听器

        // 6. 绑定按钮事件
        createDroneBtn.addActionListener(droneL);
        createIntryderBtn.addActionListener(droneL);

        // 7. 共享列表:将UI层的列表传递给监听器和线程(核心:数据共享)
        droneL.droneList = droneList;
        dt.droneList = droneList;
        droneL.intruderList = intruderList;
        dt.intruderList = intruderList;

        // 8. 启动后台线程
        dt.start();
    }
    
    // 重写paint方法:保留父类逻辑,确保绘图正常
    public void paint(Graphics g){
        super.paint(g);
    }

    // 程序入口
    public static void main(String[] args){
        new DroneUI();
    }
}
关键点:
  • 数据共享:通过将droneList/intruderList传递给监听器和线程,实现UI层、监听层、业务层的数据统一;
  • 布局管理:使用BorderLayout将按钮面板放在底部,符合桌面应用的交互习惯;
  • 线程启动:在UI初始化完成后启动后台线程,避免UI阻塞。

5. Intruder类(入侵者实体类)

该类封装了入侵者的属性和行为,核心是入侵者绘制(含血量条可视化)、移动逻辑。

java 复制代码
package duoxiancheng.xq0127.dronev3;
import java.awt.*;

public class Intruder {
    int x,y; // 入侵者坐标
    int speedx,speedy; // 入侵者移动速度
    int size; // 入侵者大小
    int blood; // 入侵者血量(初始100)
    
    // 构造方法:初始化入侵者属性
    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); // 黑色填充圆
        g.setColor(Color.RED);
        g.drawOval(x-1,y-1,size+2,size+2); // 红色边框

        // 2. 绘制血量条背景(红色)
        g.setColor(Color.RED);
        g.fillRect(x,y+size+5,size,6); // 位置:入侵者下方5像素,宽度=入侵者大小,高度6

        // 3. 绘制剩余血量(绿色,按比例显示)
        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){ // 血量为0时不移动
            return;
        }
        // x轴边界:左5,右1200-5
        if(x < 5 || (x+size+5) > 1200){
            speedx = -speedx; // 反转x轴速度
        }
        // y轴边界:上25,下950-5
        if(y < 25 || (y+size+5) > 950){
            speedy = -speedy; // 反转y轴速度
        }
        // 执行移动
        x += speedx;
        y += speedy;
    }
}
关键点:
  • 血量可视化:通过"红色背景+绿色比例条"实现血量条,bloodWidth按血量百分比计算,直观展示剩余血量;
  • 边界逻辑:移动时判断边界并反转速度,实现入侵者的"反弹"效果;
  • 存活判断:血量≤0时不绘制、不移动,实现"死亡"的视觉和逻辑效果。

三、核心技术总结

  1. 多线程:通过DroneThread实现后台业务逻辑与UI线程分离,避免UI阻塞;
  2. 双缓冲绘图:解决Swing动态绘图的闪烁问题,提升视觉体验;
  3. 状态可视化:通过颜色映射实现无人机状态、入侵者血量的直观展示;
  4. 碰撞检测:包含边界碰撞(无人机/入侵者)、实体碰撞(无人机间),保证交互合理性;
  5. 数据共享:通过全局列表实现多层级的数据统一,是多模块协同的核心。
相关推荐
im_AMBER2 小时前
消失的最后一秒:SSE 流式联调中的“时序竞争”
前端·笔记·学习·http·sse
shanghaichutai2 小时前
Transforming Growth Factor α (human) (TGF α (1-50) (human))
笔记
Gain_chance2 小时前
24-学习笔记尚硅谷数仓搭建-DIM层的维度表建表思路及商品表维度表的具体建表解析
数据仓库·hive·笔记·学习·datagrip
求真求知的糖葫芦2 小时前
RF and Microwave Coupled-Line Circuits射频微波耦合线电路4.2 使用均匀耦合线的方向性耦合器学习笔记(自用)
笔记·学习·线性代数·射频工程
ddxu2 小时前
AI学习笔记
笔记·学习·ai
大势智慧2 小时前
低空大师2025飞行报告
无人机·生态·低空经济·技术突破·场景应用·年度回顾·创新升级
Hammer_Hans2 小时前
DFT笔记24
笔记
铁手飞鹰2 小时前
[Linux笔记]内核裁剪
linux·笔记·linux内核裁剪
QZ_orz_freedom3 小时前
后端学习笔记-ApaChe POI
笔记·学习