python实现微信跳一跳外挂
使用python+adb实现微信跳一跳外挂
使用方法
-
安卓手机打开USB调试 打开USB调试方法,进入
设置
,找到开发者选项
,打开并勾选USB调试
; 如果没有开发者选项
,进入关于手机
,连续点击版本号
7次,即可开启开发者选项
-
进入微信跳一跳并点
开始游戏
,运行python helper.py
实现原理
-
使用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 .
-
使用python解析图片并查找棋子和落点
- 根据棋子颜色,取底部左右两边特征点,以中点为棋子位置
- 寻找落点
-
有小圆点,直接通过圆点颜色RGB(245, 245, 245)找出圆点位置作为落点
-
纯色平台
- 从上往下查找第一个与背景色不同的点,作为平台顶点
- 从顶点开始向左下搜索与顶点相同颜色的点,找到平台左顶点
- 从顶点开始向右下搜索与顶点相同颜色的点,找到平台右顶点
- 以左右点中点为落点
-
其他情况
- 同样从上往下查找第一个与背景色不同的点,作为平台顶点
- 通过固定斜率0.58、棋子当前位置,计算落点(图中红线交点)
-
-
使用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
寻找平台中心点
首先寻找平台顶点,然后寻找左右顶点,计算平台中心点
-
寻找平台顶点
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
-
搜索左右顶点
这种方法在某些情形会出现错误,暂未处理。可以通过设定点与点之间的规则排除这些平台(距离、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