使用python+adb实现微信跳一跳外挂

源码地址

使用方法

  1. 安卓手机打开USB调试 打开USB调试方法,进入设置,找到开发者选项,打开并勾选USB调试; 如果没有开发者选项,进入关于手机,连续点击版本号7次,即可开启开发者选项

  2. 进入微信跳一跳并点开始游戏,运行python helper.py

实现原理

  1. 使用adb命令截图保存到本地

    adb shell screencap -p | perl -pe 's/\\x0D\\x0A/\\x0A/g' > screen.png
    
    # 如果没有perl可以先保存再pull
    adb shell screencap -p /sdcard/screen.png
    adb pull /sdcard/screen.png .

  2. 使用python解析图片并查找棋子和落点

    • 根据棋子颜色,取底部左右两边特征点,以中点为棋子位置
    • 寻找落点

      • 有小圆点,直接通过圆点颜色RGB(245, 245, 245)找出圆点位置作为落点

      • 纯色平台

        1. 从上往下查找第一个与背景色不同的点,作为平台顶点
        2. 从顶点开始向左下搜索与顶点相同颜色的点,找到平台左顶点
        3. 从顶点开始向右下搜索与顶点相同颜色的点,找到平台右顶点
        4. 以左右点中点为落点 搜索平台中心
      • 其他情况

        1. 同样从上往下查找第一个与背景色不同的点,作为平台顶点
        2. 通过固定斜率0.58、棋子当前位置,计算落点(图中红线交点) 计算落点
  3. 使用adb命令模拟触摸

adb shell input swipe x y x y time #其中x和y是屏幕坐标,time是触摸时间,单位ms

详解

寻找棋子

寻找棋子

直接通过棋子特征颜色查找其“最左点”和“最右点”,计算中点

def find_cur_pos(img):
    '''
    查找棋子当前位置
    通过棋子底部颜色范围,搜索棋子左右点,以中点作为棋子当前位置
    '''
    width, height = img.width, img.height

    local = [(width, 0), (0, 0)]
    def put_in(x, y):
        left, right = local[0], local[1]
        if x < left[0]:
            left = (x, y)
            local[0] = left
        if x >= right[0]:
            right = (x, y)
            local[1] = right

    for x in range(int(width * 0.1), int(width * 0.9)):
        for y in range(int(height * 0.52), int(height * 0.62)):
            pixel = img.getpixel((x, y))
            r, g, b = pixel[0], pixel[1], pixel[2]
            if r < 45 and r > 40 and \
                g < 45 and g > 40 and \
                b < 75 and b > 70:
                put_in(x, y)

            if r < 60 and r > 50 and \
                g < 60 and g > 50 and \
                b < 90 and b > 80:
                put_in(x, y)

    left, right = local[0], local[1]
    if left[0] == width:
        return None

    x = int((left[0] + right[0]) / 2)
    y = int((left[1] + right[1]) / 2)
    return (x, y)

寻找小圆点

通过圆点颜色RGB(245, 245, 245)寻找落点

以落点在左边为例: 寻找小圆点

通过圆点颜色RGB(245, 245, 245)、斜率K、坐标x,计算斜线上的点并判断颜色

通常先查找到A点,然后分别向右和向下查找B和C点,以BC线段中点作为落点。

落点在右边时先搜索到的点A位置稍有不同,但算法相同

查找点A的代码:

# 查找点A
for x in ite:
    '''
    通过斜率计算斜线上的位置,并判断是否和圆点颜色一样
    '''
    y = int(cur[1] - 0.58 * abs(cur[0] - x))
    pixel = img.getpixel((x, y))
    r, g, b = pixel[0], pixel[1], pixel[2]
    if r == 245 and g == 245 and b == 245:
        one_of_circle = (x, y)
        break

寻找平台中心点

寻找平台中心点

首先寻找平台顶点,然后寻找左右顶点,计算平台中心点

  1. 寻找平台顶点

    next_top, top_pixel = None, None # 顶点坐标和颜色
    
    # 从上往下查找第一个与背景色不同的点,作为平台顶点
    for y in range(int(height * 0.3), int(height * 0.52)):
        # 背景色,因为有渐变,所以每行重新获取背景色
        bg_pixel = img.getpixel((width - 1, y))
    
        for x in ite:
            pixel = img.getpixel((x, y))
    
            # 渐变问题,允许差值
            if abs(pixel[0] - bg_pixel[0]) > 8 \
                or abs(pixel[1] - bg_pixel[1]) > 8 \
                or abs(pixel[2] - bg_pixel[2]) > 8:
                next_top = (x, y)
                top_pixel = pixel
                break
        if next_top != None:
            break

  2. 搜索左右顶点

    这种方法在某些情形会出现错误,暂未处理。可以通过设定点与点之间的规则排除这些平台(距离、y差值范围等规则) 错误

    x, y = next_top
    while True:
        while True:
            # 向左查找相同颜色点
            if not same_color(img.getpixel((x - 1, y)), top_pixel):
                break
            x -= 1
    
        # 向下一个像素
        if not same_color(img.getpixel((x, y + 1)), top_pixel):
            break
        y += 1
    if x != next_top[0] and y != next_top[1]:
        left = (x, y)
    x, y = next_top
    while True:
        while True:
            # 向右查找相同颜色点
            if not same_color(img.getpixel((x + 1, y)), top_pixel):
                break
            x += 1
    
        # 向下查找相同颜色点
        if not same_color(img.getpixel((x, y + 1)), top_pixel):
            break
        y += 1
    if x != next_top[0] and y != next_top[1]:
        right = (x, y)

其他情况计算落点

其他情况计算落点

如果当前棋子位置有偏差,这种方式结果会出现偏差

# x, y 为平台顶点坐标
k = 0.58 # 斜率
y = cur[1] - k * float(x - cur[0])

模拟触摸

通过当前位置和落点位置计算出距离distance,然后触摸时长T = distance * P

不同分辨率下,系数P不同,需要查找

1600x2560机型推荐0.92

1440x2560机型推荐1.039

1080x1920机型推荐1.392

720x1280机型推荐2.078

参考

思路来自WechatJumpHelper