C++实现微信跳一跳辅助程序

时间:2022-07-02 23:23:33

     最近很火的微信小程序《跳一跳》,笔者我玩了一下,总是50以下得分,在好友圈里垫底,有点扎心,于是乎就发挥下程序员的力量。这款游戏,操作非常的简单,仅仅是按住屏幕一定时间后放开即可。

     也就是说,我们只要知道自己大概要按多长时间就好了,然后笔者本身是做Android开发,经常会用到adb进行调试机器。按压屏幕一定时间,我们在cmd中运行adb shell input swipe 1 1 1 1 1000就可以滑动屏幕1秒。实现按压屏幕1秒后弹起。

       现在我们的目标是计算按压时间t;

       先做一波测试,分别测试t1~tn的值时,能跳远距离,构造出时间与距离的方程。(距离用尺子量下就好了)

       来一组adb shell input swipe 1 1 1 1 tn,笔者发现时间与距离呈线性变化,于是笔者就简单的取了个比例,也可用回归方程计算出比较精确的比例系数。(笔者比较懒就算了)

        得出了一个方程 t = 189 * s/ 0.8   (笔者手机分辨率是1080*1920,红米2)

        接下来要测量s的值,那么s的值怎么来,自然就想到图像识别分析图像中心,想了下,还是算了。于是就采取屏幕采点的方式进行策略距离。

        C++实现微信跳一跳辅助程序

       根据我们初中学的勾股定理很容易计算出s = k * [(x1-x2)^2 + (y1-y2)^2] ^ 1/2,其中k是比例系数,那么坐标(x1,y1)和(x2,y2)怎么获得。很简单,鼠标左键点一下获得点(x1,y1),右键点一下获得(x2,y2)并开始运行。

         实际代码如何实现如下。

         预备工具:adb.exe,AdbWinApi.dll,AdbWinUsbApi.dll

         打开VS创建win32程序。

        新建头文件Jump.h

      

char const *const EXEC_HEAD = "adb shell input swipe 1 1 1 1 ";
char const *const SCREENCAP = "adb shell screencap -p /sdcard/jump_display.png";
char const *const PULL = "adb pull /sdcard/jump_display.png";
char const *const TAP = "adb shell input tap ";
class Jump
{
private:
    int duration;
    float distance;
    int width;
    int height;
public:
    Jump();
    ~Jump();
    void initPhysicalSize();
    void exec();
    void calculateDistance(float d);
    void calculateDuration();
    void screencap();
    void loadimage();
    int getWidth();
    int getHeight();
    void clickScreen(int w, int h);
}

       新建C++文件Jump.cpp

#define _CRT_SECURE_NO_WARNINGS

#include "Jump.h"
#include <iostream>
#include <string>
#include <cstdlib>
#include <sstream>
#include <fstream>

using namespace std;

Jump::Jump()
{
    system("adb start-server");
    distance = 3.0;
}

void Jump::initPhysicalSize()
{
    system("adb shell wm size > size.txt");
    ifstream iss("size.txt");
    char size[10];
    if(!iss.is_open()) return;
    iss.seekg(15);
    if(!iss.eof())
    {
        iss.get(size,10);
    }
    iss.close();
    const char * split = "x";
    char *p;

    p = strtok(size,split);
    int w_len = strlen(p);
    width = 0;
    for(int index = 0; index < w_len; index ++)
    {
        width = width + pow(10,w_len - index - 1) * (int)(p[index]-48);
    }
    
    p = strtok(NULL,split);
    int h_len = strlen(p);
    height = 0;
    for(int index = 0; index < h_len; index ++)
    {
        height = height + pow(10,h_len-index - 1) * (int)(p[index]-48);
    }
}

void Jump::calculateDistance(float d)
{
    distance = d;
}

void Jump::calculateDuration()
{
    duration = (int)(189 * 1.0 * distance / 0.8);
}

void Jump::exec()
{
    ostringstream oss;
    oss << EXEC_HEAD << duration;
    system(oss.str().c_str());
}

void Jump::screencap()
{
    system(SCREENCAP);
}

void Jump::loadimage()
{
    system(PULL);
}

int Jump::getWidth()
{
    return width;
}

int Jump::getHeight()
{
    return height;
} 

void Jump::clickScreen(int w, int h)
{
    ostringstream oss;
    oss << TAP << w << " " << h;
    system(oss.str().c_str());
}

Jump::~Jump()
{
}

      接下来窗体主函数Main.cpp

 

#include <iostream>
#include <windows.h>
#include <gdiplus.h>
#pragma comment(lib,"Gdiplus.lib")
#include "Jump.h"

using namespace Gdiplus;
using namespace DllExports;
using namespace std;

LRESULT CALLBACK WinProc
{
    HWND hwnd;
    UINT uMsg;
    WPARAM wParam;
    LPARAM lParam;
};

HDC hdc;
HDC hdcmem;
HBITMAP hBm;
ULONG_PTR gdipid;
SIZE sBmp;
SIZE size_bmp;
GdiplusStartupInput gsi;
GdiplusStartupOutput gso;
GpBitmap *gbmp;
Bitmap *bmp;
Jump jump;

float x_po1, y_po1, x_po2, y_po2;
HANDLE execThread;

HWDN mhwnd;
int WIDTH_W;
int HEIGHT_W;

int WINAPI(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nShowCmd)
{
    jump.initPhysicalSize();
    WIDTH_W = jump.getWidth() / 4;
    HEIGHT_W = jump.getHeight() / 4;

    //init window
    WNDCALSS wndclass;
    wndclass.cbClsExtra = 0;
    wndclass.cbWmdExtre = 0;
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.hCursor = LoadCurosr(hInstance, MAKEINTRESOURCE(IDC_HELP));
    wndclass.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_APPLICATION));
    wndclass.hInstance = hInstance;
    wndclass.lpfnWndProc = WinProc;
    wndclass.lpszClassName = "跳一跳";
    wndclass.lpszMenuName = NULL;
    wndclass.style = CS_HREDRAM | CS_VREDRAW;

     //register
     RegisterClass(&wndclass);
    
     //create window
     mhwnd = CreateWindow("跳一跳","跳一跳",WS_OVERLAPPENDWINDOW | WS_MAXSIZE,
         CW_USERDEFAULT,CW_USERDEFAULT,WIDTH_W + 17, HEIGHT + 40,NULL,NULL,hInstance,NULL);
     ShowWindow(mhwnd,SW_SHOWNORMAL);
     UpdateWindow(mhwnd);

    //loop
    MSG msg;
    while(GetMessage(&ms, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}

DWORD WINAPI ExecThread(LPVOID lpParamter)
{
    jump.calculateDistance(pow((x_po2 - x_po1)*(x_po2 - x_po1) + (y_po2 - y_po1)*(y_po2 - y_po1), 0.5) / 43.8);
    jump.calculateDuration();
    jump.exec();
  
Sleep(1000);
  jump.screencap();   jump.loadimage();     bmp = Bitmap::FromFile(L"jump_display.png", 0);   size_bmp.cx = bmp->GetWidth();   size_bmp.cy = bmp->GetHeight();   bmp->GetHBITMAP(0, &hBm);   delete bmp;   InvalidateRect(mhwnd, NULL, NULL);
return 0; } LRESULT CALLBACK WinProc( HWND hwnd; UINT uMsg; WPARAM wParam; LPARAM lParam; ) { PAINTSTRUCT ps; switch(uMsg) { case WM_CREATE: hdc = GetDC(hwnd); hdcmem = CreateCompatibleDC(hdc); ReleaseDC(hwnd,hdc); jump.screencap(); jump.loadimage(); GdiplusStartup(&gdipid,&gsi,&gso); GdipCreateBitmapFromFile(L"jump_display.png",&gbmp); GdipGetImageWidth((GpImage*)gbmp,LPUINT(sBmp.cx)); GdipGetImageHeight((GpImage*)gbmp,LPUINT(sBmp.cy)); GdipCreateHBITMAPFromBitmap(gbmp,&hBm,0); GdipDisposeImage((GpImage*)gbmp); bmp = Bitmap::FromFile(L"jump_display.png",0); size_bmp.cx = bmp->GetWidth(); size_bmp.cy = bmp->GetHeight(); bmp->GetHBITMAP(0,&hBm); delete bmp; break; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); SelectObject(hdcmem,hBm); SetStretchBltMode(hdc,HALFTONE); StretchBlt(hdc,0,0,WIDTH_W,HEIGHT_W,hdcmem,0,0,size_bmp.cx,size_bmp.cy,SRCCOPY|SRCERASE); EndPaint(hwnd,&ps); DeleteObject(hBm); break; case WM_LBUTTONDOWN: x_po1 = LOWORD(lParam); y_po1 = HIWORD(lParam); break; case WM_RBUTTONDOWN: x_po2 = LOWORD(lParam); y_po2 = HIWORD(lParam); execThread = CreateThread(NULL, 0, ExecThread, NULL, 0, NULL); CloseHandle(execThread); break; case WM_CLOSE; if(IDYES == MessageBox(hwnd,"不玩了吗?", "跳一跳",MB_YESNO)) { DestroyWindow(hwnd); } break; case WM_DESTORY: GdiplusShutdonw(gdipid); PostQuitMessage(0); break; default : return DefWindowProc(hwnd,uMsg,wParam,lParam); } return 0; }

     操作方式,打开跳一跳游戏--->点击开始游戏--->打开程序--->左键选择起点坐标--->右键选择终点坐标并运行,loop。

代码写的很随意,可能比例系数会不一样。