用python玩微信跳一跳
游戏中:
跳一跳
源码及文件在文末,需要自取。
源码:
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 4 import os 5 import sys 6 import re 7 import json 8 import time 9 import subprocess 10 import random 11 from PIL import Image 12 import math 13 import debug 14 # 截图参数 15 SCREENSHOT_WAY = 2 16 # 是否循环游戏 17 LOOP = False 18 # 调试 19 DEBUG = True 20 21 22 def _get_screen_size(): 23 """ 24 获取手机屏幕分辨率 25 :return: 26 """ 27 size_str = os.popen('adb shell wm size').read() 28 print(size_str) 29 if not size_str: 30 print('请安装 ADB 及驱动并配置环境变量') 31 sys.exit() 32 m = re.search(r'(\d+)x(\d+)', size_str) 33 if m: 34 return "{height}x{width}".format(height=m.group(2), width=m.group(1)) 35 36 37 def init(): 38 """ 39 初始化 40 :return: 41 """ 42 # 获取屏幕分辨率 43 screen_size = _get_screen_size() 44 config_file_path = 'config/{0}/config.json'.format(screen_size) 45 print(config_file_path) 46 if os.path.exists(config_file_path): 47 with open(config_file_path, 'r') as f: 48 print("Load config file from {}".format(config_file_path)) 49 return json.load(f) 50 else: 51 with open('config/default.json', 'r') as f: 52 print("Load default config") 53 return json.load(f) 54 55 56 def get_screenshot(): 57 global SCREENSHOT_WAY 58 if SCREENSHOT_WAY == 2 or SCREENSHOT_WAY == 1: 59 process = subprocess.Popen('adb shell screencap -p', shell=True, stdout=subprocess.PIPE) 60 screenshot = process.stdout.read() 61 if SCREENSHOT_WAY == 2: 62 binary_screenshot = screenshot.replace(b'\r\n', b'\n') 63 else: 64 binary_screenshot = screenshot.replace(b'\r\r\n', b'\n') 65 with open('autojump.png', 'wb') as f: 66 f.write(binary_screenshot) 67 68 elif SCREENSHOT_WAY == 0: 69 os.system('adb shell s creencap -p /sdcard/autojump.png') 70 os.system('adb pull /sdcard/autojump.png .') 71 72 73 def check_screenshot(): 74 global SCREENSHOT_WAY 75 if os.path.isfile('autojump.png'): 76 os.remove('autojump.png') 77 78 if SCREENSHOT_WAY < 0: 79 print('暂不支持当前设备') 80 sys.exit() 81 get_screenshot() 82 try: 83 Image.open('autojump.png').load() 84 except Exception as e: 85 print(e) 86 SCREENSHOT_WAY -= 1 87 check_screenshot() 88 89 90 def find_piece_and_board(img, con): 91 w, h = img.size 92 # 棋子的底边界 93 piece_y_max = 0 94 scan_x_side = int(w / 8) # 扫描棋子的左右边界减少开销 95 scan_start_y = 0 # 扫描起始y坐标 96 # 图片像素矩阵 97 img_pixel = img.load() 98 if not LOOP: # 是否循环游戏 99 if sum(img_pixel[5, 5][:-1]) < 150: # 根据屏幕黑色 100 exit('游戏结束!') 101 # 以50px 步长,尝试探测 scan_start_y 102 for i in range(int(h / 3), int(h * 2 / 3), 50): 103 first_pixel = img_pixel[0, i] 104 for j in range(1, w): 105 # 如果不是纯色,说明碰到了新的棋盘,跳出 106 pixel = img_pixel[j, i] 107 if pixel[0] != first_pixel[0] or pixel[1] != first_pixel[1] or pixel[2] != first_pixel[2]: 108 scan_start_y = i - 50 109 break 110 if scan_start_y: 111 break 112 113 # 从上往下开始扫描棋子,棋子位于屏幕上半部分 114 left = 0 115 right = 0 116 for i in range(scan_start_y, int(h * 2 / 3)): 117 flag = True 118 119 for j in range(scan_x_side, w - scan_x_side): 120 pixel = img_pixel[j, i] 121 # 根据棋子的最低行的颜色判断,找最后一行那些点的平均值 122 if (50 < pixel[0] < 60) and (53 < pixel[1] < 63) and (95 < pixel[2] < 110): 123 if flag: 124 left = j 125 flag = False 126 right = j 127 piece_y_max = max(i, piece_y_max) 128 if not all((left, right)): 129 return 0, 0, 0, 0 130 piece_x = (left + right) // 2 131 piece_y = piece_y_max - con['piece_base_height_1_2'] # 上调高度,根据分辨率自行 调节 132 133 # 限制棋盘扫描横坐标 134 if piece_x < w / 2: # 棋子在左边 135 board_x_start = piece_x + con["piece_body_width"]//2 136 board_x_end = w 137 else: 138 board_x_start = 0 139 board_x_end = piece_x - con["piece_body_width"]//2 140 141 # 从上往下扫描找到棋盘的顶点 142 left = 0 143 right = 0 144 num = 0 145 for i in range(int(h / 3), int(h * 2 / 3)): 146 flag = True 147 first_pixel = img_pixel[0, i] 148 for j in range(board_x_start, board_x_end): 149 pixel = img_pixel[j, i] 150 # 20是色差阈值可以调节 151 if abs(pixel[0] - first_pixel[0]) + abs(pixel[1] - first_pixel[1]) + abs(pixel[2] - first_pixel[2]) > 10: 152 if flag: 153 left = j 154 right = j 155 flag = False 156 else: 157 right = j 158 num += 1 159 # print(left, right) 160 if not flag: 161 break 162 163 board_x = (left + right) // 2 164 top_point = img_pixel[board_x, i+1] # i+1去掉上面一条白线的bug 165 # 从上顶点往下 + con['hight'] 的位置开始向上找颜色与上顶点一样的点,为下顶点 166 # if num < 5: 167 # # 说明是方形 168 # if abs(top_point[0] - 255) + abs(top_point[1] - 228) + abs(top_point[2] - 226) < 5: 169 # print('唱片图案') 170 # top = 0 171 # bottom = 0 172 # for k in range(i, i + con["hight"]): 173 # pixel = img_pixel[board_x, k] 174 # # 根据唱片中的红色部分判断 175 # # if (155 < pixel[0] < 180) and (141 < pixel[1] < 165) and (113 < pixel[2] < 116): 176 # # print(pixel[0], pixel[1], pixel[2]) 177 # if (abs(pixel[0] - 239) < 3) and (abs(pixel[1] - 118) < 3) and (abs(pixel[2] - 119) < 3): 178 # 179 # if not top: 180 # top = k 181 # else: 182 # bottom = k 183 # # print(top, bottom) 184 # board_y = (top + bottom) // 2 185 # return piece_x, piece_y, board_x, board_y 186 187 # 该方法对所有纯色平面和部分非纯色平面有效 188 # print(top_point) 189 for k in range(i + con["hight"], i, -1): 190 pixel = img_pixel[board_x, k] 191 # print(pixel) 192 if abs(pixel[0] - top_point[0]) + abs(pixel[1] - top_point[1]) + abs(pixel[2] - top_point[2]) < 10: 193 break 194 board_y = (i + k) // 2 195 196 if num < 5: 197 # 去除有些颜色比较多的误差 198 199 if k - i < 30: 200 print('酱红色433----》》》') 201 board_y += (k - i) 202 203 # 去掉药瓶 204 205 if top_point[:-1] == (255, 255, 255): 206 print('药瓶图案') 207 board_y = (i + board_y) // 2 208 209 # 去掉唱片 210 if num == 3: 211 if top_point[:-1] == (219, 221, 229): 212 print('唱片') 213 top = 0 214 bottom = 0 215 for k in range(i, i + con["hight"]): 216 pixel = img_pixel[board_x, k] 217 # 根据唱片中的红色部分判断 218 # if (155 < pixel[0] < 180) and (141 < pixel[1] < 165) and (113 < pixel[2] < 116): 219 # print(pixel[0], pixel[1], pixel[2]) 220 if pixel[:-1] == (118, 118, 118): 221 222 if not top: 223 top = k 224 else: 225 bottom = k 226 # print(top, bottom) 227 board_y = (top + bottom) // 2 228 return piece_x, piece_y, board_x, board_y 229 230 if not all((board_x, board_y)): 231 return 0, 0, 0, 0 232 233 return piece_x, piece_y, board_x, board_y 234 235 236 def jump(distance, point, ratio): 237 press_time = distance * ratio 238 press_time = max(press_time, 200) # 最小按压时间 239 press_time = int(press_time) 240 cmd = 'adb shell input swipe {x1} {y1} {x2} {y2} {duration}'.format( 241 x1=point[0], 242 y1=point[1], 243 x2=point[0] + random.randint(0, 3), 244 y2=point[1] + random.randint(0, 3), 245 duration=press_time 246 ) 247 print(cmd) 248 os.system(cmd) 249 return press_time 250 251 252 def run(): 253 oper = input('请确保手机打开了 ADB 并连接了电脑,然后打开跳一跳并【开始游戏】后再用本程序,确定开始?y/n>>:') 254 if oper != 'y': 255 exit('退出') 256 # 初始化,获取配置 257 config = init() 258 # 检测截图方式 259 check_screenshot() 260 while True: 261 # 获取截图 262 get_screenshot() 263 # 获取棋子,棋盘位置 264 img = Image.open('autojump.png') 265 piece_x, piece_y, board_x, board_y = find_piece_and_board(img, config) 266 ntime = time.time() 267 print(piece_x, piece_y, board_x, board_y, '------->') 268 distance = math.sqrt((board_x - piece_x) ** 2 + (board_y - piece_y) ** 2) 269 # 生成一个随机按压点,防止被ban 270 271 press_point = (random.randint(*config['swipe']['x']), 272 random.randint(*config['swipe']['y'])) 273 jump(distance, press_point, config['press_ratio']) 274 if DEBUG: 275 debug.save_debug_screenshot(ntime, img, piece_x, piece_y, board_x, board_y) 276 debug.backup_screenshot(ntime) 277 time.sleep(random.randrange(1, 2)) 278 279 280 def test_scrennshot(): 281 282 img = Image.open('autojump.png') 283 con = init() 284 res = find_piece_and_board(img, con) 285 print(res) 286 287 # def test_time_ratio(): 288 # config = init() 289 # 290 # 291 # get_screenshot() 292 # img = Image.open('autojump.png') 293 # piece_x, piece_y, board_x, board_y = find_piece_and_board(img) 294 # print(piece_x, piece_y) 295 # point = (random.randint(*config['swipe']['x']), 296 # random.randint(*config['swipe']['y'])) 297 # t = 600 298 # 299 # cmd = 'adb shell input swipe {x1} {y1} {x2} {y2} {duration}'.format( 300 # x1=point[0], 301 # y1=point[1], 302 # x2=point[0] + random.randint(0, 3), 303 # y2=point[1] + random.randint(0, 3), 304 # duration=t 305 # ) 306 # print(cmd) 307 # os.system(cmd) 308 # time.sleep(2) 309 # get_screenshot() 310 # img = Image.open('autojump.png') 311 # piece_2x, piece_2y, board_2x, board_2y = find_piece_and_board(img) 312 # 313 # print(piece_2x, piece_2y) 314 # print(t/math.sqrt((piece_x-piece_2x)**2+(piece_y-piece_2y)**2)) 315 316 if __name__ == '__main__': 317 run() 318 # test_time_ratio() 319 # test_scrennshot() 320 # get_screenshot() 321 # check_screenshot()
食用指南:
-
测试PC安装ADB调试工具,用于和Android设备交互,主要完成截图,截图下载,进行按压屏幕模拟。
下载地址:
https://dl.pconline.com.cn/download/359035.html
下载后放到合适的位置解压,不要安装。在Win10中,系统目录和之前有所不同,所以旧的安装方法是无效的。
-
Android设备通过USB连接到测试PC,Android 设备开启调试模式,需要保证ADB能正常和Android连接。
在命令行中进入解压后的目录,输入
Adb devices
如果看到CMD显示一串字符,后面还有一个“device”的字样,那就说明安卓机已经成功以USB调试的形式连接到了Win10中。
- Android 进入微信跳一跳小程序并开始游戏;
- 在PC上运行脚本程序,脚本程序正常运行,输入y,开始自动游戏。
游戏截图:
源码及文件下载
链接:https://pan.baidu.com/s/1SVtrPh3zTp-I1AtNAbKNLA
提取码:n9w0