一、目的
《Python从入门到实践》第14章拉拉杂杂“抄”完,急于练手,便捡起以前一直想写却没写完的“鼠标键盘模拟”程序。
二、思考

图1.0 auto_game思考方向
如图1.0,思考了两种实现方法。
第一种方法是在电脑层面模拟电脑鼠标点击。使用pyautogui库实现之后,MUMU模拟器内运行游戏并未做出相应反应。更换20180111版本MUMU,仍然不成功。如果仍想采用这种思路,就需要更换模拟器软件,或者采用驱动级鼠标键盘模拟。本文对此不再进行讨论。
第二种方法通过使用adb命令控制安卓手机实现。下面对第二种方法予以讨论。
(一)模拟过程
如图1.1所示,明日方舟1-7刷图可以分为三个部分:开始(①、②)、等待(③)、结束(④)。

图1.2 1-7刷图过程
1.开始阶段(①、②)
需要在两个特定位置(“开始行动”)点击两次。
2.等待阶段(③)
需要等待一段时间。
3.结束阶段(④)
需要在除“获得物品”之外的其他地方点击一次。
(二)实现思路
1.判断当前游戏阶段
使用adb命令截图,cv2判断特定图形出现在截图中的可能性,超过阈值,即为出现特定场景。
2.特定场景时发出点击命令
3.点击位置伪随机
4.点击时间间隔伪随机
5.特殊情况
开始阶段的①、②两图需要点击的按钮范围存在重合部分。可以将两次独立的判断后点击合并为:判断出现场景①后,点击两次。
结束阶段的④图,只需要在屏幕的上半部分点击一次即可。
三、实现过程
(一)安装cv2

图2.0 opencv-python安装过程
安装cv2实际上是安装opencv-python。不推荐使用pip指令安装,因为那样下载速度感人。建议图2.0所示,先去下好whl包,本地安装。
(下载地址:https://pypi.org/project/numpy/ https://pypi.org/project/opencv-python/ )
(二)连接安卓设备
本文使用MUMU版本为:2.3.4(0327192208)
1.找到adb

图2.1 adb_server
如图2.1,MUMU模拟器默认的adb位置为:MuMu\emulator\nemu\vmonitor\bin
2.修改环境变量

图2.2 打开环境变量
>此电脑>属性>高级系统设置>环境变量,双击Path更改:添加进adb_server所在的文件路径。
3.连接
对于windows系统,MUMU默认的连接端口为:127.0.0.1:7555
在命令行窗口输入指令:>adb_server connect 127.0.0.1:7555

图2.3 连接成功
(三)编写程序
1.框架

图3.0 auto_game框架
如图3.0 所示,程序分为4部分:setting(包含Settings对象)、robot_functions(包含一些操作函数)、robot(包含Robot对象)、main(主函数auto_game)。
2.setting.py
1 import cv2
2 class Settinigs:
3 """表示机器人参数设置的类"""
4 def __init__(self):
5 #机器人玩游戏局数
6 self.num = 30
7 #机器人可点击屏幕区域范围
8 self.clickx = [830,935]
9 self.clicky = [500,515]
10 self.t_start = cv2.imread("./pictures/t_start.png")
11 self.t_end = cv2.imread("./pictures/t_end.png")
3.robot_functions.py
1 import os
2 import cv2
3 import time
4 import random
5
6
7 def execute(cmd):
8 #构造并执行adb命令
9 str = "adb_server shell {cmdStr}".format(cmdStr=cmd)
10 # print(str)
11 os.system(str)
12
13 def click(x, y):
14 #点击像素点
15 click_order = 'input tap {} {}'.format(x, y)
16 execute(click_order)
17
18 def get_randpoint(x,y):
19 px = random.randint(x[0], x[1])
20 py = random.randint(y[0], y[1])
21 return px,py
22
23 def sleep_randtime(min,max):
24 time.sleep(random.uniform(min,max))
25
26 def match(img,template):
27 """计算图像中包含模板的最大可能性,取值范围0~1"""
28 res = cv2.matchTemplate(img,template,cv2.TM_CCOEFF_NORMED)
29 return res.max()
30
31 def shot_screen(img_name):
32 """截屏并命名为img_name,返回图片"""
33 shot_order = "screencap -p /storage/emulated/0/Pictures/{name}.png".format(name = img_name)
34 execute(shot_order)
35 poll_order ="adb_server pull /storage/emulated/0/Pictures/{name}.png ./pictures/{name}.png".format(name = img_name)
36 #因为拉取命令格式特殊,直接用os
37 os.system(poll_order)
38 res = cv2.imread("./pictures/{name}.png".format(name = img_name))
39 return res
40
41 def shot_match(img_name,template):
42 #截屏命名为img_name,img_name与template匹配,成功返回True,失败返回False
43 n = 0
44 while n < 15:
45 img1 = shot_screen(img_name)
46 res = match(img1, template)
47 if res > 0.97:
48 print("-Matched {} times.".format(n+1))
49 return True
50 else:
51 sleep_randtime(0.8, 1.2)
52 n += 1
53 print("-Match failed.")
54 return False
4.robot.py
1 import robot_functions as rf
2
3
4 class Robot():
5 def __init__(self,settings):
6 self.settings = settings
7
8 def start(self):
9 #截屏并匹配
10 rf.shot_match("img1",self.settings.t_start)
11 #延时点击区域内随机点两次
12 x,y = rf.get_randpoint(self.settings.clickx,self.settings.clicky)
13 rf.click(x,y)
14 rf.sleep_randtime(0.8,1.5)
15 rf.click(x, y)
16
17 def waiting(self):
18 print("-Waiting......")
19 rf.sleep_randtime(79.0,81.0)
20
21 def end(self):
22 #截屏并匹配
23 if not rf.shot_match("img2",self.settings.t_end):
24 print("Game over.")
25 return False
26 x, y = rf.get_randpoint([0,1023],[0,250])
27 rf.click(x, y)
28 rf.sleep_randtime(1.8, 2.0)
29 return True
5.auto_game.py
1 from robot import Robot
2 from settings import Settinigs
3
4
5 settings = Settinigs()
6 n = 0
7 for n in range(settings.num):
8 robot = Robot(settings)
9 robot.start()
10 robot.waiting()
11 if not robot.end():
12 break
13
14 print("Done {} times.".format(n+1))
15 print("Consumed {} sanity.".format((n+1)*6))
注:本博客仅供学习交流,严禁其他非法用途。
来源:https://www.cnblogs.com/alas/p/12653133.html