##起初是想使用按键精灵脚本程序控制,但还是选择熟悉的java。我这里使用了工具,造成延迟问题。也求教:java控制安卓的正确姿势,
参考了.NET玩跳一跳,思路都是一样的,只不过使用ADB控制安卓的方式更好,博主也贴出了adb命令,解决了我一大问题。
先看效果图:
设计思路:
java识别小人和目标物,计算距离,计算时间,触发按键时长。
主要解决问题:
1、java操作安卓手机。
##本人对安卓不懂,只能使用工具了,手机连接电脑使用“手机控”软件把手机屏幕显示到电脑上,就能鼠标玩跳一跳,然后java识别小人和目标物,控制点击时长。
使用ADB发送命令操作手机。ADB版本选择1.0.32以上,才能识别安卓5.0。ADB下载地址:http://www.cr173.com/soft/205142.html
1、截图。2、上传电脑。3、退出
可以把命令写成BAT文件。
adb shell screencap -p /sdcard/1.png adb pull /sdcard/1.png E:/adb exit
2、如何识别目标。
##java截取手机屏幕部分,对图片进行像素点识别。通过像素点占百分比数,最多的为目标颜色,设计识别正方形像素点的算法。
##具体识别方法:小人颜色固定,去除背景色,识别小人位置以上像素点,去除小人底座颜色防止与目标颜色相同,计算百分比,得到目标颜色,通过目标颜色的最大最小xy坐标(颜色边界),计算出中心点,在计算出中心点与小人的距离,推算时间。使用Robot控制截图并鼠标点击.。
并没有准确的找到目标物的中心点,而是找到目标物的顶点,通过小人最底部的颜色确定小人的位置,如果使用OpenCV会更好。
3、还存在的问题:
1、小人和目标物的距离和按键时长的关系,好像是指数形式,并不是简单的直线
2、不同手机的分辨率不同,需要调整按键时长系数和始扫描行。
3、代码优化,方法全部放在了main里面了,摘出来发现有线程问题,未做优化。待解决也希望指正。
直接复制以下代码即可运行,另外需要写好的批处理文件:
package com.cyd.util; import java.awt.AWTException; import java.awt.Graphics2D; import java.awt.MouseInfo; import java.awt.Point; import java.awt.Robot; import java.awt.Transparency; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import javax.imageio.ImageIO; public class RobotT1T_2 { static String file1 = "E:\adb\1.png"; static String file2 = "E:\adb\2.png"; //始 扫描行,针对不同的手机分辨率可能不一样,需要修改 static int start_y = 300; //按键时长系数,针对不同的手机按键时长可能不一样,需要680.6258244648354的值 static final double time_out = (680.6258244648354 / 563.8129122324177); static boolean istest = false; static boolean is_qz = false; static boolean is_qz_1 = false; static boolean is_qz_2 = false; public static void main(String[] args) throws AWTException, InterruptedException, IOException { istest = true; // is_qz=true; // is_qz_1 = true; is_qz_2 = true; while (true) { System.out.println("+++++++++++++"); if (istest) { cmd_java("cmd /c start adb.bat ", "E:\adb\cofface_adb\cofface_adb_windows_v5.1");//批处理文件 } BufferedImage bi = (BufferedImage) ImageIO.read(new File(file1)); Map<String, String> map = new HashMap<String, String>(); // 获取图像的宽度和高度 int width = bi.getWidth(); int height = bi.getHeight(); int poix = 0; int poiy = 0; BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = img.createGraphics(); // 设置画布为透明 img = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT); // 扫描图片 for (int i = start_y; i < height; i++) { for (int j = 0; j < width; j++) {// 行扫描 int dip = bi.getRGB(j, i); int p = dip; int red = 0xff & (p >> 16); int green = 0xff & (p >> 8); int blue = 0xff & p; // 目标人图形 if (i < (height / 1.5)) { if ((red > 30 && red < 70) && (green > 40 && green < 70) && (blue > 60 && blue < 110)) {// 获取小人颜色 int cyd = 6; RGB rgb_1 = dipToRgb(bi, j + cyd, i + cyd); RGB rgb_2 = dipToRgb(bi, j - cyd, i - cyd); RGB rgb_3 = dipToRgb(bi, j - cyd, i + cyd); RGB rgb_4 = dipToRgb(bi, j + cyd, i - cyd); if (istrueren(rgb_1) && istrueren(rgb_2) && istrueren(rgb_3) && istrueren(rgb_4)) { img.setRGB(j, i, dip); if (poiy < i) { if (red == 54 && green == 60 && blue == 102) { if (bi.getRGB(j + 1, i) == dip) { poix = j; poiy = i; } } } } } } } } for (int rgb_ox = 0; rgb_ox < 10; rgb_ox++) { for (int rgb_ox_y = 0; rgb_ox_y < 10; rgb_ox_y++) { try { img.setRGB(poix + rgb_ox, poiy + rgb_ox_y, -2559242); } catch (Exception e) { } } } int fd_rgb = 10;// 颜色差 int qs_rgb_x = 0; int qs_rgb_y = 0; int qs_index = 0; int rgb_oxrgb = -13091994; boolean is_mbh = false; System.out.println(); for (int y = start_y; y < poiy; y++) {// 行扫描 RGB rgb_0 = dipToRgb(bi, 0, y); for (int x = 1; x < width; x++) { /***** 去掉目标人颜色 */ int dip = bi.getRGB(x, y); int p = dip; int red = 0xff & (p >> 16); int green = 0xff & (p >> 8); int blue = 0xff & p; // 目标人图形 if (y < (height / 1.5)) { if ((red > 30 && red < 70) && (green > 40 && green < 70) && (blue > 60 && blue < 110)) {// 获取小人颜色 int cyd = 6; RGB rgb_1 = dipToRgb(bi, x + cyd, y + cyd); RGB rgb_2 = dipToRgb(bi, x - cyd, y - cyd); RGB rgb_3 = dipToRgb(bi, x - cyd, y + cyd); RGB rgb_4 = dipToRgb(bi, x + cyd, y - cyd); if (istrueren(rgb_1) && istrueren(rgb_2) && istrueren(rgb_3) && istrueren(rgb_4)) { //img.setRGB(x, y, dip); continue; } } } if (x < (poix + 55) && x > (poix - 55) && y > (poiy - 240)) continue; /***** 去掉目标人颜色 */ RGB rgb_1 = dipToRgb(bi, x, y); img.setRGB(x, y, bi.getRGB(x, y)); if (rgb_cz(rgb_0, rgb_1, fd_rgb)) {// 同一种颜色 continue; } else { qs_rgb_y = y; if (!is_mbh) { qs_rgb_x = x; } qs_index++; is_mbh = true; for (int rgb_ox = 0; rgb_ox < 10; rgb_ox++) { for (int rgb_ox_y = 0; rgb_ox_y < 10; rgb_ox_y++) { try { img.setRGB(x + rgb_ox, y + rgb_ox_y, rgb_oxrgb); } catch (Exception e) { } } } } } if (is_mbh) { break; } } qs_rgb_x = qs_rgb_x + (qs_index / 2); // System.out.println("目标物坐标:"+qs_rgb_x+" "+qs_rgb_y); int ox_x = qs_rgb_x; int ox_y = qs_rgb_y + 40; poiy -= 10; // System.out.println("目标人:" + poix + " " + poiy); // System.out.println("中心点:" + ox_x + " " + ox_y); for (int rgb_ox = 0; rgb_ox < 10; rgb_ox++) { for (int rgb_ox_y = 0; rgb_ox_y < 10; rgb_ox_y++) { img.setRGB(ox_x + rgb_ox, ox_y + rgb_ox_y, rgb_oxrgb); } } int z_i = (poix - ox_x) * (poix - ox_x) + (ox_y - poiy) * (ox_y - poiy); double math_i = (double) Math.sqrt(z_i); System.out.println("最终距离:" + math_i); ImageIO.write(img, "png", new File(file2)); double end_time_out = (math_i * time_out); if (math_i < 250) { end_time_out += 13; } System.out.println("按键时长:" + end_time_out); if (istest) { cmd_java("cmd /c start adb shell input swipe " + 500 + " " + 1650 + " " + 510 + " " + 1650 + " " + (int) end_time_out); } Thread.sleep(1000); } } /** * 判断小人颜色 * * @param rgb * @return */ public static boolean istrueren(RGB rgb) { if (rgb == null) { return true; } int red = rgb.getRed(); int green = rgb.getGreen(); int blue = rgb.getBlue(); if ((red > 30 && red < 70) && (green > 40 && green < 70) && (blue > 60 && blue < 110)) {// 获取小人颜色 return true; } return false; } static InputStreamReader ir = null; static LineNumberReader input = null; public static void cmd_java(String cmd) throws IOException { Process process = Runtime.getRuntime().exec(cmd, null, new File("C:\Users\chenyd\adb")); ir = new InputStreamReader(process.getInputStream()); input = new LineNumberReader(ir); while (input.readLine() != null) { } input.close(); ir.close(); } public static void cmd_java(String cmd, String url) throws IOException { Process process = Runtime.getRuntime().exec(cmd, null, new File(url)); ir = new InputStreamReader(process.getInputStream()); input = new LineNumberReader(ir); while (input.readLine() != null) { } input.close(); ir.close(); } /** * 颜色的差值 */ public static boolean rgb_cz(RGB rgb_1, RGB rgb_2, int fd_rgb) { if (Math.abs(rgb_1.getRed() - rgb_2.getRed()) > fd_rgb || Math.abs(rgb_1.getGreen() - rgb_2.getGreen()) > fd_rgb || Math.abs(rgb_1.getBlue() - rgb_2.getBlue()) > fd_rgb) { return false; } return true; } public static RGB dipToRgb(BufferedImage bi, int j, int i) { try { int dip = bi.getRGB(j, i); int p = dip; int red = 0xff & (p >> 16); int green = 0xff & (p >> 8); int blue = 0xff & p; return new RGB(j, i, red, green, blue); } catch (Exception e) { } return null; } } class RGB { public RGB() { } public RGB(int x, int y, int red, int green, int blue) { super(); X = x; Y = y; this.red = red; this.green = green; this.blue = blue; } public int X; public int Y; public int red; public int green; public int blue; public int getRed() { return red; } public void setRed(int red) { this.red = red; } public int getGreen() { return green; } public void setGreen(int green) { this.green = green; } public int getBlue() { return blue; } public void setBlue(int blue) { this.blue = blue; } public int getX() { return X; } public void setX(int x) { X = x; } public int getY() { return Y; } public void setY(int y) { Y = y; } }