登录 立即注册
查看: 13283|回复: 0

[使用经验] 微信跳一跳辅助制作原理及代码分析

[复制链接]

1156

主题

4183

帖子

4346

积分

超级版主

Rank: 8Rank: 8

积分
4346

逍遥会员章逍遥忠实勋章逍遥荣耀勋章逍遥达人勋章逍遥游戏玩家逍遥论坛达人逍遥新人资格章

发表于 2018-1-2 08:03:45 | 显示全部楼层 |阅读模式
原理说明
  • 将手机点击到《跳一跳》小程序界面;
  • 用 ADB 工具获取当前手机截图,并用 ADB 将截图 pull 上来
    adb shell screencap -p /sdcard/autojump.png    adb pull /sdcard/autojump.png .
  • 计算按压时间
  • 手动版:用 Matplotlib 显示截图,用鼠标点击起始点和目标位置,计算像素距离;
  • 自动版:靠棋子的颜色来识别棋子,靠底色和方块的色差来识别棋盘;
  • 用 ADB 工具点击屏幕蓄力一跳;
    adb shell input swipe x y x y time(ms)
安卓手机操作步骤
  • 安卓手机打开 USB 调试,设置》开发者选项》USB 调试
  • 电脑与手机 USB 线连接,确保执行adb devices可以找到设备 ID
  • 界面转至微信跳一跳游戏,点击开始游戏
  • 运行python wechat_jump_auto.py,如果手机界面显示 USB 授权,请点击确认
  • 请按照你的手机分辨率从./config/文件夹找到相应的配置,拷贝到 *.py 同级目录./config.json(如果屏幕分辨率能成功探测,会直接调用 config 目录的配置,不需要复制)
iOS 手机操作步骤
  • 运行安装好的 WebDriverAgentRunner
  • 将手机点击到《跳一跳》小程序界面
  • 运行脚本。有两种模式可供选择:手动辅助跳 和 自动连续跳
    • 手动辅助跳
      • 命令行运行python3 wechat_jump_iOS_py3.py
      • 依次点击弹出的窗口中的起始位置和目标位置,会自动计算距离后起跳
      • 根据起跳的精准情况更改python3 wechat_jump_iOS_py3.py中的time_coefficient参数,直到获得最佳取值
    • 自动连续跳
      • 拷贝./config/iPhone目录下对应的设备配置文件,重命名并替换到./config.json
      • 命令行运行python3 wechat_jump_auto_iOS.py
      • 会自动计算坐标并连续起跳,根据起跳的精准情况更改./config.json 中的press_coefficient参数,直到获得最佳取值


下面我们来看下这款辅助的制作原理及代码分析:
  • 这款辅助需要手机连接PC,PC通过adb命令对手机游戏界面截图,并保存在PC上。
  • PC端根据保存的图片进行处理(读取RGB值),获取棋子的位置,获取下一步棋盘的位置,然后利用"勾股定理"来计算出两点之间的距离,然后根据经验值计算出按压时间。
  • 通过adb命令模拟按压时间即可实现棋子的跳跃。

部分代码如下:
  • 通过adb命令截图,并复制到PC。

def pull_screenshot():
os.system('del autojump.png')
os.system('adb shell screencap -p /sdcard/autojump.png')
os.system('adb pull /sdcard/autojump.png .')
2. 查找棋子的坐标
# 以50px步长,尝试探测scan_start_yfor i in range(under_game_score_y, h, 50):last_pixel = im_pixel[0, i]for j in range(1, w):pixel = im_pixel[j, i]# 不是纯色的线,则记录scan_start_y的值,准备跳出循环if pixel[0] != last_pixel[0] or pixel[1] != last_pixel[1] or pixel[2] != last_pixel[2]:scan_start_y = i - 50break if scan_start_y:breakprint("scan_start_y: ", scan_start_y)# 从scan_start_y开始往下扫描,棋子应位于屏幕上半部分,这里暂定不超过2/3for i in range(scan_start_y, int(h * 2 / 3)):for j in range(scan_x_border, w - scan_x_border): # 横坐标方面也减少了一部分扫描开销pixel = im_pixel[j, i]# 根据棋子的最低行的颜色判断,找最后一行那些点的平均值,这个颜色这样应该 OK,暂时不提出来if (50 < pixel[0] < 60) and (53 < pixel[1] < 63) and (95 < pixel[2] < 110):piece_x_sum += jpiece_x_c += 1piece_y_max = max(i, piece_y_max)if not all((piece_x_sum, piece_x_c)):return 0, 0, 0, 0piece_x = piece_x_sum / piece_x_cpiece_y = piece_y_max - piece_base_height_1_2 # 上移棋子底盘高度的一半
3. 查找下一跳地盘的坐标
for i in range (int (h / 3), int (h * 2 / 3)):last_pixel = im_pixel[0, i]if board_x or board_y:breakboard_x_sum = 0board_x_c = 0for j in range(w):pixel = im_pixel[j, i]# 修掉脑袋比下一个小格子还高的情况的 bugif abs(j - piece_x) < piece_body_width:continue# 修掉圆顶的时候一条线导致的小 bug,这个颜色判断应该 OK,暂时不提出来if abs(pixel[0] - last_pixel[0]) + abs(pixel[1] - last_pixel[1]) + abs(pixel[2] - last_pixel[2]) > 10:board_x_sum += jboard_x_c += 1if board_x_sum:board_x = board_x_sum / board_x_c# 按实际的角度来算,找到接近下一个 board 中心的坐标 这里的角度应该是30°,值应该是tan 30°, math.sqrt(3) / 3board_y = piece_y - abs(board_x - piece_x) * math.sqrt(3) / 3if not all((board_x, board_y)):return 0, 0, 0, 0
4. 利用勾股定理计算两点之间的距离
math.sqrt((board_x - piece_x) ** 2 + (board_y - piece_y) ** 2)
5. 根据长度计算出按压时间
def jump(distance):press_time = distance * 1.35press_time = int(press_time)cmd = 'adb shell input swipe 320 410 320 410 ' + str(press_time)print(cmd)os.system(cmd)

CPU要支持虚拟化技术 主板开启VT 关闭Hyper-V 显卡驱动正确 完整系统
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|模拟器|手机模拟器|手游模拟器|安卓模拟器|( 沪ICP备14046591号 )

GMT+8, 2024-5-21 19:18 , Processed in 0.030062 second(s), 24 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表