Automating the WeChat Jump Game on Android Using ADB and Python
This guide explains how to set up ADB on a Windows PC, connect an Android device, capture screenshots, and run a Python script that detects the game pieces and board in WeChat's Jump mini‑program to automatically perform jumps based on calculated distances.
This article provides a step‑by‑step tutorial for automating the WeChat Jump mini‑game on Android devices. It begins with downloading the ADB debugging tools, extracting them without installation, and ensuring the device is in USB debugging mode so that the adb devices command lists the device as "device".
After confirming the connection, the user runs a Python script that first reads the screen resolution via adb shell wm size , loads a configuration file based on that resolution, and then captures a screenshot using one of several ADB screenshot methods.
The core of the automation is a set of image‑processing functions that locate the player's piece and the target platform by scanning pixel colors, handling different board shapes, and compensating for various visual artifacts. Once the coordinates are obtained, the script computes the Euclidean distance between the piece and the board, multiplies it by a calibrated press‑ratio, and issues an adb shell input swipe command with a random offset to simulate a human tap.
The main execution loop repeatedly captures a screenshot, extracts the piece and board positions, calculates the jump distance, selects a random press point, performs the swipe, and sleeps briefly before the next iteration. Debugging utilities can save intermediate screenshots for analysis.
Below is the complete Python source code used in the tutorial. All code is kept intact and wrapped in a single ... block as required.
def _get_screen_size():
"""
获取手机屏幕分辨率
:return:
"""
size_str = os.popen('adb shell wm size').read()
print(size_str)
if not size_str:
print('请安装 ADB 及驱动并配置环境变量')
sys.exit()
m = re.search(r'(\d+)x(\d+)', size_str)
if m:
return "{height}x{width}".format(height=m.group(2), width=m.group(1))
def init():
"""
初始化
:return:
"""
# 获取屏幕分辨率
screen_size = _get_screen_size()
config_file_path = 'config/{0}/config.json'.format(screen_size)
print(config_file_path)
if os.path.exists(config_file_path):
with open(config_file_path, 'r') as f:
print("Load config file from {}".format(config_file_path))
return json.load(f)
else:
with open('config/default.json', 'r') as f:
print("Load default config")
return json.load(f)
def get_screenshot():
global SCREENSHOT_WAY
if SCREENSHOT_WAY == 2 or SCREENSHOT_WAY == 1:
process = subprocess.Popen('adb shell screencap -p', shell=True, stdout=subprocess.PIPE)
screenshot = process.stdout.read()
if SCREENSHOT_WAY == 2:
binary_screenshot = screenshot.replace(b'\r\n', b'\n')
else:
binary_screenshot = screenshot.replace(b'\r\r\n', b'\n')
with open('autojump.png', 'wb') as f:
f.write(binary_screenshot)
elif SCREENSHOT_WAY == 0:
os.system('adb shell s creencap -p /sdcard/autojump.png')
os.system('adb pull /sdcard/autojump.png .')
def check_screenshot():
global SCREENSHOT_WAY
if os.path.isfile('autojump.png'):
os.remove('autojump.png')
if SCREENSHOT_WAY < 0:
print('暂不支持当前设备')
sys.exit()
get_screenshot()
try:
Image.open('autojump.png').load()
except Exception as e:
print(e)
SCREENSHOT_WAY -= 1
check_screenshot()
def find_piece_and_board(img, con):
w, h = img.size
# 棋子的底边界
piece_y_max = 0
scan_x_side = int(w / 8) # 扫描棋子的左右边界减少开销
scan_start_y = 0 # 扫描起始y坐标
img_pixel = img.load()
if not LOOP: # 是否循环游戏
if sum(img_pixel[5, 5][: -1]) < 150: # 根据屏幕黑色
exit('游戏结束!')
# 以50px 步长,尝试探测 scan_start_y
for i in range(int(h / 3), int(h * 2 / 3), 50):
first_pixel = img_pixel[0, i]
for j in range(1, w):
# 如果不是纯色,说明碰到了新的棋盘,跳出
pixel = img_pixel[j, i]
if pixel[0] != first_pixel[0] or pixel[1] != first_pixel[1] or pixel[2] != first_pixel[2]:
scan_start_y = i - 50
break
if scan_start_y:
break
# 从上往下开始扫描棋子,棋子位于屏幕上半部分
left = 0
right = 0
for i in range(scan_start_y, int(h * 2 / 3)):
flag = True
for j in range(scan_x_side, w - scan_x_side):
pixel = img_pixel[j, i]
if (50 < pixel[0] < 60) and (53 < pixel[1] < 63) and (95 < pixel[2] < 110):
if flag:
left = j
flag = False
right = j
piece_y_max = max(i, piece_y_max)
if not all((left, right)):
return 0, 0, 0, 0
piece_x = (left + right) // 2
piece_y = piece_y_max - con['piece_base_height_1_2']
# 限制棋盘扫描横坐标
if piece_x < w / 2: # 棋子在左边
board_x_start = piece_x + con["piece_body_width"] // 2
board_x_end = w
else:
board_x_start = 0
board_x_end = piece_x - con["piece_body_width"] // 2
# 从上往下扫描找到棋盘的顶点
left = 0
right = 0
num = 0
for i in range(int(h / 3), int(h * 2 / 3)):
flag = True
first_pixel = img_pixel[0, i]
for j in range(board_x_start, board_x_end):
pixel = img_pixel[j, i]
if abs(pixel[0] - first_pixel[0]) + abs(pixel[1] - first_pixel[1]) + abs(pixel[2] - first_pixel[2]) > 10:
if flag:
left = j
right = j
flag = False
else:
right = j
num += 1
if not flag:
break
board_x = (left + right) // 2
top_point = img_pixel[board_x, i+1]
for k in range(i + con["hight"], i, -1):
pixel = img_pixel[board_x, k]
if abs(pixel[0] - top_point[0]) + abs(pixel[1] - top_point[1]) + abs(pixel[2] - top_point[2]) < 10:
break
board_y = (i + k) // 2
if top_point[:-1] == (255, 255, 255):
print('药瓶图案')
board_y = (i + board_y) // 2
if num == 3:
if top_point[:-1] == (219, 221, 229):
print('唱片')
top = 0
bottom = 0
for k in range(i, i + con["hight"]):
pixel = img_pixel[board_x, k]
if pixel[:-1] == (118, 118, 118):
if not top:
top = k
else:
bottom = k
board_y = (top + bottom) // 2
return piece_x, piece_y, board_x, board_y
if not all((board_x, board_y)):
return 0, 0, 0, 0
return piece_x, piece_y, board_x, board_y
def jump(distance, point, ratio):
press_time = distance * ratio
press_time = max(press_time, 200) # 最小按压时间
press_time = int(press_time)
cmd = 'adb shell input swipe {x1} {y1} {x2} {y2} {duration}'.format(
x1=point[0],
y1=point[1],
x2=point[0] + random.randint(0, 3),
y2=point[1] + random.randint(0, 3),
duration=press_time
)
print(cmd)
os.system(cmd)
return press_time
def run():
oper = input('请确保手机打开了 ADB 并连接了电脑,然后打开跳一跳并【开始游戏】后再用本程序,确定开始?y/n>>:')
if oper != 'y':
exit('退出')
# 初始化,获取配置
config = init()
# 检测截图方式
check_screenshot()
while True:
# 获取截图
get_screenshot()
# 获取棋子,棋盘位置
img = Image.open('autojump.png')
piece_x, piece_y, board_x, board_y = find_piece_and_board(img, config)
ntime = time.time()
print(piece_x, piece_y, board_x, board_y, '------->')
distance = math.sqrt((board_x - piece_x) ** 2 + (board_y - piece_y) ** 2)
# 生成一个随机按压点,防止被ban
press_point = (random.randint(*config['swipe']['x']), random.randint(*config['swipe']['y']))
jump(distance, press_point, config['press_ratio'])
if DEBUG:
debug.save_debug_screenshot(ntime, img, piece_x, piece_y, board_x, board_y)
debug.backup_screenshot(ntime)
time.sleep(random.randrange(1, 2))
def test_scrennshot():
img = Image.open('autojump.png')
con = init()
res = find_piece_and_board(img, con)
print(res)
if __name__ == '__main__':
run()The script can be executed directly after installing the required Python libraries (Pillow, etc.) and ensuring that ADB is in the system PATH. Users are prompted to confirm that the device is ready before the automation loop starts.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.