1. 想法
阴阳师作为一个过气游戏,非常识时务的给觉醒、御魂和探索加上了官方的脚本(压了等级,估计御灵也有)。但问题就是,结界突破官方并没有加上脚本,而只有一个“锁定阵营”。所以就决定搞一个结界突破的脚本XD
2. 基本思路
我们先以个人结界突破为例子,如图:
我们选定三个特征点(红圈的位置),然后以这三个坐标为基准,基本上就可以搞定这九个结界的位置,在这里不多做赘述。我们主要想实现的是阴阳寮结界突破的脚本(寮突破加的经验又少,还不消耗突破券。多勋章或者是低等级的结界都有,简直是为我这种压级的所准备的XD)
好的,我们来看阴阳寮突破的界面,如图:
这里我们同样选择选择三个特征点(红圈)来定位。我们然后算出这三点坐标的平均坐标,大致就位于画面的中间位置,然后加上随机函数,这样大致模拟点按的就是绿色的区域。但这样还是有问题,如果我们人的头像就比较麻烦(这个我们后面在实现的时候会讲到)
点按之后界面就会变成这样,我们要做的就是识别出“挑战”这个按钮的位置然后点击
当然我们要保证已经锁上了阵营,点击“挑战”之后这样就不用手动点开始了
好的,当我们胜利之后,如果不进行操作,最后会到这样的位置:
这个地方很明显有一个打开的达摩(还是啥玩意儿orz)我们只有识别到黄圈的部分就可以了,然后随便按一下。
但如果输了的话,我个人认为用“薙魂”这个图标会比较好,不过旁边的“式神强化”什么的也都可以啦OwO,然后随便点一下就行了。
我在这里会考虑终止脚本(总不能一直输吧。。。不过倒也无所谓,阴阳寮突破每小时只有6次233)
基本脚本的思路就是这样的,下面就来看怎么实现吧OwO
3. 实现
需要的模块和模拟点按的实现什么的都在上一篇关于抽卡的脚本的文章里讲了,这里就不再赘述了
有了基本的思路,然后我们照着这个思路来写代码就可以了QWQ
- QAQ我还是加上我们要用的库吧(经某些同学提醒),另外我们还要装上adb(本来觉得上一篇提到过了就可以不提了orz)
import time # 延时,例如战斗完后会有一点动画效果
import cv2 # OpenCV的库,也就是我们图像识别要用到的
import lib.ats # 自己建的XD里面放的是Android操作的函数(点按,滑动,截图的操作,具体在我上一篇文章有提到)
import random # 随机数,防封号用的
import numpy as np #这个嘛orz。。。
- 首先是界面的识别
def base(sh):
img = cv2.imread(sh, 0)
template1 = cv2.imread('res/dorm_loc1.jpg', 0) # 我把所有的模板放到了Project里面的/res文件夹中
# 导入模板图片,还有template2 和template3 也是一样的操作
res1 = cv2.matchTemplate(img, template1, cv2.TM_CCOEFF_NORMED)
# 这里是匹配率 res2 和 res3 也是相同的代码
threshold = 0.75
pos1 = []
# 坐标的数组(吧)pos2 和 pos3 也是一样的操作
loc1 = np.where(res1 >= threshold)
for pt1 in zip(*loc1[::-1]): # 压缩
pos1.append(pt1)
# 对 pos2 和pos3 也是相同的操作
tapX = (pos1[0][0] + pos2[0][0] + pos3[0][0]) / 3
tapY = (pos1[0][1] + pos2[0][1] + pos3[0][1]) / 3
# 计算平均值,得出中心的坐标
tap_loc = [tapX, tapY] # 中心的坐标
return tap_loc
- 然后是随机点按(一个目标)
def tap_range(org_loc):
orgX = org_loc[0]
orgY = org_loc[1]
# 随机函数
tapX = orgX + random.uniform(-100, 600)
tapY = orgY + random.uniform(-300, 300)
# 真正点按的坐标
tap_loc = [tapX, tapY]
return tap_loc
- 识别“挑战”按钮并点击,这里的代码和前面的识别界面“特征点”的代码并没有什么区别
def start(sh):
# 导入截图和模板
img = cv2.imread(sh, 0)
template = cv2.imread('res/start.jpg', 0)
res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED) # 匹配
threshold = 0.7
pos = []
loc = np.where(res >= threshold) # 找到高于threshold的坐标
for pt in zip(*loc[::-1]):
pos.append(pt)
lib.ats.tap(pos[0][0], pos[0][1]) # 我们只取第一个,并点按
- 对于“胜利”“失败”和一不小心点到头像的情况和上面识别“挑战”都是差不多的
#前面的代码和上面的是一样的
# 判断是否出现这样的画面
if (res >= threshold).any():
# 点按或者返回某个值,例如:(配合主程序的条件语句)
return 1
- 我们把上面的函数按照顺序在main里面依次调用就行了QWQ
def main():
for i in range(6): # 因为寮突破每小时只有6个所以用for就行了
sh = lib.ats.screenshot()
tap_base = base(sh)
# 这里选择突破的目标
tap_loc = tap_range(tap_base)
lib.ats.tap(tap_loc[0], tap_loc[1])
# 判断是否错误点按
while lib.ats.screenshot():
sh = lib.ats.screenshot()
if special(sh) == 1: # 如果刚好点到了人的头像上。。。
# 重新选择突破的目标
# 重新执行上面选择突破的目标的代码即可
else:
break
# 这里要再次截图
start(sh) # 开始突破
# 重复截图,判断战斗是否结束
while lib.ats.screenshot():
time.sleep(1)
# 随机设定x1和x2
judge = lib.ats.screenshot()
if win(judge) == 1: # 赢的话
lib.ats.tap(x1, y1)
break # 仅仅是退出这个小循环
elif lose(judge) == 1: #输的话
lib.ats.tap(x1, y1)
break
# 退出这个小循环之后还有终止整个大循环
orz又是基本把所有代码都写出来了(不过还是省略了很多,直接copy过去肯定是不行的XD)
4. 思考
写完这个脚本之后,发现这个脚本和之前的脚本都会频繁的使用到cv2库中的某几个函数,所以想了一下干脆把那他们打包成函数直接调用,这样应该就省事很多OwO
# 如果我们识别图像后还要返回位置的话
def location(sh, tmp, thd): # 分别是原图片(路径),模板(路径),和threshold
img = cv2.imread(sh, 0)
template = cv2.imread(tmp, 0)
res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
threshold = thd
pos = []
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
pos.append(pt)
return pos
# 如果我们只要识别图像的话
def check(sh, tmp, thd):
img = cv2.imread(sh, 0)
template = cv2.imread(tmp, 0)
res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
threshold = thd
if (res >= threshold).any():
return 1
5. 总结
总体来说,这个脚本和上一个抽卡那个大同小异233
然后因为人懒,懒得写个人寮突破的脚本(反正原理都是一样的嘛OwO)
PS:说实话个人突破的那个九宫格其实还是相当麻烦的,因为寮结界突破后会直接掉到后面去,也就是说界面上一的都是没被突破的,但个人结界就不是这个情况QAQ
东西也放到Github了哦,同样有什么问题记得回复QWQ