微信跳一跳辅助原理浅析

微信跳一跳辅助原理浅析

前言

本文从原理和算法的角度(参考https://github.com/wangshub/wechat_jump_game的实现)探讨怎样实现跳一跳的辅助,做到知其然还要只其所以然。尽量使一个没任何外挂经验的任何语言的普通人也能做出辅助来。当然如果你只打算刷分的话,那本文可能没什么帮助了。(另外,本教程只针对android)

原理介绍

原理其实很简单,棋子跳跃的时间和距离有关。那就利用adb(Android Debug Bridge)将当前手机的截图下载到电脑上,对截图进行分析,算出棋子和要跳的方块之间的距离,再乘以适当的参数即可得到时间。再利用adb模拟手机触摸事件,触摸对应的时间即可。

有2点需要明白的关键:

  1. 什么是adb?
  2. 怎样根据图片算出距离

这2点也是实现辅助的关键,下面一一介绍

ADB介绍

adb这东西应该算android的概念,全称Android Debug Bridge,翻译过来android调试桥?反正是与android设备(如手机)交互的工具。可使用它调试手机应用(需要手机授权)。如安装一个APP,模拟点击事件等,下面列出几个与本文有关的命令。(详情参考Android adb

1
2
3
4
5
6
7
8
9
10
11

adb shell screencap /sdcard/screen.png #屏幕截图并储存

adb pull /sdcard/screen.png # 将指定位置图片拉取过来

# 向设备发送模拟操作(输入、触摸等)
adb shell input
usage:input text <string> # 输入文字
input keyevent <key code number or name> # 按键
input tap <x> <y> # 点击
input swipe <x1> <y1> <x2> <y2> [duration(ms)] # 滑动

模拟操作的只用到了 adb shell input swipe <x1> <y1> <x2> <y2> [duration(ms)],表示从(x1,x2)的位置滑动到(x2,y2)的位置,滑动时间为duration毫秒。

怎样算出距离

图片拿到了,怎样算出距离是个难题。在介绍算法之前,有必要先了解下计算机是怎样储存和表示图片信息的。

计算机将图片的颜色表示为RGBA值。我们知道颜色的三原色红绿蓝,RGB即分别表示红绿蓝。剩下的A表示透明度。每个GRBA值表示一个像素,每个图片就是由这些千千万万个像素点构成的。

同时,为表示每个像素点,引入了坐标概念。以左上顶点为原点(0,0),向右为x轴,向下为y轴,像素点坐标均为正值(与数学上不太一致)

如上图所示,我们要想找到棋子,需要充分利用棋子颜色的这个特征,一行一行遍历像素点,直到找到棋子底座颜色(深紫色的)的若干像素点(实际是一个颜色范围区间),平均后得到底座中心位置。

至于方块的位置就不好找了,可以利用色差来做。如上图,背景色是浅黄色,要跳的方块是深灰色,可从上到下扫描像素点,记录背景色,一旦发现有与背景色相差太大的像素点,即表示发现了目标方块,照着此颜色多找几个点,平均下得到方块的中心点。(也可直接用其他方法或用其他方式选取中点,看你自己研究了)

不过这样会有点问题,万一棋子高度大于目标方块就会有误,这在奶茶杯的方块会遇到。这时将棋子的颜色排除掉即可。总之原则就是根据色差找到目标中点。

具体实现

上面的介绍大致就知道了实现原理,由此可知重点是根据图片找到适合的中点。原则上讲只要有处理图片及像素的库的语言都可实现。python、go、java等均可。python处理图片更简单,下面用python简要实现。

寻找棋子中点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

width, height = image.size # image为图片实例
num = 0
sum_x = 0
sum_y = 0
s_height = int(height / 3) # 查找的起始高度
e_height = int(height / 5 * 4) # 查找的终止高度

for i in range(0, width, 10): # 宽度查找,步长为10
for j in range(s_height, e_height, 20): # 高度查找,步长为20
pixel = image.getpixel((i, j)) # 获取像素点
# print(pixel)
if (0x20 < pixel[0] < 0x40) \
and (0x20 < pixel[1] < 0x40) \
and (0x45 < pixel[2] < 0x80): # 比较是否在紫色棋子的颜色范围
r, g, b, a = pixel
# print('颜色是{},{},{}'.format(r, g, b))
# print('坐标:{},{}'.format(i, j))
num = num + 1
sum_x = sum_x + i
sum_y = sum_y + j
if num == 0: # 出错,停止
return DEFAULT_ERROR_DISTANCE
avg_x = int(sum_x / num) # 找出的点平均后得到中点
avg_y = int(sum_y / num)

print('棋子坐标为:{},{}'.format(avg_x, avg_y))

寻找方块中点

以下为寻找方块中点,原理是根据色差。具体:记录上一个像素点,当前像素点与上一个的比较,
若相差过大,表明找到了目标方块的第一个像素点(需排除是棋子的可能),记录在select_color里。
以后遍历时当前像素点就与select_color比较,相差不大则表明是目标方块的点,记录。
收集足够多的点或遍历完成后求中点即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    pre_px = None
h_num = 0
h_sum_x = 0
h_sum_y = 0
select_color = None
l_num = 0

flag = False

for j in range(s_h, e_h, 30):
for i in range(0, width, 30):
px = image.getpixel((i, j))
r, g, b, a = px
cap, l_num = compare_px(pre_px, px, select_color, l_num, i) # 比较
if not is_spot(px):
pre_px = px
if cap: # 若色差够大
h_num = h_num + 1
h_sum_x = h_sum_x + i
h_sum_y = h_sum_y + j
# print('颜色是{},{},{}'.format(r, g, b))
print('寻找的坐标:{},{}'.format(i, j))
if h_num == 1:
select_color = r, g, b, i
if l_num == 12: # 找到足够多的点,跳出循环
flag = True
if flag:
break
if h_num == 0: # 未找到,重新开始
return DEFAULT_ERROR_DISTANCE

h_avg_x = int(h_sum_x / h_num)
h_avg_y = int(h_sum_y / h_num)

print('棋盘坐标为:{},{}'.format(h_avg_x, h_avg_y))



# 比较函数
def compare_px(pre, cur, select_cl, like_num, x):
if pre is None: # 第一次查找
return False, like_num
else:
pr, py, pb, pa = pre
r, y, b, a = cur
if select_cl is None:
if (abs(pr - r) + abs(py - y) + abs(pb - b) > DEFAULT_GAP) \
and not is_spot(cur): # 若与上一个点色差过大且不是棋子
return True, like_num + 1 # 目标色点还未赋值,表明第一次发现色点
return False, like_num # 色差过大,未找到
else: # 则与目标色点比较,若相似且距离合适则表明又发现了一个色点
sr, sy, sb, sx = select_cl
if abs(sr - r) < DEFAULT_GAP \
and abs(sy - y) < DEFAULT_GAP \
and abs(sb - b) < DEFAULT_GAP \
and abs(sx - x) < DEFAULT_DISTANCE:
like_num += 1
return True, like_num
return False, like_num # 相差过大,不是上次选中的色点

后记

我将其简要实现放到了github上,有详细的注释及说明,地址在微信跳一跳辅助,感兴趣的同学可以去看看。一起谈探讨更好的实现。

参考

  1. python 微信《跳一跳》辅助
  2. Python编程快速上手 P333
  3. Android adb介绍
分享到:
0%