open函数返回-1_Python学习笔记:人生苦短,Python脚本代肝手游(1)

感觉北大夏校学Python真的是太赚了,虽然课程难度不低,一周上手到对封装过的单片机进行编程,但是真的学到很多东西,成功入门。

可以来围观下我的小组作业:

https://www.bilibili.com/video/av58643734/​www.bilibili.com

封面是自己画的,六月份学了一段时间矢量绘画。网上教程和优秀作品都很多,作为萌新在此就不细说。

今天讲的是关于一个简单手游脚本的制作想法,由于网上的资源又杂又乱,我遇到了不少坑,比较粗糙的制作了一个个人用的脚本,写完后便想总结下。

软件:蓝叠模拟器(海外版)

游戏:明日方舟

环境:Python 3.7

库:pillow,pyautogui

编辑器:VS Code

选择方舟的原因是因为设计比较简单,同时也是我比较喜欢的游戏。前后我折腾了两个版本,让我在此慢慢道来。

关于模拟器多说一句,像mumu和tx的,鼠标事件是没办法在上面触发的,可能已经把win32api屏蔽,所以我选择了能响应鼠标事件的叠蓝,而海外版是因为少了广告且版本比较新。还有种头铁的解决方案就是模拟驱动级的鼠标事件,当然这个难度可比换个模拟器高多了。

思路一:

获取屏幕图像→用事先准备好的按钮截图进行比较→获取按钮中心坐标→鼠标移动到中心坐标(并在一个范围内随机移动,防止每次点击位置相同)→点击

用于这种图片比较的,我第一个想到的是opencv,当然这个库的学习略难,于是我查询到了pyautogui这个相对很傻白的库。这个库的特点是能同时对图像进行跟踪并且控制鼠标。

ba3dad0a8b1e2736f60f3b16ee77658e.png

5-9行的代码依据个人需要写,a的+1或-1是为了控制随机生成数值的+-,并让鼠标在指定像素大小的方框内移动,可以不写。

pyautogui.locateOnScreen('PictureName',grayscale=True/Flase) 便是我们要用到的核心函数.已经准备好的按钮jpg,是和脚本同目录的,所以不需要再加路径,便可直接读取。grayscale是灰度滤镜,开启后可以提高识别速度,当然可以不开。

该函数判断失败的时候返回的是None,很多网上的博客教程解释返回的并不是这个,这是错误的解释。因此只要判断返回的是不是None就可以知道是否有需要的按钮。

这个函数会返回屏幕上与样本图相同区域的一组坐标,这里我用‘lct’进行了记录,即左上和右下。再通过pyautogui.center修正,我们便可以得到这个区域的中央点。

之后,x坐标和y坐标我分别进行了赋值,这样便可以分别对两个数值进行随机的调整。

.moveTo函数可以将鼠标直接移动到指定的坐标,.moveTo(x,y,time),最后的时间,是以秒计算,看个人需求。

.click便是让鼠标做出左键按下的动作。

如此一步便完成了,方舟的副本从开始到结束需要三次点击,如法炮制对于三个画面完成三次点击,这三步做成一个循环,不符合就跳过,符合则点击,即可。

问题一:

这样的方案看似不错且智能,甚至可以换着副本刷,但是问题来了——.locateOnScreen()要求两张实例与样本必须一模一样,只要有一个像素的变换,就识别不出来,且没有容差的选项。

这个问题直接导致了,当我刷A副本可行,但是换到B副本就不行,就算是眼睛看不出来的变化,也没办法识别成功。有时候甚至是重新开下模拟器也会识别失败,于是每次刷的时候,还要重新截图替换样本,实在是......有点失败。

思路二:

获取指定区域图像→处理图像→图像比较→点击

这个思路主要依托的是pillow库的特性,在指定坐标区域截图然后比较样本。当然,这样也意味着模拟器不能有任何的改变,无论是分辨率还是位置。

因为要提前准备坐标,所以要先手动确定,这个我用的是affinity/ps完成的。如图所示:

f2e1426d8315350e9d4e585dbd838018.png
用标尺功能去测量按钮

同理,测量三组数据。

测量时候也记得要使用代码进行截图,我们需要将截获的图片转换为灰度图,这样操作起来会方便不少(信息量大幅度减少)。

dd4b30b5ac9cf4e4708af4a2170b4977.png

box是一个数组,你可以不用单独列出,我这样写只是为了看着舒服。.grab是区域内指定截图用的函数,后面跟坐标。

im是对于仍在内存中的数据进行命名,你可以用其他名字比如pho,im2等。程序如果直接关闭,im将不会保留。

.convert("L")是将图片转换成灰度图。

.save是保存图片用函数,命名的时候直接跟上后缀,推荐png。我们只需要样本,正式的脚本中我们并不需要保存任何的图片,因为都是作为临时图片与样本做比较。

接下来我们对图片进行简单计算处理:

576cd98de7f55704783e7d96c0b96f28.png

由于对于python学习不够深入,这里写的算法很白痴

.size原本会直接输出图片的长和宽,而.size[0]会输出横向的长度,同理[1]输出纵向长度,不要弄反了,否则下面的函数会输出超出坐标。

.getpixel(x,y)会输出指定坐标的像素信息,对于灰度图,只会输出0-256其中的数值(灰度)。而对于正常的彩色图,是同时输出(R,G,B)一个三元数组,当然每个值对应的也是在[0,256]这个范围内的。

我们将所有的灰度值全部加起来,然后计算平均灰度。

接下来是我一个偷懒的地方,虽然会大幅度降低准确度,但是对于这种简单需求脚本而言能勉强够用。

我们再一次读取每个像素的数值,并且跟平均值比较,大于平均值就进行计数,否则不计数。图中的result就是计数结果,最后我们可以根据两个图片数值大小,通过比较来确认两张图片是否相似。

读取之前制作好的样本图的时候,要用到Image.open('name.png')函数,这样样本就可以载入到内存。

48393ca8685cc675ec14785f56c42978.png
代码写得有些冗余,不过后来懒得改

我测出来适合我的阈值是0.46到0.52之间比较准确。我这里输出的是0或1代表真假,想输出什么都可以。

但是,这个方法有时候如果在过场中遇到统计值相似的图片,无论像不像,肯定百分百判断失误。

所以一个改进方法便是,当灰度值与平均值比较的时候,大于平均值记为1,否则为0,然后将这一串数据记录为像(1,1,1,1,1,1,1,0,0,0,1,1,0,......)数列,将两张图片的数列进行比较,数列的吻合比例>X%(如70)就判断为合格。这样的话能够大幅度减少误判。

e3d54bfa9cf698cf0942489903a55f0c.png

将上面的程序用def打包,此处我将打包的程序命名为"Getresult",后面是坐标和需要比较的文件参数,整个程序就是while循环,每一步都是其中的一个次级循环,完成一步后才可以进行下一步,如果def程序输出为假,该次级循环继续,为真,进入下一个次级循环。

这里鼠标控制我仍然使用pyautogui,因为win32gui写得略微繁琐,何况pyautogui就是win32api封装的而已。

次级循环结束后的time.sleep()其实是个无奈之举,因为我写的算法并不准确,为了防止在过场动画时候对画面进行判断,便在执行后等待过场动画结束。实际上共计三个画面需要循环的点击,意味着三次有效的停顿还是需要的。

由此,程序已经基本完成了。

下面展示下主体部分:

5607472cd061b2856e678a0ef13b6b28.png
def打包部分

b0e4feeb57a9901411ac6ba225ee1e50.png
clock是计数用的自定义函数,每次大循环结束的时候输出一次,这样我知道采集几次

总的来说,为了更方便的刷游戏,学习更加高级的opencv等的图形判断库和相关的算法,还是非常有必要的,各位Doc继续努力吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值