“Cpp+EasyX库+adb命令”实现微信跳一跳自主运行

一、概述

“微信跳一跳”小程序出现以来,网上出现了各种各样的“外挂”,从用单片机做的“半自动外挂”到用按键精灵做的“全自动外挂”,各式各样。我觉得做所谓的外挂并不是根本目的,根本目的在于在做外挂的过程中学习各种知识并享受整个过程。寒假在家的几天尝试了一种新的思路,就是用“Cpp+EasyX库+adb命令”的方式实现相关功能。在整个过程中,我在论坛查阅了不少前辈的博文,给予了我很大的启发,因此在这里表示感谢。但是在截图的像素处理、像素的定位方式等方面,我也有些自己的见解与大家分享。

二、所需工具

VS2012编译器、EasyX库(安装到VS2012),adb命令工具(安装至电脑)、手机、数据线

三、基本流程

实现功能的基本思路如下:

四、详细流程

(一)安装所需工具

1.下载并安装adb工具(可自行百度,很简单)

2.在VS2012安装EasyX库(可自行百度,很简单)

(二)测试手机与PC的连接

1.将手机与PC端通过数据线连接,并打开USB调试

2.通过cmd发送adb指令检查连接情况,如果成功连接,会返回一串设备号

adb命令为“adb devices”,效果如下

(三)功能代码

1.头文件、子函数与变量

#include<stdafx.h>
#include<atlimage.h>
#include<graphics.h>
#include<math.h>
#include <conio.h>

/***********************子函数区**************************************/
int ColorFun(COLORREF color1, COLORREF color2, unsigned int diff);//diff为差异值

/***********************全局变量区*************************************/
int xy[800][700];//用来存储切割后截图的像素点
float r1,g1,b1,r2,g2,b2;//用来储存像素点的RGB值

/***********************局部变量区*****************************************/
    int i,j;//用于取色中的循环,i代表行,j代表列
    float hi,hj,ri,rj;//分别记录盒子顶部坐标与人底部坐标
    int x;
    double d;
    int t;//储存时间
    char str[50];//储存模拟触摸命令
 

2.adb命令进行手机连接、发送截图与传送命令

system("adb devices");//连接移动设备

Sleep(1000);//等待连接

CImage cimage;//进行格式转换

IMAGE image,img;//指向原始截图与切割后的截图
system("adb shell /system/bin/screencap -p /sdcard/screenshot.png");//截屏并命名为screenshot.png
system("adb pull /sdcard/screenshot.png e:/screenshot.png");//把截图screenshot.png发送到e

 

3.通过CImage类进行截图的图片格式转换

因为截图默认格式为png格式,而EasyX库文件中进行图片操作的函数不支持该格式,因此通过CImage类将截图转化为jpg格式:

cimage.Load("E://screenshot.png");//加载e盘中的截图screenshot.png
cimage.Save("E://screenshot.jpg");//把截screenshot.png转换为screenshot.jpg

 

4.对图片进行切割并显示:

经过不断尝试,将图片切割为800×700即可:

initgraph(800,700);
loadimage(&image,"E:\\screenshot.jpg",0, 0);//加载转换好的screenshot.jpg
SetWorkingImage(&image); // 把原始截图设定为绘图设备,以便切割
getimage(&img, 150, 600, 800, 700); // 从(150,600)开始切割图片,宽800,高700.并把切割后的图片保存到img
SetWorkingImage(NULL); // 恢复默认工作区(即原始窗口)
putimage(0,0,&img);

 

5.像素对比子函数

“人”与“新盒子”的位置是通过对比像素的RGB来得到的,我采取对图片像素进行扫描,并对像素的RGB进行对比从而得到人与新盒子的位置。因此,我需要一个能对比像素区别度的子函数:

int ColorFun(COLORREF color1, COLORREF color2, unsigned int diff)
{
    //三种基色的颜色差的平方根的值则代表两种颜色的相似度,值越小则越相似
     r1 = GetRValue(color1);
     g1 = GetGValue(color1);
     b1 = GetBValue(color1);
 
     r2 = GetRValue(color2);
     g2 = GetGValue(color2);
     b2 = GetBValue(color2);
 
     if (sqrt(((r2-r1)*(r2-r1)+(g2-g1)*(g2-g1)+(b2-b1)*(b2-b1)))>diff)
     {
         return 1;
     }
     return 0;
}
该子函数能够取出像素点color1与像素点color2的RGB值并进行对比,如果区别度大于diff则认为是两个像素是差别较大的颜色并返回1,反之则返回0。

 

6.确定新盒子与人的位置

对于“人”:因为人的颜色是不变的,我可以得到其RGB值为(55,60,100)。因此对于人的识别,我们只需要“从下往上、从左往右”对像素进行扫描,并对比当前像素RGB与(55,60,100)的区别度,当区别度小于5.0时即认为扫描到了人的“底”,记录下“人底”的位置。

对于新盒子:因为盒子的颜色是不断变化的,但因为新盒子的颜色与背景色差异较大,因此对于新盒子的识别,我采取“从上往下、从左往右”的方式进行扫描并对比当前像素与前一个像素的RGB值的区别度,当区别度大于50.0时,即认为扫描到了新盒子顶部,记录此时的位置。

/***************************取色对比确定盒顶与人底坐标********************************/
SetWorkingImage(&img);//把切割后的截图设定为绘图设备,以便取色对比
for(j=0;j<700;j++)//取色
{
    for(i=0;i<800;i++)
    {
        xy[i][j] = getpixel(i,j);
    }
}
SetWorkingImage(NULL);

for(j=5;j<700;j++)//从上到下横向扫描对比色差,确定盒顶坐标(i变j不变)
{
    for(i=5;i<800;i++)
    {
        x=i-1;
        if(ColorFun(xy[i][j],xy[x][j],50.0)==1)//如果色差大于50.0
        {
            hi=i;//记录坐标
            hj=j;
            i=800;
            j=700;//跳出循环
        }
    }
}

/*****************************从下到上寻找人的底部坐标********************************************/
for(j=698;j>=0;j--)//对比色差,确定坐标
{
    for(i=0;i<800;i++)
    {
        if(ColorFun(xy[i][j], RGB(55,60,100),5)==0)//色差不大于5
        {
            ri=i;//记录坐标
            rj=j;
            i=800;
            j=-1;//跳出循环
        }
    }
}

 

7.根据两者位置计算距离并乘比例系数得到触屏时间

hi+=10;//根据盒定位置计算出盒子中心的大概位置

hj+=110;
d=sqrt((hi-ri)*(hi-ri)+(hj-rj)*(hj-rj));
d=d*1.35;//距离乘比例系数
t=d;
if(d-t>=0.5)//,因为时间只能为整数,因此对计算到的时间值进行四舍五入
{
    t=t+1;
}
else
{
    t=t-1;
}

 

8.通过adb指令向手机发送模拟触屏命令

sprintf_s(str,"adb shell input swipe 800 800 800 100 %d",t);
system(str);
closegraph();
printf("盒顶坐标:%f  %f\n人底坐标:%f  %f\n模拟触摸时间:%d\n\n",hi-10,hj-110,ri,rj,t);
Sleep(2000);

至此,整个功能已经实现。后期,我们只需将相关步骤放入循环体,即可实现跳一跳的连续自动运行。

 

五、完整源代码

#include<stdafx.h>
#include<atlimage.h>
#include<graphics.h>
#include<math.h>
#include <conio.h>

/***********************子函数区**************************************/
int ColorFun(COLORREF color1, COLORREF color2, unsigned int diff);//diff为差异值

/***********************全局变量区*************************************/
int xy[800][700];//用来存储切割后截图的像素点
float r1,g1,b1,r2,g2,b2;//用来储存像素点的RGB值


void main()
{
/***********************局部变量区*****************************************/
    int i,j;//用于取色中的循环,i代表行,j代表列
    float hi,hj,ri,rj;//分别记录盒子顶部坐标与人底部坐标
    int x;
    double d;
    int t;//储存时间
    char str[50];//储存模拟触摸命令

/*****************通过adb命令获取截图,传至PC端并转化为jpg格式***********/
    system("adb devices");//连接移动设备
    Sleep(1000);
    while(1)
    {
        CImage cimage;//进行格式转换
        IMAGE image,img;//指向原始截图与切割后的截图
        system("adb shell /system/bin/screencap -p /sdcard/screenshot.png");//截屏并命名为screenshot.png
        system("adb pull /sdcard/screenshot.png e:/screenshot.png");//把截图screenshot.png发送到e
        cimage.Load("E://screenshot.png");//加载e盘中的截图screenshot.png
        cimage.Save("E://screenshot.jpg");//把截screenshot.png转换为screenshot.jpg

    /**************************切割截图并保存*******************************************/
        initgraph(800,700);
        loadimage(&image,"E:\\screenshot.jpg",0, 0);//加载转换好的screenshot.jpg
        SetWorkingImage(&image); // 把原始截图设定为绘图设备,以便切割
        getimage(&img, 150, 600, 800, 700); // 从(150,600)开始切割图片,宽800,高700.并把切割后的图片保存到img
        SetWorkingImage(NULL); // 恢复默认工作区(即原始窗口)
        putimage(0,0,&img);///

    /***************************取色对比确定盒顶与人底坐标********************************/
        SetWorkingImage(&img);//把切割后的截图设定为绘图设备,以便取色对比
        for(j=0;j<700;j++)//取色
        {
            for(i=0;i<800;i++)
            {
                xy[i][j] = getpixel(i,j);
            }
        }
        SetWorkingImage(NULL);

        for(j=5;j<700;j++)//从上到下横向扫描对比色差,确定盒顶坐标(i变j不变)
        {
            for(i=5;i<800;i++)
            {
                x=i-1;
                if(ColorFun(xy[i][j],xy[x][j],50.0)==1)//如果色差大于20
                {
                    hi=i;//记录坐标
                    hj=j;
                    i=800;
                    j=700;//跳出循环
                }
            }
        }


    /*****************************从下到上寻找人的底部坐标********************************************/
        for(j=698;j>=0;j--)//对比色差,确定坐标
        {
            for(i=0;i<800;i++)
            {
                if(ColorFun(xy[i][j], RGB(55,60,100),5)==0)//色差不大于5
                {
                    ri=i;//记录坐标
                    rj=j;
                    i=800;
                    j=-1;//跳出循环
                }
            }
        }

    /********************根据坐标计算距离,并根据距离计算时间********************/
        hi+=10;
        hj+=110;
        d=sqrt((hi-ri)*(hi-ri)+(hj-rj)*(hj-rj));
        d=d*1.35;//距离乘比例系数
        t=d;
        if(d-t>=0.5)
        {
            t=t+1;
        }
        else
        {
            t=t-1;
        }

    /*****************************发送模拟触摸命令**************************************/
        sprintf_s(str,"adb shell input swipe 800 800 800 100 %d",t);
        system(str);
        closegraph();
        printf("盒顶坐标:%f  %f\n人底坐标:%f  %f\n模拟触摸时间:%d\n\n",hi-10,hj-110,ri,rj,t);
        Sleep(2000);
    }


}

/*************************判断颜色差异*******************************************/
int ColorFun(COLORREF color1, COLORREF color2, unsigned int diff)
{
    //三种基色的颜色差的平方根的值则代表两种颜色的相似度,值越小则越相似
     r1 = GetRValue(color1);
     g1 = GetGValue(color1);
     b1 = GetBValue(color1);
 
     r2 = GetRValue(color2);
     g2 = GetGValue(color2);
     b2 = GetBValue(color2);
 
     if (sqrt(((r2-r1)*(r2-r1)+(g2-g1)*(g2-g1)+(b2-b1)*(b2-b1)))>diff)
     {
         return 1;
     }
     return 0;
}
 

注:实测视频还要传输到一些视频平台才能添加到本文,比较麻烦。有想看的可以留下邮箱或者私聊我,我可以发给大家

 

 

左肩理想右肩担当,君子不怨永远不会停下脚步!

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是用 EasyX 实现绘制贝塞尔曲面的 C++ 代码: ```cpp #include <graphics.h> #include <math.h> // 贝塞尔曲面控制点个数 #define CTRL_POINTS_NUM 16 // 定义控制点结构体 struct CtrlPoint { int x; int y; }; // 控制点数组 CtrlPoint ctrlPoints[CTRL_POINTS_NUM] = { // 第一行 { 50, 50 }, { 150, 50 }, { 250, 50 }, { 350, 50 }, // 第二行 { 50, 150 }, { 150, 150 }, { 250, 150 }, { 350, 150 }, // 第三行 { 50, 250 }, { 150, 250 }, { 250, 250 }, { 350, 250 }, // 第四行 { 50, 350 }, { 150, 350 }, { 250, 350 }, { 350, 350 } }; // 计算阶乘 int factorial(int n) { int result = 1; for (int i = 1; i <= n; i++) { result *= i; } return result; } // 计算组合数 C(n, i) int combination(int n, int i) { return factorial(n) / (factorial(i) * factorial(n - i)); } // 计算贝塞尔曲线上的点 CtrlPoint bezier(CtrlPoint* points, double t) { int n = CTRL_POINTS_NUM - 1; // 控制点数 CtrlPoint result = { 0, 0 }; for (int i = 0; i <= n; i++) { int c = combination(n, i); double ti = pow(t, i); double tni = pow(1 - t, n - i); result.x += c * ti * tni * points[i].x; result.y += c * ti * tni * points[i].y; } return result; } // 绘制贝塞尔曲面 void drawBezierSurface(CtrlPoint* points) { for (double t = 0; t <= 1; t += 0.01) { for (double s = 0; s <= 1; s += 0.01) { // 计算16个控制点 CtrlPoint ctrlPoints[CTRL_POINTS_NUM]; for (int i = 0; i < CTRL_POINTS_NUM; i++) { int u = i % 4; int v = i / 4; ctrlPoints[i] = bezier(&points[v * 4], s); } // 计算贝塞尔曲面上的点 CtrlPoint p = bezier(ctrlPoints, t); putpixel(p.x, p.y, WHITE); } } } int main() { initgraph(400, 400); setbkcolor(BLACK); cleardevice(); // 绘制控制点 setcolor(GREEN); for (int i = 0; i < CTRL_POINTS_NUM; i++) { circle(ctrlPoints[i].x, ctrlPoints[i].y, 3); } // 绘制贝塞尔曲面 setcolor(WHITE); drawBezierSurface(ctrlPoints); getch(); closegraph(); return 0; } ``` 该代码使用了 EasyX 图形和数学,通过计算贝塞尔曲面上的点来绘制出整个曲面。运行该代码,可以得到如下所示的贝塞尔曲面: ![贝塞尔曲面](https://cdn.luogu.com.cn/upload/image_hosting/edn1gm6c.png)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值