用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

在这里插入图片描述

 

posted @ 2021-02-18 22:27  BugMiaowu2021  阅读(171)  评论(0编辑  收藏  举报