前言
因为自己手太残,平均跳30来分就over了,最近又在捣鼓OpenCV所以干脆基于OpenCV写一个程序刷分来并总结一下最近学的内容。
之前写过一个版本,那个也就跳120来分就不行了,所以昨天进行优化了一下,效果挺好。网上开发语言都是Python,也没C++,所以在这里整理一下思路和代码,分享一下(对,我就是活雷锋)。
准备
首 先:配置好OpenCV,3.几 都没问题,还有adb.exe 配置好。
开发环境:VS 2015(什么都可以,只要配置到OpenCV可以使用就行)。
需要零件:可以跳一跳的Android手机一部,脑子。
思路
1、获取到手机上跳一跳的画面。
2、找到起跳点位置 à A。
3、找到目标点位置 à B。
4、计算A B两点的距离,计算出模拟按屏时间的长短。
5、adb 传输模拟按屏时间命令,完成跳跃。
具体实现
1、获取手机画面,并改变大小改成原图的一半。(我的测试手机是1280*720的)
Mat getNextImg() {
system("adb shell screencap -p /sdcard/next.png");
system("adb pull /sdcard/next.png");
Mat nextImg, reImg;
nextImg = imread("next.png");
resize(nextImg, reImg, Size(nextImg.cols / 2, nextImg.rows / 2));
return reImg;
}
Point getStartMaxPoint(Mat nextImg, Mat temp) {
Mat player;
matchTemplate(nextImg, temp, player, TM_CCOEFF_NORMED);
double min_val = 0, max_val = 0;
Point min_loc, max_loc, now_loc;
minMaxLoc(player, &min_val, &max_val, &min_loc, &max_loc);
rectangle(nextImg,
Point(0, 0),
Point(nextImg.cols, nextImg.rows / 4),
CV_RGB(0, 0, 0),
-1,8,0);
rectangle(nextImg,
Point(0, nextImg.rows * 3 / 4),
Point(nextImg.cols, nextImg.rows),
CV_RGB(0, 0, 0),
-1, 8, 0);
return max_loc;
}
3、获取目标点B,比较麻烦,分两小步写。
①、先判断下一步是否识别到加分的那个小圆点,如果有就获取小圆点的中心坐标 即:目标点B的坐标;如果没有就执行第②步。
②、将源图像进行高斯模糊、边缘化处理。然后从上向下行遍历,从右到左列遍历,得到目标区域的最顶部坐标和最右边的坐标。从而得到目标点。下面是简易的执行原理图。
Point findTargetPoint(Mat img) {
//开始遍历行数
int startRow = img.rows / 4 + 5;
//结束遍历行数
int rows = startRow + img.rows / 5 + 10;
int cols = img.cols * img.channels();
Point top, right;
right.x = 0; right.y = 0;
bool topPonit = false;
// 找上边的顶点
for (int i = startRow; i < rows; i++) {
uchar* data = img.ptr<uchar>(i);
int temporaryX = 0;
for (int j = cols; j > 0; j--) {
if (data[j] != 0) {
temporaryX++;
if (!topPonit) {
top.x = j;
top.y = i;
topPonit = true;
}
}
if (temporaryX > 1) {
top.x = top.x - (temporaryX / 2);
top.y = i;
temporaryX = 0;
}
}
//一旦找到,循环结束
if(topPonit){
break;
}
}
//找右边的顶点
for (int i = top.y; i < rows; i++) {
uchar* data = img.ptr<uchar>(i);
for (int j = cols; j > top.x; j--) {
if (data[j] != 0) {
if (j > right.x) {
right.x = j;
right.y = i;
}
}
}
}
return Point(top.x, right.y);
}
4、计算A B两点距离,随机生成模拟按屏位置坐标,计算模拟按屏时间,adb命令传入手机,完成跳跃。其中2.12的那个地方根据实际情况调节。
d = sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)) * 2;
cout << "实际距离:" << d << endl;
int pressX = random(10, next.cols * 2);
int pressY = random(next.cols*2/5, next.cols *8/5);
char* str1 = "adb shell input swipe";
char cmd[100];
float time = d * 2.12;
sprintf(cmd, "%s %d %d %d %d %d", str1, pressX, pressY, pressX, pressY, (int)time);
cout << "cmd:" << cmd << endl;
system(cmd);
大体思路就是这样,这一版本是按“j”键完成跳跃,按“e”键结束,想要实现自动跳(源码里没有,下边有思路)就是在while{…}里作文章。
while (true)
{
char key = waitKey(50);
if (key == 'j') {
automatic = true;
}
if (automatic) {
.........................
别的细节操作,源码里有
.........................
int anTime = random(15, 22);
char command = waitKey(time + anTime * 100);
if (command == 'e') {
automatic = false;
cout << "*********以结束程序运行**********" << endl;
break;
}
}
}
微信有防作弊机制,这个程序反防作弊机制也还可以(只要别太过分),本来想看看到底能跳多久,直到跳到下图,再跳就扣分了,……对,就是能一直跳,膨胀了。
下面的是全部代码的网盘连接。(好人就是我)
连接:https://pan.baidu.com/s/1KYDoOahorYUT7fPszRFqwg
密码:n8ud
{{ cmt.username }}
{{ cmt.content }}
{{ cmt.commentDate | formatDate('YYYY.MM.DD hh:mm') }}