引子

啰嗦的部分,可以跳过

前几日入了阴阳师的坑,经过了前期的快速升级后,发现这个游戏真的是要肝啊。每天都是身体被掏空了。不知道大家有没有感觉,就是这个游戏吧,也不需要集中什么注意力,但是隔一会儿就要操作一下,没法集中精力干别的事情。阴阳师的操作也比较单一,于是去找找看有没有大神写好的脚本。果然人民群众想到我的前面去了,于是下了安卓虚拟机,上脚本,谁用谁知道,救了我的肝呀。奈何我的账号在苹果上,于是越狱下载,又是一顿折腾。终于在pad上也可以运行了。

但是,我很好奇这些脚本是怎么写的,发现了按键精灵。这里建议大家去官网上下载。因为,连官网下的都有一堆乱七八糟的软件啊!其他网站我就更不敢保证了。学了一会儿发现,这个软件确实很好用,很多操作都简化了,挺适合学习和理解编程的。但是导出文件的时候发现要加密导出的话还要注册会员,不然只能导出源文件......反正给我的感觉好用,但是不爽,算了,还是用python吧。

Python选定了之后,各种找资料,下库文件,心累。我还用的是python3,心都快碎了。说点感想,搜索资料的时候,最怕的就是作者以为我什么都懂,只是简单提了一句如何如何,可是臣妾真的不懂啊!所以,我尽力把过程写的详细些,让大家少走些弯路。虽然这个程序只写了两天,但是现在有些东西可能也忘了,如果有什么没说清楚的地方可以私信我。

正文

本文只是学术探讨,学术交流,交流.......网易爸爸不要找我

思路

1.模仿按键精灵的功能,抓取需要点击的位置的坐标,将鼠标移动过去后点击。可以解决妖气封印、御魂、石巨等只需要点击的功能。

2妖怪探索,需要将屏幕截图,然后通过一个图像识别(异常的简单,哈哈,我都佩服自己的机智),点击下面图标,进入交战界面。

程序实现

1先说实现鼠标点击的功能。

安装pyautogui这个库,注意自己的python版本(2.x还是3.x)和操作系统的位数(32/64位)。还会出现安装失败之类的各种问题,反正是一阵折腾。

使用pyautogui.moveTo()这个方法,把鼠标移动到制定的位置,比如将鼠标移动到屏幕的左上角就是pyautogui.moveTo(0,0)。pyautogui.click()实现单机左键。

把需要点击的位置在显示器上的位置都找好,我用的显示器是1920*1080的,所以以下代码只能运行在1920*1080的显示器上,且是最大化模拟器的窗口时各种需要点击地方的坐标,运行在其他平台的话需要相应的改变坐标。以下是实现妖气封印自动点击的代码。前提是登陆进去后人物不要移动,只在初始位置,点开下面的卷轴,如下图这样。然后运行程序,因为人物走动到其他位置后按钮的坐标就变化了。

import pyautogui

import time

#妖气封印函数

def yaoqi():

#点击组队

pyautogui.moveTo(424,904)

pyautogui.click()

time.sleep(2)

#点击妖气封印

pyautogui.moveTo(433,852)

pyautogui.click()

time.sleep(2)

start=time.clock()

while(True):

end=time.clock()

#刷新、加入,准备

pyautogui.moveTo(1116,907)

pyautogui.click()

time.sleep(0.1)

pyautogui.moveTo(1538,330)

pyautogui.click()

pyautogui.moveTo(1668,806)

pyautogui.click()

#判断运行时长

if int(end-start)==600:

break

#天雷鼓函数

def Tianlei():

#点击组队

pyautogui.moveTo(424,904)

pyautogui.click()

time.sleep(2)

#点击天雷鼓

pyautogui.moveTo(466,639)

pyautogui.click()

time.sleep(2)

start=time.clock()

while(True):

end=time.clock()

#刷新、加入,准备

pyautogui.moveTo(1116,907)

pyautogui.click()

time.sleep(0.1)

pyautogui.moveTo(1538,330)

pyautogui.click()

pyautogui.moveTo(1668,806)

pyautogui.click()

#判断运行时长

if int(end-start)==600:

break

if __name__ == '__main__':

yaoqi()

上面写了妖气封印和天雷鼓的函数,运行的是妖气封印的函数。需要注意的是,打完妖气封印后直接就退回到了主界面,也就是上图这个界面,还需要重新打开卷轴点击组队,然后运行。理想情况应该是继续打开卷轴开始新一轮的刷新。也蛮简单的,这里我们只做学术交流,点到为止,哈哈~

2妖怪发现部分,也就是探索部分。和前一步类似,通过和前面一样的确定坐标,我们一路点击进入了这个界面。

这里的难点在于点击怪物头上的交战符号进入交战。起初我是在这个交战符号附近的Y坐标的高度一路点过去若干个点,总能点到,如下图的红点。然后适当的延迟几秒后,等切换到下一个交战的界面后还是点点的老问题。

但是这样有一个问题,我不知道这页的妖怪什么时候打完了,为了保险,可以多循环几次。为了保险,设置循环六次,但是经常会出现这页只有一个妖怪,打完了之后,傻傻的等到循环结束后才走到下一个页面。

其实一开始我就想到了图像识别这个方法。在按键精灵中也有这个功能,在一张大图上面找出来指定的图案位置,然后将鼠标移动过去。然后我就找python中图像匹配的库,理论上只要在上图中找到下面这个图片,然后把鼠标移动过去,就能实现精准的点击了。

重点来了,我在网上找到的方案很多都是同尺寸图片进行比较,然后得出相似度,我这种需求的基本找不到答案。一番思考之后,我想出了下面这个方案:把大图切成若干个小图,这样尺寸的问题就解决了。然后每个小图和进行比较,选出相似度较大的方块,然后把鼠标移动到这个方块中点击。

但是这个方案我做到一半的时候发现,这个图像比较好像......比较....慢啊,之前我就担心这样的问题。在查找资料的时候就看到各种比较算法什么的,给我的感觉就是事情没有这么简单,什么神经学习,人工智能之类的,我只是写一个脚本啊,要不要这样。

于是乎我想到下面这个出奇简单的方法,速度奇快,勉强也能叫图像识别吧,哈哈!

如上图,这次我们只采集红点处的颜色信息,然后与目标颜色比较,途中交战图标的棕色的rgb颜色是(53,30,15),由于是个渐变色,我们只要设定一个大致的范围,比如R(50-70)G(30-40)B(10-30)这个区间,满足这个区间的采样点我们用鼠标去点击。适当的调整采样的间隔和颜色的偏差区间,可以得到满足准确点击的效果,同时也满足了对处理时间的要求。

下面是代码部分。有进入对战后点击准备和结束对战后点击奖励退出的部分,以及本页怪物打完后走到下一页的部分。很简单,没有什么难度。同时在找怪物时统计了本页怪物数量,打完后走到下一页,就不会傻傻呆着了,这一部分还没有认真测试,还能写的更好点。

from PIL import ImageGrab

from PIL import Image,ImageChops

import pyautogui

import time

#寻找怪物函数

def find():

k=0

#截图到交战图片

im=ImageGrab.grab((0,300,1920,600))

pix=im.load()

#网格取点,点击交战图标

for i in range(0,1920,30):

for j in range(0,300,30):

r,g,b=pix[i,j]

if 50

pyautogui.moveTo(i,j+300)

pyautogui.click()

k=k+1

return(k)

def Fight():

#对战部分

time.sleep(8)

pyautogui.moveTo(1668,806)

pyautogui.click()

#循环点击退出对战界面

for n in range(0,15):

pyautogui.moveTo(936,554)

pyautogui.click()

time.sleep(4)

def walkleft():

pyautogui.moveTo(137,695)

pyautogui.click()

time.sleep(3)

def walkright():

pyautogui.moveTo(1805,752)

pyautogui.click()

time.sleep(3)

if __name__ == '__main__':

num=1

while(num):

#num统计出页面的怪物个数,确定循环次数

num=find()

Fight()

#右走两次

walkright()

walkright()

num=1

while(num):

num=find()

Fight()

walkright()

walkright()

num=1

while(num):

num=find()

Fight()

walkleft()

walkleft()

num=1

while(num):

num=find()

Fight()