微信跳一跳辅助代码分析
前言:
最近微信跳一跳挺火的,身边的朋友都在玩,偶然想到能否用python写一个辅助工具实现自动跳一跳呢?上网查阅相关资料时才发现已经有大神在github上发布了用python+opencv制作的跳一跳辅助,这里对其中的一个简单版本稍加修改后进行分析。
Ps:利用边缘检测的那个版本以后再讲解。
准备工具:
Adb
Python3.0 & OpenCV库
一部手机
外挂原理:
外挂的整体原理是利用adb命令截取手机游戏时的图片,再利用opencv提供的方法找到所截取图片中的棋子的位置,当用户点击跳跃目的地,计算棋子位置和跳跃目的地的两点间的距离,最后利用adb发送跳跃命令。
那么这就产生了两个关键问题:
1. 怎么确定棋子的位置
2. 怎么计算点击位置和棋子位置间的距离
只要解决上述两个问题基本上就能完成整个外挂的制作了
源码:
import os import time import datetime import matplotlib.pyplot as plt import matplotlib.animation as animation import cv2 import serial #ser = serial.Serial("COM3", 9600) def pull_screenshot(): os.system('adb shell screencap -p /sdcard/autojump.png') os.system('adb pull /sdcard/autojump.png .') def jump(distance): press_time = distance * 1.35 press_time = int(press_time) cmd = 'adb shell input swipe 320 410 320 410 ' + str(press_time) #要换成串口发送信息 print(cmd) #print("ready send data to serial of arduino") #ser = serial.Serial("COM3", 9600) #time.sleep(2) #ser.write(press_time) #print("sent finish close serial") #ser.close() os.system(cmd) #执行屏幕点击命令 def search(img): result = cv2.matchTemplate(img, template, cv2.TM_SQDIFF) #(原图,匹配模型,匹配算法) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) cv2.rectangle( img, (min_loc[0],min_loc[1]), (min_loc[0] + template_size[1], min_loc[1] + template_size[0]), (255, 0, 0), 3 ) return img, min_loc[0] + template_size[1] / 2, min_loc[1] + template_size[0] def update_data(): global src_x, src_y img = cv2.imread('autojump.png') img = cv2.resize(img, (0, 0), fx=scale, fy=scale) img, src_x, src_y = search(img) return img def updatefig(*args): global update if update: time.sleep(1) #避免刷新过快 pull_screenshot() #截屏,做好准备工作 im.set_array(update_data()) #注意返回元组而不是数组 update = False #点击响应后update = True return im, def on_click(event): global update dst_x, dst_y = event.xdata, event.ydata distance = (dst_x - src_x)**2 + (dst_y - src_y)**2 distance = (distance ** 0.5) / scale jump(distance) update = True print('distance = ', distance) scale = 0.25 update = True template = cv2.imread('E:\\example.png') #棋子图像,即"小明照" template = cv2.resize(template, (0, 0), fx=scale, fy=scale) template_size = template.shape[:2] #模型训练目标的w,h(长和宽) fig = plt.figure() fig.canvas.mpl_connect('button_press_event', on_click) img = update_data() im = plt.imshow(img, animated=True) ani = animation.FuncAnimation(fig, updatefig, interval=1, blit=True) #动态更新窗口 plt.show()
先对各个函数功能模块作用进行讲解吧:
1.def pull_screenshot():
利用adb工具截取手机屏幕,并把图片移动到工程的根目录下。
当运行这个函数后,工程中会出现一个autojump.png文件,这个就是手机当前的截图文件。
2.def search(img):
这个函数的功能是从截图中找到棋子,并且把找到的棋子用红色的矩形线条圈起来,返回棋子所在点的位置(x,y)。
这个函数也是解决问题1的关键,即怎么确定棋子的位置,它调用了OpenCV提供的matchtemplate(),就是用该方法找到棋子的位置的。
Matchtemplate函数的使用方法:cv2.matchtemplate(input_image, template_image, cv2.TM_SQDIFF) ,怎么理解函数中的三个参数呢(input_image和template_image是图片对象),举个例子,我从来没见过小明,但是我有一张小明的照片和他的班级照,我现在要做的是把小明从班级照中圈出来,matchtemplate做的也是这个工作input_image就是“班级照”,template_image是“小明照”而已。嗯,这个工作交个人来做或许相对简单,可是交给计算机做就不那么简单了,cv2.TM_SQDIFF是匹配过程采用的5种算法之一,感兴趣的可以去查阅相关资料,这里不再复述。
Cv2.rectangle()的作用是把匹配到的棋子在截图中用矩形方框圈起来,函数使用也相当简单,使用方法这里不再复述。
3.def on_click(event):
设置点击事件,当鼠标指针点击屏幕的某一位置时,获取该位置的坐标,计算该位置与棋子位置的距离(两点间的距离公式),调运下面的jump()函数发出跳跃命令。这里就解决了第2个问题,即怎么计算点击位置和棋子位置间的距离。
4.def jump(distance):
distance是两点间的距离,该函数模块利用adb发出跳跃指令,但玩过跳一跳的朋友都知道游戏中并没有直接输入跳跃距离的选项,而是根据按压时间来决定棋子跳跃的距离,令人高兴的是在游戏中按压时间和跳跃距离这两者之间的关系是线性的,即passtime = distance * k,k是常系数,k会因为手机屏幕的分辨率不同而变化,经过本人手机测试k = 1.35,所以当你使用该外挂时跳跃距离没有达到预期时,看看是不是k的问题。
5.def update_data():和def updatefig(*args):
用于完成部分准备工作以及动态更新窗口,这里不再复述。
结果展示:
运行python代码后:
手机当前显示:
鼠标点击绿块中心后:
点击后手机屏幕显示:
注意事项:
1. 不要跳太高分,会被检测。
2. 代码template=cv2.imread(‘E://example.png’),这句为创建“小明”照片对象,看到这里不要再问我小明是谁了。
3. 第一次运行代码是可能会出错,那是因为工程中没有autojump.png这个文件,这时随便把一张图片改名为autojump.png放入工程中即可,不影响结果。