明日方舟脚本1.0(python\\adb\\cv2)

会有一股神秘感。 提交于 2020-04-07 16:45:32

一、目的

《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))

注:本博客仅供学习交流,严禁其他非法用途。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!