java外挂-adb操作跳一跳

package cn.yihanyuan.tyt;
 import java.awt.Color;
 import java.awt.Font;
 import java.awt.Graphics2D;
 import java.awt.font.TextAttribute;
 import java.awt.image.BufferedImage;
 import java.io.File;
 import java.io.IOException;
 import java.text.AttributedCharacterIterator;
 import java.text.AttributedString;
 import java.util.Arrays;
 import java.util.Scanner;
 import java.util.concurrent.TimeUnit;
 import javax.imageio.ImageIO;
 public class tyt {
  static Scanner sc = new Scanner(System.in);
  private static final String IMAGE_NAME = "current.png";
  private static final String STORE_DIR = "current";
  // 数量
 private static final int imageLengthLength = 5;
  // 存放图片的大小
 private static final long[] imageLength = new long[imageLengthLength];
  private final RGBInfo rgbInfo = new RGBInfo();
  // 截屏中游戏分数显示区域最下方的Y坐标,300是 1920x1080的值,根据实际情况修改
 private final int gameScoreBottomY = 300;
  // 按压的时间系数,可根据具体情况适当调节
 private final double pressTimeCoefficient = 1.47;
  // 按压的起始点坐标,也是再来一局的起始点坐标
 private final int swipeX = 550;
  private final int swipeY = 1580;
  // 二分之一的棋子底座高度
 private final int halfBaseBoardHeight = 20;
  // 棋子的宽度,从截屏中量取,自行调节
 private final int halmaBodyWidth = 74;
  // 游戏截屏里的两个跳板的中点坐标,主要用来计算角度,可依据实际的截屏计算,计算XY的比例
 private final int boardX1 = 813;
  private final int boardY1 = 1122;
  private final int boardX2 = 310;
  private final int boardY2 = 813;
  private int[] getHalmaAndBoardXYValue(File currentImage) throws IOException {
   BufferedImage bufferedImage = ImageIO.read(currentImage);
   int width = bufferedImage.getWidth();
   int height = bufferedImage.getHeight();
   System.out.println("宽度:" + width + ",高度:" + height);
   int halmaXSum = 0;
   int halmaXCount = 0;
   int halmaYMax = 0;
   int boardX = 0;
   int boardY = 0;
   // 从截屏从上往下逐行遍历像素点,以棋子颜色作为位置识别的依据,最终取出棋子颜色最低行所有像素点的平均值,即计算出棋子所在的坐标
  for (int y = gameScoreBottomY; y < height; y++) {
    for (int x = 0; x < width; x++) {
     processRGBInfo(bufferedImage, x, y);
     int rValue = this.rgbInfo.getRValue();
     int gValue = this.rgbInfo.getGValue();
     int bValue = this.rgbInfo.getBValue();
     // 根据RGB的颜色来识别棋子的位置,
    if (rValue > 50 && rValue < 60 && gValue > 53 && gValue < 63 && bValue > 95 && bValue < 110) {
      halmaXSum += x;
      halmaXCount++;
      // 棋子底行的Y坐标值
     halmaYMax = y > halmaYMax ? y : halmaYMax;
     }
    }
   }
   if (halmaXSum != 0 && halmaXCount != 0) {
    // 棋子底行的X坐标值
   int halmaX = halmaXSum / halmaXCount;
    // 上移棋子底盘高度的一半
   int halmaY = halmaYMax - halfBaseBoardHeight;
    // 从gameScoreBottomY开始
   for (int y = gameScoreBottomY; y < height; y++) {
     processRGBInfo(bufferedImage, 0, y);
     int lastPixelR = this.rgbInfo.getRValue();
     int lastPixelG = this.rgbInfo.getGValue();
     int lastPixelB = this.rgbInfo.getBValue();
     // 只要计算出来的boardX的值大于0,就表示下个跳板的中心坐标X值取到了。
    if (boardX > 0) {
      break;
     }
     int boardXSum = 0;
     int boardXCount = 0;
     for (int x = 0; x < width; x++) {
      processRGBInfo(bufferedImage, x, y);
      int pixelR = this.rgbInfo.getRValue();
      int pixelG = this.rgbInfo.getGValue();
      int pixelB = this.rgbInfo.getBValue();
      // 处理棋子头部比下一个跳板还高的情况
     if (Math.abs(x - halmaX) < halmaBodyWidth) {
       continue;
      }
      // 从上往下逐行扫描至下一个跳板的顶点位置,下个跳板可能为圆形,也可能为方框,取多个点,求平均值
     if ((Math.abs(pixelR - lastPixelR) + Math.abs(pixelG - lastPixelG)
        + Math.abs(pixelB - lastPixelB)) > 10) {
       boardXSum += x;
       boardXCount++;
      }
     }
     if (boardXSum > 0) {
      boardX = boardXSum / boardXCount;
     }
    }
    // 按实际的角度来算,找到接近下一个 board 中心的坐标
   boardY = (int) (halmaY
      - Math.abs(boardX - halmaX) * Math.abs(boardY1 - boardY2) / Math.abs(boardX1 - boardX2));
    if (boardX > 0 && boardY > 0) {
     int[] result = new int[4];
     // 棋子的X坐标
    result[0] = halmaX;
     // 棋子的Y坐标
    result[1] = halmaY;
     // 下一块跳板的X坐标
    result[2] = boardX;
     // 下一块跳板的Y坐标
    result[3] = boardY;
     return result;
    }
   }
   return null;
  }
  private void executeCommand(String command) {
   Runtime rt = Runtime.getRuntime();
   Process p = null;
   try {
    p = rt.exec("cmd /c C:\\yuanyihanSOFT\\adb\\" + command);
    System.out.println(p.toString());
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
  private void executeADBCaptureCommands() {
   executeCommand("adb shell screencap -p /storage/emulated/0/baidu/current.png");
   try {
    TimeUnit.MILLISECONDS.sleep(50);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   executeCommand("adb pull /storage/emulated/0/baidu/current.png current/current.png");
   try {
    TimeUnit.MILLISECONDS.sleep(600);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  private void doJump(double distance) {
   System.out.println("distance: " + distance);
   // 计算按压时间,最小200毫秒
  int pressTime = (int) Math.max(distance * pressTimeCoefficient, 50);
   System.out.println("pressTime: " + pressTime);
   // 执行按压操作
  String command = String.format("adb shell input swipe %s %s %s %s %s", swipeX, swipeY, swipeX, swipeY,
     pressTime);
   System.out.println(command);
   executeCommand(command);
  }
  private void replayGame() {
   String command = String.format("adb shell input tap %s %s", swipeX, swipeY);
   executeCommand(command);
  }
  private double computeJumpDistance(int halmaX, int halmaY, int boardX, int boardY) {
   return Math.sqrt(Math.pow(Math.abs(boardX - halmaX), 2) + Math.pow(Math.abs(boardY - halmaY), 2));
  }
  public static void main(String[] args) {
   try {
    File storeDir = new File(STORE_DIR);
    if (!storeDir.exists()) {
     boolean flag = storeDir.mkdir();
     if (!flag) {
      System.err.println("创建图片存储目录失败");
      return;
     }
    }
    File currentImage2 = new File(STORE_DIR, IMAGE_NAME);
    if (currentImage2.exists()) {
     System.out.println("图片存在");
     currentImage2.delete();
    }
    if (currentImage2.exists()) {
     System.out.println("图片存在");
     currentImage2.delete();
    }
    currentImage2.deleteOnExit();
    tyt jumpjumpHelper = new tyt();
    // 执行次数
   int executeCount = 0;
    for (;;) {
     // 执行ADB命令,获取安卓截屏
    jumpjumpHelper.executeADBCaptureCommands();
     File currentImage = new File(STORE_DIR, IMAGE_NAME);
     if (!currentImage.exists()) {
      System.out.println("图片不存在");
      continue;
     }
     long length = currentImage.length();
     imageLength[executeCount % imageLengthLength] = length;
     // 查看是否需要重新开局
    jumpjumpHelper.checkDoReplay();
     executeCount++;
     System.out.println("当前第" + executeCount + "次执行!");
     // 获取跳棋和底板的中心坐标
    int[] result = jumpjumpHelper.getHalmaAndBoardXYValue(currentImage);
     if (result == null) {
      System.out.println("The result of method getHalmaAndBoardXYValue is null!");
      continue;
     }
     int halmaX = result[0];
     int halmaY = result[1];
     int boardX = result[2];
     int boardY = result[3];
     // 计算跳跃的距离
    double jumpDistance = jumpjumpHelper.computeJumpDistance(halmaX, halmaY, boardX, boardY);
     System.out.println("jumpDistance:" + jumpDistance);
     jumpDistance = yyhSetReal(halmaX, halmaY, boardX, boardY, jumpDistance, currentImage);
     System.out.println("doJump jumpDistance:" + jumpDistance);
     jumpjumpHelper.doJump(jumpDistance);
     // 每次停留2.5秒
    TimeUnit.MILLISECONDS.sleep(2500);
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
  private static double yyhSetReal(int halmaX, int halmaY, int boardX, int boardY, double jumpDistance,
    File currentImage) throws IOException {
   System.out.println("halmaX: " + halmaX + ", halmaY: " + halmaY + ", boardX: " + boardX + ", boardY: " + boardY);
   System.out.println("jumpDistance:" + jumpDistance);
   BufferedImage bufferedImage = ImageIO.read(currentImage);
   Graphics2D g2d = bufferedImage.createGraphics();
   g2d.drawImage(bufferedImage, 0, 0, null);
   g2d.setColor(new Color(1));
   Font f = new Font(null, Font.BOLD, 48);
   String markContent = new String("jumpDistance:" + jumpDistance);// 文字
  AttributedString ats = new AttributedString(markContent);
   ats.addAttribute(TextAttribute.FONT, f, 0, markContent.length());
   AttributedCharacterIterator iter = ats.getIterator();
   g2d.drawString(iter, 0, boardY + 500);
   g2d.drawLine(halmaX, halmaY, boardX, boardY);
   g2d.drawLine(halmaX + 1, halmaY + 1, boardX + 1, boardY + 1);
   g2d.drawLine(halmaX - 1, halmaY - 1, boardX - 1, boardY - 1);
   g2d.dispose();
   ImageIO.write(bufferedImage, "PNG", currentImage);
   System.out.println("ScannerTest, Please Enter number:");
   return jumpDistance;
//由袁一涵进行了代码的修改
 //  String scsc = sc.nextLine();
 //  if (scsc.isEmpty()) {
 //   return jumpDistance;
 //  }
 //  int intd = Integer.parseInt(scsc);
 //  double jumpDistance2 = jumpDistance + intd;
 //  if (intd == 0) {
 //   jumpDistance2 = 0.0;
 //  }
 //  return jumpDistance2;
  }
  private void checkDoReplay() {
   if (imageLength[0] > 0 && imageLength[0] == imageLength[1] && imageLength[1] == imageLength[2]
     && imageLength[2] == imageLength[3] && imageLength[3] == imageLength[4]) {
    // 此时表示已经连续5次图片大小一样了,可知当前屏幕处于再来一局
   Arrays.fill(imageLength, 0);
    // 模拟点击再来一局按钮重新开局
   replayGame();
   }
  }
  private void processRGBInfo(BufferedImage bufferedImage, int x, int y) {
   this.rgbInfo.reset();
   int pixel = bufferedImage.getRGB(x, y);
   // 转换为RGB数字
  this.rgbInfo.setRValue((pixel & 0xff0000) >> 16);
   this.rgbInfo.setGValue((pixel & 0xff00) >> 8);
   this.rgbInfo.setBValue((pixel & 0xff));
  }
  class RGBInfo {
   private int RValue;
   private int GValue;
   private int BValue;
   public int getRValue() {
    return RValue;
   }
   public void setRValue(int rValue) {
    RValue = rValue;
   }
   public int getGValue() {
    return GValue;
   }
   public void setGValue(int gValue) {
    GValue = gValue;
   }
   public int getBValue() {
    return BValue;
   }
   public void setBValue(int bValue) {
    BValue = bValue;
   }
   public void reset() {
    this.RValue = 0;
    this.GValue = 0;
    this.BValue = 0;
   }
  }
 }

猜你喜欢

转载自blog.csdn.net/qq1226317595/article/details/80374962
今日推荐