智能无人机防空平台 V2.0 ——攻击反制

引言

在之前的V1、V2版本中,该平台可动态生成我方无人机敌方入侵者 ,两者均具备自主移动能力,并能通过像素级扫描互相发现与攻击。V3版本在之前版本基础上优化了边界处理、速度随机生成逻辑,并完善了双向扫描机制(无人机扫描入侵者并跟随,入侵者扫描无人机并扣除生命值)。


项目结构

类名 类型 职责
Drone 实体类 表示我方无人机,包含位置、速度、扫描范围等属性,提供绘制与移动方法。
Intruder 实体类 表示敌方入侵者,包含位置、速度、生命值等属性,提供绘制与移动方法。
DroneUI 界面类 继承JFrame,搭建主窗口、按钮面板,并初始化共享数据列表及线程。
DroneListener 监听器类 实现ActionListener,响应按钮点击事件,随机生成无人机或入侵者对象并加入列表。
DroneThread 线程类 继承Thread,在run()中循环刷新图像,执行所有对象的绘制、移动及双向扫描逻辑。

数据共享:DroneUI中维护两个ArrayList分别存储无人机和入侵者对象,通过引用传递给DroneListenerDroneThread,实现多线程间的数据共享。


项目更新具体实现(聚焦V3版本新增功能)

1.事件监听器:DroneListener

复制代码
package 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<Intruder> intruderList;
    ArrayList<Drone> droneList=new ArrayList<>();
    Random random=new Random();

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("Drones Production")){
            int x= random.nextInt(700)+200;
            int y= random.nextInt(500)+175;
            int speedx;
            do {
                speedx = random.nextInt(5) - 2;
            } while (speedx == 0);
            int speedy;
            do {
                speedy = random.nextInt(5) - 2;
            } while (speedy == 0);
            Drone drone=new Drone(x,y,speedx,speedy,0);
            droneList.add(drone);
        } else if (e.getActionCommand().equals("Intruder Production")) {
            int x= random.nextInt(950)+50;
            int y= random.nextInt(800)+50;
            while (true){
                if (x<200 || x>1000 || y<175 || y>775) {
                    break;
                }
                x= random.nextInt(950)+50;
                y= random.nextInt(800)+50;
            }
            int speedx;
            do {
                speedx = random.nextInt(5) - 2;
            } while (speedx == 0);
            int speedy;
            do {
                speedy = random.nextInt(5) - 2;
            } while (speedy == 0);
            Intruder intruder=new Intruder(x,y,speedx,speedy,45,100);
            intruderList.add(intruder);
        }
    }
}

更新解析:

  • 生成无人机 :坐标范围在红色边界框内(x:200~900,y:175~675),使用nextInt(700)+200nextInt(500)+175确保。速度通过do-while保证非零(-2,-1,1,2),避免静止对象。

  • 生成入侵者 :坐标范围全屏(50~1000,x:50~1000,y:50~850),但要求必须位于红色边界框之外 (即x<200或x>1000或y<175或y>775)。使用while(true)循环不断生成直到满足条件。速度同样保证非零。2.

2.核心线程:DroneThread

复制代码
package Dronev3;

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

public class DroneThread extends Thread{

    ArrayList<Drone> droneList;
    ArrayList<Intruder> intruderList;
    Graphics g;

    public DroneThread(Graphics g){
        this.g=g;
    }

    public void run() {
        while (true) {
            BufferedImage image = new BufferedImage(1200, 950, 2);
            Graphics bg = image.getGraphics();
            bg.setColor(Color.WHITE);
            bg.fillRect(0, 0, 1200, 950);
            bg.setColor(Color.RED);
            bg.drawRect(200, 175, 800, 600);

            // 遍历无人机数组,调用无人机的绘制方法
            for (int j = 0; j < droneList.size(); j++) {
                droneList.get(j).drawDrone(bg);
                droneList.get(j).moveDrone();
            }
            // 遍历入侵者数组,调用入侵者的绘制方法
            for (int j = 0; j < intruderList.size(); j++) {
                intruderList.get(j).drawIntruder(bg);
                intruderList.get(j).moveIntruder();
            }

            // 无人机扫描入侵者:每个无人机扫描自己周围区域
            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++) {
                            int colorNum = image.getRGB(i, j);
                            Color color = new Color(colorNum);
                            // 灰度值小于10,认为是入侵者(黑色)
                            if ((color.getRed() + color.getGreen() + color.getBlue()) / 3 < 10) {
                                for (int l = 0; l < intruderList.size(); l++) {
                                    Intruder intruder = intruderList.get(l);
                                    if (i < intruder.x + intruder.size && i >= intruder.x
                                            && j >= intruder.y && j < intruder.y + intruder.size) {
                                        drone.speedx = intruder.speedx;
                                        drone.speedy = intruder.speedy;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // 入侵者扫描无人机:每个活着的入侵者扫描周围区域,检测到无人机则扣血
            for (int i = 0; i < intruderList.size(); i++) {
                System.out.println("入侵者进入检测");
                Intruder intruder = intruderList.get(i);
                if (intruder.HP <= 0) {
                    continue;
                }
                for (int j = intruder.x - 15; j < intruder.x + 70; j++) {
                    boolean flag = false;
                    for (int k = intruder.y - 15; k < intruder.y + 70; k++) {
                        int colorNum = image.getRGB(j, k);
                        Color color = new Color(colorNum);
                        int gray = (color.getRed() + color.getGreen() + color.getBlue()) / 3;
                        // 灰度值在30~150之间且红色分量<100,认为是无人机(紫色)
                        if (gray > 30 && gray < 150 && color.getRed() < 100) {
                            intruder.HP -= 1;
                            System.out.println("入侵者被检测到~" + intruder.HP);
                            flag = true;
                            break;
                        }
                    }
                    if (flag) {
                        break;
                    }
                }
            }

            g.drawImage(image, 0, 0, null);

            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
  • 无人机扫描(改进后)

    • 遍历所有无人机(for (int k = 0; k < droneList.size(); k++)),实现多机同时扫描。

    • 扫描区域:从drone.xdrone.x+scanSizedrone.ydrone.y+scanSize

    • 遍历区域内每个像素,计算灰度值,若小于10(接近黑色),则认为是入侵者的黑色像素。

    • 进一步通过坐标判断该像素是否落在某个入侵者的矩形内(入侵者绘制为黑色圆形,但检测时用矩形包围盒),若匹配,则将该无人机的速度设置为该入侵者的速度,实现"跟随"。

  • 入侵者扫描(改进后)

    • 遍历每个活着的入侵者(HP>0)。

    • 扫描范围:从intruder.x-15intruder.x+70intruder.y-15intruder.y+70(约比自身大一圈)。

    • 遍历像素,计算灰度值,若满足gray>30 && gray<150 && color.getRed()<100,则认为检测到无人机(紫色机体RGB约(94,20,223),灰度约112,红色分量小),入侵者HP减1。

    • 一旦检测到,立即跳出循环(避免同一帧多次扣血)。


项目更新涉及知识点

1.入侵者存储与攻击机制

1.1 入侵者的存储方式

入侵者对象的集合在 DroneUI 中初始化:

复制代码
ArrayList<Intruder> intruderList = new ArrayList<>();

随后通过引用传递注入到 DroneThread

复制代码
dt.intruderList = intruderList;

DroneThread 中,使用成员变量持有该引用:

复制代码
ArrayList<Intruder> intruderList;

存储特点:

  • 使用 ArrayList 作为容器,支持动态增删。

  • 该列表被两个线程共享:DroneThread(读取/修改入侵者 HP)和 DroneListener(添加新入侵者)。由于未加同步锁,存在并发修改风险。

  • 每个 Intruder 对象包含坐标、速度、大小、HP 等属性,其中 HP 是攻击机制的核心指标。

1.2 无人机扫描入侵者:发现与追踪

1.2.1 扫描循环结构
复制代码
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++) {
                // 像素检测...
            }
        }
    }
}
  • 外层循环:遍历所有无人机。

  • 内层双重循环 :遍历当前无人机扫描区域内的每个像素(scanSize = 100,即 100×100 像素区域)。

1.2.2 像素级判定逻辑
复制代码
int colorNum = image.getRGB(i, j);
Color color = new Color(colorNum);
if ((color.getRed() + color.getGreen() + color.getBlue()) / 3 < 10) {
    // 认为是入侵者(黑色)
    for (int l = 0; l < intruderList.size(); l++) {
        Intruder intruder = intruderList.get(l);
        if (i < intruder.x + intruder.size && i >= intruder.x
                && j >= intruder.y && j < intruder.y + intruder.size) {
            drone.speedx = intruder.speedx;
            drone.speedy = intruder.speedy;
            break;
        }
    }
}

判定依据

  • 入侵者绘制为纯黑色(Color.BLACK),其 RGB 均为 0,灰度值 = 0。代码取阈值 < 10

  • 一旦发现黑色像素,再通过坐标范围判断该像素是否落在某个入侵者的矩形包围盒 内(intruder.xintruder.x+sizey 同理)。

攻击效果

  • 将无人机的速度设置为入侵者的速度,从而实现"跟随"。这并非直接扣血,而是模拟锁定并追踪目标。

1.3 无人机扫描入侵者:扣血攻击

1.3.1 扫描循环结构
复制代码
for (int i = 0; i < intruderList.size(); i++) {
    Intruder intruder = intruderList.get(i);
    if (intruder.HP <= 0) {
        continue;
    }
    for (int j = intruder.x - 15; j < intruder.x + 70; j++) {
        boolean flag = false;
        for (int k = intruder.y - 15; k < intruder.y + 70; k++) {
            // 像素检测...
        }
        if (flag) break;
    }
}
  • 外层循环:遍历所有入侵者。

  • 健康检查 :跳过已死亡(HP <= 0)的入侵者。

  • 扫描区域 :从 x-15x+70y-15y+70。入侵者自身大小为 45,该区域比自身略大(左右各扩大约 15 像素),用于检测靠近的无人机。

1.3.2 像素级判定逻辑
复制代码
int colorNum = image.getRGB(j, k);
Color color = new Color(colorNum);
int gray = (color.getRed() + color.getGreen() + color.getBlue()) / 3;
if (gray > 30 && gray < 150 && color.getRed() < 100) {
    intruder.HP -= 1;
    System.out.println("入侵者被检测到~" + intruder.HP);
    flag = true;
    break;
}

判定依据

  • 无人机机体颜色为紫色 (94,20,223),计算其灰度 ≈ (94+20+223)/3 ≈ 112,红色分量 94 < 100。

  • 因此阈值设为 gray > 30 && gray < 150 && color.getRed() < 100,能够匹配紫色区域,同时排除背景白色(灰度 255)和红色边框(红色分量 255)。

攻击效果

  • 入侵者每被检测到一次,HP 减 1。

  • HP 初始为 100,归零后不再绘制和移动,视为被摧毁。


项目运行展示


项目开发阻碍

1.程序运行一段时间后崩溃,报数组越界异常

现象程序运行几分钟,或频繁点击生成按钮后直接崩溃,控制台报ArrayIndexOutOfBoundsException。

根本原因

  1. 多线程并发修改集合:EDT 线程(监听器)往ArrayList里 add 对象,子线程在遍历ArrayList,导致并发修改异常或数组越界
  2. 调用image.getRGB(i,j)时,i 或 j 超出了BufferedImage的 1200x950 范围,导致数组越界
  3. 用 fori 循环遍历集合时,集合中的元素被移除,导致索引超出集合当前长度

解决方案

修改扫描区域、图像边界、无人机移动范围、入侵者移动范围,通过画图计算,不让扫描区域超出图像边界。

(AI提供解决方案:

  1. 对集合的操作加锁,或使用线程安全的集合CopyOnWriteArrayList,避免并发修改问题
  2. 调用getRGB()前,先判断 i 和 j 是否在图片尺寸范围内,超出则直接跳过
  3. 遍历集合时使用迭代器Iterator,或倒序遍历,避免增删元素导致的索引越界)

后续改进方向

1.完善智能对抗策略

  1. 实现需求文档中定义的定点清除移动目标拦截两种对抗模式,针对固定目标和移动目标采用不同的追踪策略
  2. 加入移动目标位置预测,根据入侵者的当前速度和位置,预测下一帧的坐标,提前进行拦截,而非单纯的速度同步
  3. 实现广播机制任务分配机制,让所有无人机共享入侵者信息,每个无人机同一时间只锁定一个目标,避免资源浪费,实现多无人机协同围剿
  4. 加入无人机优先级策略,优先拦截距离防守区最近的入侵者,提升防御效果

2.性能与检测逻辑优化

  1. 优化扫描检测逻辑,采用矩形粗筛 + 像素精检的方式,先判断边界是否相交,再执行像素检测,大大减少循环次数,降低 CPU 占用
  2. 优化颜色识别逻辑,采用特定颜色通道区分目标,提升检测准确率,避免背景干扰
  3. 优化双缓冲逻辑,复用BufferedImage对象,避免每一帧都创建新的对象,减少 GC 压力

3.玩法与 UI 交互扩展

  1. 加入可视化的血量条、得分系统、击杀数统计,提升交互体验
  2. 加入难度等级系统,随着游戏时间增加,入侵者的数量、速度、血量逐步提升,增加游戏挑战性
  3. 加入暂停、继续、重置游戏、调整难度的按钮,完善游戏的基础功能
  4. 给无人机和入侵者加入等级系统,不同等级的无人机有不同的扫描范围、移动速度、攻击力
  5. 加入音效系统,扫描到目标、击杀入侵者时播放对应音效,提升游戏沉浸感
相关推荐
LiPing1223352 小时前
unity3d游戏-VR无人机拆卸
游戏·无人机·vr
AI科技星2 小时前
v=c空间光速螺旋量子几何归一化统一场论——全维度ω、r、f推导G与c的终极关联及严格证明
开发语言·opencv·r语言
IT枫斗者2 小时前
CentOS 7 一键部署 K8s 1.23 + Rancher 2.7 完整指南
java·linux·spring boot·后端·kubernetes·centos·rancher
格林威2 小时前
工业相机图像高速存储(C#版):先存内存,后批量转存方法,附 Basler 相机实战代码!
开发语言·人工智能·数码相机·计算机视觉·c#·视觉检测·工业相机
Predestination王瀞潞2 小时前
SQL 片段的提取与复用机制
java·sql·mybatis
㱘郳2 小时前
Python开发 Django和DRF框架 推荐部分B站视频
开发语言·python·django
IMPYLH2 小时前
Lua 的 UTF-8 模块
开发语言·笔记·后端·游戏引擎·lua
brucelee1862 小时前
芋道 Spring Boot 框架 + AWS S3 图片上传显示
java·开发语言·数据库