本程序在华为荣耀4A上测试可跳达3000分
工具:ADB
原理:
- 开始游戏后,使用ADB工具让手机截屏发送到电脑
- 分析图像中小人与目标中心点间的距离,根据一定比例计算出需要触屏的时间
- 使用ADB进行模拟点击(触屏)相应的时间,完成精准跳跃
程序代码:(源码未经优化)
1 import java.awt.EventQueue; 2 import java.awt.Image; 3 import java.awt.Toolkit; 4 5 import javax.swing.JFrame; 6 import javax.swing.JLabel; 7 import java.awt.BorderLayout; 8 9 import javax.imageio.ImageIO; 10 import javax.swing.ImageIcon; 11 import java.awt.event.MouseAdapter; 12 import java.awt.event.MouseEvent; 13 import java.awt.image.BufferedImage; 14 import java.io.File; 15 import java.io.IOException; 16 17 import java.awt.Color; 18 import java.awt.Graphics; 19 import java.awt.Image; 20 import java.awt.image.BufferedImage; 21 import java.io.File; 22 import java.io.IOException; 23 import java.time.Year; 24 25 import javax.imageio.ImageIO; 26 27 class Control { 28 private static int footX = 0, footY = 0; //小人底部坐标 29 private static int targetX = 0,targetY = 0; //目标方块中心坐标 30 //获取截屏 31 public static BufferedImage getScreen(){ 32 //截屏 33 try { 34 //手机截屏,存储到SD卡 35 Process process = Runtime.getRuntime().exec("adb shell screencap /sdcard/screen.png"); 36 process.waitFor(); 37 //将截图传到电脑,以便接下来的分析 38 process = Runtime.getRuntime().exec("adb pull /sdcard/screen.png screen.png"); 39 process.waitFor(); 40 } catch (IOException | InterruptedException e) { 41 //异常处理 42 e.printStackTrace(); 43 } 44 //加载文件 45 File file = new File("screen.png"); 46 if (file == null || !file.exists()) { 47 System.out.println("获取截屏失败"); 48 return null; 49 } 50 51 //加载图片 52 BufferedImage image = null; 53 try { 54 image = ImageIO.read(file); 55 } catch (IOException e) { 56 // TODO Auto-generated catch block 57 e.printStackTrace(); 58 } 59 return image; 60 } 61 62 //长按屏幕 63 public static void mouseon(int time) { 64 try { 65 Runtime.getRuntime().exec("adb shell input swipe 200 200 200 200 " + time); 66 } catch (IOException e) { 67 // TODO Auto-generated catch block 68 e.printStackTrace(); 69 } 70 } 71 72 public static double getDistance (BufferedImage image) { 73 getFoot(image); 74 getTarget(image); 75 return Math.sqrt((footX - targetX) * (footX - targetX) + (footY - targetY) * (footY - targetY)); 76 } 77 78 public static void getFoot(BufferedImage image){ 79 // BufferedImage image = getScreen(); //屏幕截图 80 Color footColor = new Color(54,60,102); //小人底部颜色 81 int top = (int)(image.getHeight() * 0.5); //扫描范围顶部(X) 82 int bottom = (int) (image.getHeight() * 0.7); //扫描范围底部(X) 83 /* 84 * 自底向上扫描小人脚下位置 85 */ 86 for(int i = bottom;i > top;i--) 87 { 88 for(int j = 0;j < image.getWidth();j++) 89 { 90 if(Math.abs(image.getRGB(j, i) - footColor.getRGB()) < 200) { 91 footX = j; 92 footY = i - 10; 93 i = top; //结束外层循环 94 System.out.println("footX:" + footX + "," + "footY:" + footY); 95 break; 96 } 97 } 98 } 99 Graphics g = image.getGraphics(); 100 g.setColor(Color.BLUE); 101 g.fillRect(footX - 5, footY - 5, 10, 10); 102 } 103 104 public static void getTarget(BufferedImage image) { 105 int top = (int)(image.getHeight() * 0.35); //扫描范围顶部 106 int bottom = (int)(image.getHeight() * 0.48); //扫描范围底部 107 Color headColor = new Color(56, 54, 71); 108 /* 109 * 自顶向下扫描目标方块顶端位置 110 */ 111 for(int i = top;i < bottom;i++) 112 { 113 Color bgColor = new Color(image.getRGB(10, i)); //取背景色 114 for(int j = 0;j < image.getWidth();j++) 115 { 116 if (j >= footX - 30 && j <= footX + 30) { 117 continue; 118 } 119 Color color = new Color(image.getRGB(j, i)); 120 //System.out.printf("背景:(%d,%d,%d),当前:(%d,%d,%d)_(%d,%d)%n",bgColor.getRed(),bgColor.getGreen(),bgColor.getBlue(),color.getRed(),color.getGreen(),color.getBlue(),j,i); 121 int t = 0; 122 t = Math.abs(bgColor.getRGB() - color.getRGB()); 123 124 //判断与背景色不同但不是小人头 125 if ((t > 200000))// && !(Math.abs(headColor.getRGB() - color.getRGB()) < 8200000)) 126 { 127 targetX = j; 128 targetY = i; 129 i = bottom; //结束外层循环 130 System.out.println("t=" + t); 131 break; 132 } 133 } 134 } 135 136 int maxLength; //方块的直径 137 int x = targetX; //行扫描起始坐标 138 int y = targetY; //直径所在行(y坐标) 139 int flag = 0; //不满足条件标志 140 for(int i = y + 1;i < y + 101 && flag < 8;i++) 141 { 142 System.out.print("i = " + i); 143 for(int j = x;j < image.getWidth();j++) 144 { 145 Color bgColor = new Color(image.getRGB(image.getWidth() - 10, i)); //取背景色 146 Color color = new Color(image.getRGB(j, i)); 147 if (( Math.abs(bgColor.getRGB() - color.getRGB())) <= 703400) { 148 149 System.out.println("j = " + j); 150 151 if (j > x) { 152 x = j; 153 targetY = i; 154 flag = 0; 155 }else { 156 flag++; 157 System.out.println("flag=" + flag); 158 } 159 break; 160 } 161 } 162 } 163 targetY = targetY - flag; 164 System.out.println("targetX:" + targetX + "," + "targetY:" + targetY); 165 Graphics g = image.getGraphics(); 166 g.setColor(Color.RED); 167 g.fillRect(targetX - 5, targetY - 5, 10, 10); 168 // g.drawLine(footX - 30,0,footX - 30,image.getHeight()); 169 // g.drawLine(footX + 30,0,footX + 30,image.getHeight()); 170 } 171 } 172 173 174 public class Skip { 175 176 private JFrame frame; 177 private JLabel lblNewLabel; 178 private BufferedImage image; 179 private int i = 0; 180 private int x = 0,y = 0; 181 /** 182 * Launch the application. 183 */ 184 public static void main(String[] args) { 185 EventQueue.invokeLater(new Runnable() { 186 public void run() { 187 try { 188 Skip window = new Skip(); 189 window.frame.setVisible(true); 190 } catch (Exception e) { 191 e.printStackTrace(); 192 } 193 } 194 }); 195 } 196 197 /** 198 * Create the application. 199 */ 200 public Skip() { 201 initialize(); 202 } 203 204 /** 205 * Initialize the contents of the frame. 206 */ 207 private void initialize() { 208 image = Control.getScreen(); 209 Control.getFoot(image); 210 Control.getTarget(image); 211 ImageIcon imageIcon = new ImageIcon(image); 212 213 frame = new JFrame(); 214 frame.setBounds(100, 0, imageIcon.getIconWidth(), imageIcon.getIconHeight()); 215 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 216 217 lblNewLabel = new JLabel("手机屏幕"); 218 lblNewLabel.addMouseListener(new MouseAdapter() { 219 @Override 220 public void mouseClicked(MouseEvent e) { 221 Thread skip = new Thread(new SkipRun()); 222 skip.start(); 223 } 224 }); 225 lblNewLabel.setIcon(imageIcon); 226 frame.getContentPane().add(lblNewLabel, BorderLayout.CENTER); 227 } 228 229 protected void skip() { 230 double distance = Control.getDistance(image); 231 System.out.println(distance); 232 Control.mouseon((int)(distance * 2.05)); 233 try { 234 ImageIO.write(image, "png", new File("debug" + i++ + ".png")); 235 } catch (IOException e) { 236 // TODO Auto-generated catch block 237 e.printStackTrace(); 238 } 239 } 240 241 class SkipRun implements Runnable{ 242 243 @Override 244 public void run() { 245 // TODO Auto-generated method stub 246 while(true) { 247 skip(); 248 try { 249 Thread.sleep(3000); 250 } catch (InterruptedException e1) { 251 // TODO Auto-generated catch block 252 e1.printStackTrace(); 253 } 254 image = Control.getScreen(); 255 lblNewLabel.setIcon(new ImageIcon(image)); 256 } 257 } 258 259 } 260 261 }