思路:
1.截取安卓模拟器对应窗口的图像内容
2.处理图像找出起点和终点
3.计算距离
4.鼠标事件
经过:
1.一开始想先将截图储存在某个路径,在用文件流读取那个图片,对图片进行处理。之后发现直接对BufferedImage里的内容进行处理更方便。
2.在计算距离的时候遇到了一点困难,用了取巧的办法。即找到新台阶中心点的横坐标,找到小人起跳点的横坐标,相减求得横向距离。手测三角形的长边和底边的比例,乘一下求出距离。
3.距离和按键时间的关系一开始以为是线性关系,后来发现好像并不是这样,想利用神经网络来拟合一下,还在思考实现方法。
结果:
1.能够自动地在安卓模拟器上刷到600+分,遇到圆形小台阶不是很稳,会掉下去。
2.在遇到圆形台阶时距离的测算会遇到一点问题,应该是三角形的形状变了,导致距离计算不准确,很难刷到高分。
待改进:
1.拟合距离-时间公式。
2.找到测距离更准确的办法。
窗口截取:
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.image.*;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
public class ScreenCut {
private static int startX = 0;
private static int startY = 0;
private static int width = 0;
private static int height = 0;
private static String path = "";
private static int[][] data = null;
public static void main(String[] args)
{
ScreenCut();
}
public static int[][] ScreenCut()
{
startX = 7;
startY = 45;
width = 540;
height = 960;
path = "C:\\Users\\Administrator\\Desktop\\Jump1.bmp";
data = getScreenCutData(startX, startY, width, height);
storeAsBmp(path,data);
return data;
}
public static int[][] getScreenCutData(int startX, int startY, int width, int height)
{
//time = caledTime;
//BufferedImage screenCut = new BufferedImage();
int[][] data = new int[width][height];
try
{
Robot robot = new Robot();
Rectangle screenRect = new Rectangle(startX,startY,width,height);
BufferedImage screenCut = robot.createScreenCapture(screenRect);
//System.out.println(screenCut);
for(int i = 0; i < width; i++)
{
for(int j = 0; j < height; j++)
{
data[i][j] = screenCut.getRGB(i, j);
}
}
//screenCut.getRGB(0, 0, 540, 960, data, 0, 0);
}
catch(AWTException e)
{
System.out.println(e);
}
/*
for(int i = 0; i < width; i++)
{
for(int j = 0; j < height; j++)
{
System.out.println("i = " + i + "j = " + j + data[i][j]);
}
}
*/
return data;
// int r = data[539][958] >> 16 & 0xFF;
// int g = data[539][958] >> 8 & 0xFF;
// int b = data[539][958] & 0xFF;
// System.out.println(r + " " + g + " " + b);
}
}
处理图像及计算距离:
import java.util.*;
import java.awt.Graphics;
import java.io.*;
public class PicDeal
{
// public static void main(String args[])
// {
// String src = "C:\\Users\\Administrator\\Desktop\\Jump1.bmp";
// String srcout = "C:\\Users\\Administrator\\Desktop\\Jumpout.bmp";
// double distance = BmpCalTime(src,srcout);
// }
//
public static double screenCutDataCalTime(int[][] data)
{
int screenCutWidth = data.length;
int screenCutHeight = data[0].length;
int[][] r = null;
int[][] g = null;
int[][] b = null;
int nTopX = 0;
int nTopY = 0;
int oX = 0;
int oY = 0;
double distance = 0;
double ratioDistance = 0;
double allDistance = 0;
System.out.println("pic size: " + screenCutWidth + " " + screenCutHeight);
allDistance = screenCutHeight;
//
//System.out.println(skipnum);
r = new int[screenCutHeight][screenCutWidth];
g = new int[screenCutHeight][screenCutWidth];
b = new int[screenCutHeight][screenCutWidth];
int flag = 1;
boolean flag2 = false;
for(int i = 0; i < screenCutHeight; i++)
{
for(int j = 0; j < screenCutWidth; j++)
{
// int r = data[539][958] >> 16 & 0xFF;
// int g = data[539][958] >> 8 & 0xFF;
// int b = data[539][958] & 0xFF;
// System.out.println(r + " " + g + " " + b);
int red = data[j][i] >> 16 & 0xFF;
int green = data[j][i] >> 8 & 0xFF;
int blue = data[j][i] & 0xFF;
// if(476 > i && i > 474 && j < 183 && j > 181)
// {
// System.out.println(red +" " + green +" "+ blue);
// }
if(i > 300 && j > 10 && j < screenCutWidth - 10)
{
if( flag == 1 && (Math.abs(red-r[i][j-1]) + Math.abs(green-g[i][j-1]) + Math.abs(blue-b[i][j-1])) > 20 )
{
nTopX = j;
nTopY = i + 1;
flag = 2;
System.out.println("new location: " + nTopX + " " + nTopY);
}
if( flag2 == false && red > 50 && red < 54 && green > 51 && green < 55 && blue > 58 && blue < 62)
{
oX = j;
oY = i + 88;
flag2 = true;
System.out.println("old location: " + oX + " " + oY);
}
}
r[i][j] = red;
g[i][j] = green;
b[i][j] = blue;
}
}
distance = 1.1557 * Math.abs(oX - nTopX);
ratioDistance = distance/allDistance;
System.out.println("distance = " + distance);
System.out.println("allDistance = " + allDistance);
System.out.println("ratioDistance = " + ratioDistance);
return ratioDistance;
}
private static int byte2Int(byte[] b)
{
int num=(b[3]&0xff)<<24|(b[2]&0xff)<<16|(b[1]&0xff)<<8|(b[0]&0xff);
return num;
}
}
鼠标事件:
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.*;
public class mouseClick {
private static int time = 0;
public static void clickAndHode(int caledTime)
{
time = caledTime;
if(time <100)
{
time = 300;
}
//BufferedImage screenCut = new BufferedImage();
try
{
Robot robot = new Robot();
robot.mouseMove(300, 300);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.delay(time);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.delay(1500);
}
catch(AWTException e)
{
System.out.println(e);
}
}
}
main函数:
public class JumpCheat {
public static void main(String[] args)
{
//String src = "C:\\Users\\Administrator\\Desktop\\Jump1.bmp";
for(int lop = 0; lop < 100; lop ++)
{
PicDeal picDeal = new PicDeal();
mouseClick mClick = new mouseClick();
ScreenCut sCut = new ScreenCut();
int[][] data = sCut.ScreenCut();
//double caledTime = picDeal.BmpCalTime(src);
double caledTime = picDeal.screenCutDataCalTime(data);
int holdTime = (int) (caledTime * 2675);
mClick.clickAndHode(holdTime);
}
}
}
github:https://github.com/stpraha/JumpCheat