智能无人机平台V3
V2版本回顾
- 回顾:在V2版本中,初步实现了将无人机与入侵者的对象进行封装,并添加了对应的按钮用来生产无人机和入侵者。同时为无人机添加了扫描机制,为入侵者添加了被扫描与扣血机制
V3版本提升
- 实现了无人机的锁敌追踪功能:在扫描到无人机后,可以改变自己的速度,持续跟踪入侵者
- 实现了无人机的“广播”功能:在一个无人机发现入侵者后,可以将结果“告知”给其他无人机,让其他“有空”的无人机围剿入侵者
- 完善了边界控制,防止出现越界问题
V3版本具体功能实现
- 无人机的锁敌追踪功能的实现:
如果该无人机扫描到入侵者,那么程序会将这个像素点拿出,并在入侵者数组中进行遍历,寻找该像素点对应的入侵者,并将该入侵者对象告知给无人机,无人机通过该入侵者的坐标、速度来进行扫描追踪。 - 无人机广播机制的实现:
创建一个动态数组,它会将这个入侵者的信息传入一个动态数组,其他没有目标的无人机可以通过访问这个数组来得知被发现的入侵者的信息并协同其他无人机来“围剿”这个入侵者。
实现过程:
-
创建ScanResult类,并将无人机scan方法的返回值设为ScanResult,便于拿到对应像素点的坐标
package com.nwu.by0127.V3; public class ScanResult{ int targetX; int targetY; public ScanResult(int targetX,int targetY) { this.targetY = targetY; this.targetX = targetX; } }public ScanResult scan(int x, int y, int size, BufferedImage img) { int distanceSquare; for (int i = x; i < x + size; i++) { for (int j = y; j < y + size; j++) { int roundx=x + scanSize / 2; int roundy=y + scanSize / 2; distanceSquare = (roundx - i) * (roundx - i) + (roundy - j) * (roundy - j); if (distanceSquare < rSquare){ int colorNum = img.getRGB(i,j); Color color = new Color(colorNum); Color targetColor1 = new Color(213, 15, 15); Color targetColor2 = new Color(0,0,0); if(isIntruderColor(color,targetColor1,20)||isIntruderColor(color,targetColor2,20)){ //System.out.println("扫描到入侵者"); ScanResult sr= new ScanResult(i,j); return sr ; } } } } return null; } -
创建动态数组
ArrayList把每个被发现的入侵者存入这个数组,并且让没有目标的无人机将该数组中的入侵者设为目标。foundedIntruders=new ArrayList<>(); if (drones.size() > 0) { for (int k = 0; k < drones.size(); k++) { Drone drone = drones.get(k); ScanResult sr=drone.scan(drone.x, drone.y, drone.scanSize, image); if (sr!=null) {//如果扫到目标 Intruder intruder = getTargetIntruder(sr.targetX,sr.targetY);//通过坐标把这个目标找出来 if (intruder!=null) {//找到目标后 foundedIntruders.add(intruder);//把这个目标传入动态数组 drone.target = intruder;//把自己的目标设置为这个 } }else{//如果没扫描到目标 if(foundedIntruders!=null){//看看动态数组里面有没有别人发现的目标 for (int i = foundedIntruders.size()-1; i>=0; i--) { Intruder intruder = foundedIntruders.get(i); if(intruder!=null){ if(intruder.blood<=0||!isInRange(intruder)){//先判断这个目标还是否存在或在范围内 foundedIntruders.remove(i);//删掉死亡的或者逃跑的 }else{ drone.target=intruder;//把自己的目标设置成这个目标 } } } } } } } -
修改Drone的move方法,让无人机锁定目标后具有追赶功能。追赶的速度计算逻辑为:先创建一个追赶的速度huntingSpeed,然后再用三角函数算出追赶速度的x,y分量。并在move方法内加入硬限位的代码防止无人机被带离守卫区,具体逻辑为:将坐标与边界进行大小比较,取出合适的坐标
int newx = x+huntingSpeedx; int newy = y+huntingSpeedy; x = Math.max(200, Math.min(1000 - scanSize, newx)); y = Math.max(100, Math.min(700 - scanSize, newy)); -
在无人机类中加入Intruder类型的target对象,用以标记当前正在追踪的入侵者目标。同时将扣血机制由原来的入侵者被扫描(通过遍历像素点)扣血,改为当它成为某一个无人机的目标后扣血
if (intruders.size() > 0) {
//如果该入侵者被某个无人机列为目标,就进行扣血
for (int k = 0; k < intruders.size(); k++) {
Intruder intruder = intruders.get(k);
for (int i = 0; i < drones.size(); i++) {
if(intruder==drones.get(i).target){
intruder.underAttack();
System.out.println("第"+k+"个入侵者被扫到,血量剩余:"+intruder.blood);
if (intruder.blood <= 0) {
intruders.remove(k);
for(Drone drone:drones){
if(drone.target==intruder){
drone.target=null;
}
}
}
}
}
}
}
V3版本全部代码
- DroneThread类
package com.nwu.by0127.V3; import java.awt.*; import java.awt.image.BufferedImage; import java.util.ArrayList; public class DroneThread extends Thread { Graphics g; ArrayList<Drone> drones; ArrayList<Intruder> intruders; ArrayList<Intruder> foundedIntruders=new ArrayList<>(); //将所有被扫描到的入侵者存入这里 public DroneThread(Graphics g) { this.g = g; } @Override public void run() { for (; ; ) { BufferedImage image = new BufferedImage(1200, 800, 2); Graphics bg = image.getGraphics(); bg.setColor(Color.white); bg.fillRect(0, 0, 1200, 800); bg.setColor(Color.red); bg.drawRect(200, 100, 800, 600); if (drones != null) { for (int i = 0; i < drones.size(); i++) { Drone drone = drones.get(i); drone.drawDrone(bg); drone.move(); } } if (intruders != null) { for (int i = 0; i < intruders.size(); i++) { Intruder intruder = intruders.get(i); intruder.drawIntruder(bg); intruder.move(); } } g.drawImage(image, 0, 0, null); if (drones.size() > 0) { for (int k = 0; k < drones.size(); k++) { Drone drone = drones.get(k); ScanResult sr=drone.scan(drone.x, drone.y, drone.scanSize, image); if (sr!=null) {//如果扫到目标 Intruder intruder = getTargetIntruder(sr.targetX,sr.targetY);//通过坐标把这个目标找出来 if (intruder!=null) {//找到目标后 foundedIntruders.add(intruder);//把这个目标传入动态数组 drone.target = intruder;//把自己的目标设置为这个 } }else{//如果没扫描到目标 if(foundedIntruders!=null){//看看动态数组里面有没有别人发现的目标 for (int i = foundedIntruders.size()-1; i>=0; i--) { Intruder intruder = foundedIntruders.get(i); if(intruder!=null){ if(intruder.blood<=0||!isInRange(intruder)){//先判断这个目标还是否存在或在范围内 foundedIntruders.remove(i);//删掉死亡的或者逃跑的 }else{ drone.target=intruder;//把自己的目标设置成这个目标 } } } } } } } if (intruders.size() > 0) { //如果该入侵者被某个无人机列为目标,就进行扣血 for (int k = 0; k < intruders.size(); k++) { Intruder intruder = intruders.get(k); for (int i = 0; i < drones.size(); i++) { if(intruder==drones.get(i).target){ intruder.underAttack(); System.out.println("第"+k+"个入侵者被扫到,血量剩余:"+intruder.blood); if (intruder.blood <= 0) { intruders.remove(k); for(Drone drone:drones){ if(drone.target==intruder){ drone.target=null; } } } } } } } try { Thread.sleep(4); } catch (InterruptedException e) { throw new RuntimeException(e); } } } public Intruder getTargetIntruder ( int scannedI, int scannedJ){ for (int k = 0; k < intruders.size(); k++) { Intruder intruder = intruders.get(k); int distanceSquare; for (int i = intruder.x; i < intruder.x + intruder.size; i++) { for (int j = intruder.y; j < intruder.y + intruder.size; j++) { int roundx=intruder.x + intruder.size / 2; int roundy=intruder.y +intruder.size / 2; distanceSquare = (roundx - i) * (roundx - i) + (roundy - j) * (roundy - j); if (distanceSquare < intruder.rSquare) { if (i == scannedI && j == scannedJ) { return intruder; } } } } } return null; } public boolean isInRange(Intruder intruder){ if(intruder.x<200+ intruder.size||intruder.x>1000-intruder.size||intruder.y<100+intruder.size||intruder.y> 700-intruder.size){ return false; }else{ return true; } } } - Drone类
package com.nwu.by0127.V3; import java.awt.*; import java.awt.image.BufferedImage; public class Drone { int x; int y; int stateSize = 16; int scanSize = 100; int size = 30; int speedx; int speedy; int huntingSpeedx; int huntingSpeedy; int rSquare=scanSize*scanSize/4; int huntingSpeed = 4;//设置追逐速度 Intruder target = null; public Drone(int x, int y, int speedx, int speedy) { this.x = x; this.y = y; this.speedx = speedx; this.speedy = speedy; } public void drawDrone(Graphics g) { Color color1 = new Color(52, 146, 241, 75); g.setColor(color1); g.fillOval(x, y, scanSize, scanSize); Color color2 = new Color(111, 200, 34); g.setColor(color2); g.fillOval(x + 35, y + 35, size, size); Color color3 = new Color(211, 39, 39); g.setColor(color3); g.fillOval(x + 42, y + 42, stateSize, stateSize); } public void move() { if(target!=null&&target.blood>0){ //先判断目标是否在守卫区外,若在守卫区外则不在追逐 if(target.x+target.size/2<200||target.x+target.size/2>900||target.y+target.size/2<100||target.y+target.size/2>600){ target=null; }else{ int dx = target.x+target.size/2-(x+scanSize/2); int dy = target.y+target.size/2-(y+scanSize/2); double distance = Math.sqrt(dx*dx+dy*dy); if(distance>20){ huntingSpeedx=(int)(dx/distance*huntingSpeed); huntingSpeedy=(int)(dy/distance*huntingSpeed); }else{ huntingSpeedx=0; huntingSpeedy=0; } //硬限位,防止出界 int newx = x+huntingSpeedx; int newy = y+huntingSpeedy; x = Math.max(200, Math.min(1000 - scanSize, newx)); y = Math.max(100, Math.min(700 - scanSize, newy)); } }else if(target==null){ x += speedx; y += speedy; if (x < 200 || x > 900) { speedx = -speedx; } if (y < 100 || y > 600) { speedy = -speedy; } } } public ScanResult scan(int x, int y, int size, BufferedImage img) { int distanceSquare; for (int i = x; i < x + size; i++) { for (int j = y; j < y + size; j++) { int roundx=x + scanSize / 2; int roundy=y + scanSize / 2; distanceSquare = (roundx - i) * (roundx - i) + (roundy - j) * (roundy - j); if (distanceSquare < rSquare){ int colorNum = img.getRGB(i,j); Color color = new Color(colorNum); Color targetColor1 = new Color(213, 15, 15); Color targetColor2 = new Color(0,0,0); if(isIntruderColor(color,targetColor1,20)||isIntruderColor(color,targetColor2,20)){ //System.out.println("扫描到入侵者"); ScanResult sr= new ScanResult(i,j); return sr ; } } } } return null; } //颜色判断方法 public boolean isIntruderColor (Color c1, Color c2, int tolerance){ return Math.abs(c1.getRed()-c2.getRed()) <= tolerance && Math.abs(c1.getGreen()-c2.getGreen()) <= tolerance && Math.abs(c1.getBlue()-c2.getBlue()) <= tolerance; } } - Intruder类
package com.nwu.by0127.V3; import java.awt.*; public class Intruder { int x; int y; int speedx; int speedy; int size=30; int blood=200; int rSquare=size*size/4; boolean beAttacked=false; public Intruder(int x, int y, int speedx, int speedy) { this.x = x; this.y = y; this.speedx = speedx; this.speedy = speedy; } public void drawIntruder(Graphics g) { if (blood>0){ Color color1 =new Color(0, 0, 0); g.setColor(color1); g.fillOval(x, y, size, size); Color color2 =new Color(213, 15, 15); g.setColor(color2); g.fillOval(x+5, y+5, size-10, size-10); } } public void move(){ x+=speedx; y+=speedy; if(x<=0||x>=1160){ speedx=-speedx; } if(y<=0||y>=760){ speedy=-speedy; } } public void underAttack(){ beAttacked=true; this.blood--; } } - DroneUI类
package com.nwu.by0127.V3; import javax.swing.*; import java.awt.*; import java.util.ArrayList; public class DroneUI extends JFrame { ArrayList<Drone> drones=new ArrayList<>(); ArrayList<Intruder> intruders=new ArrayList<>(); public DroneUI() { setTitle("智能无人机平台2.0"); setSize(1200,900); setDefaultCloseOperation(EXIT_ON_CLOSE); setLocationRelativeTo(null); JButton button1 = new JButton("生产无人机"); JButton button2 = new JButton("生产入侵者"); JPanel panel = new JPanel(); panel.setBackground(Color.lightGray); panel.add(button1); panel.add(button2); add(panel,BorderLayout.SOUTH); setVisible(true); Graphics g=this.getGraphics(); //创建按钮监听器 DroneListener droneListener = new DroneListener(); button1.addActionListener(droneListener); button2.addActionListener(droneListener); //创建无人机线程 DroneThread droneThread = new DroneThread(g); //将共享内存的数组传入到两个线程中 droneListener.drones=drones; droneThread.drones=drones; droneListener.intruders=intruders; droneThread.intruders=intruders; droneThread.start(); } @Override public void paint(Graphics g) { super.paint(g); } public static void main(String[] args) { new DroneUI(); } } - ScanResult类
package com.nwu.by0127.V3; public class ScanResult{ int targetX; int targetY; public ScanResult(int targetX,int targetY) { this.targetY = targetY; this.targetX = targetX; } } - DroneListener类
package com.nwu.by0127.V3; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Random; public class DroneListener implements ActionListener { Random rand = new Random(); ArrayList<Drone> drones; ArrayList<Intruder> intruders; @Override public void actionPerformed(ActionEvent e) { if(e.getActionCommand().equals("生产无人机")) { int x = rand.nextInt(700)+200; int y = rand.nextInt(500)+100; int speedx = rand.nextInt(5)-2; while(speedx==0) { speedx = rand.nextInt(5)-2; } int speedy = rand.nextInt(5)-2; while(speedy==0) { speedy = rand.nextInt(5)-2; } Drone drone = new Drone(x,y,speedx,speedy); drones.add(drone); }else if(e.getActionCommand().equals("生产入侵者")) { int x = rand.nextInt(1160); int y = rand.nextInt(760); while(true){ if(y<60||y>700||x<160||x>1000) { break; } x = rand.nextInt(1160); y = rand.nextInt(760); } int speedx = rand.nextInt(5)-2; while(speedx==0) { speedx = rand.nextInt(5)-2; } int speedy = rand.nextInt(5)-2; while(speedy==0) { speedy = rand.nextInt(5)-2; } Intruder intruder = new Intruder(x,y,speedx,speedy); intruders.add(intruder); } } }
代码运行截图











