@cndy1860
2020-08-27T01:28:41.000000Z
字数 5142
阅读 1131
叉叉助手
框架
自适应分辨率
控件锚点
因一些原因此项目在很长一段时间里没有进行维护,最近整理了一下一直未更新的新版的代码重新上传。
本意是想开发一个自用的简洁并尽可能通用的框架,但在没有开发过其他游戏脚本的情况下,直接以实况手游为蓝本进行开发难免会导致很多地方以适应这个游戏为主,且易有疏漏,仅供参考。
目前手游脚本的实现主要是在多级界面之间不断的跳转,并在其间穿插各状态判定和逻辑操作,流程模式大致可以归结为:界面-->>事件-->>界面-->>事件...本项目即是依据此模型构建的一个的基本框架。
目前流行的框架基本上采用了在每个界面上锚定控件位置,然后在每个控件上加上一个简单的事件(多为tap点击操作),添加一个任务只需要依次列出界面和对应要点击的控件,这样的好处是逻辑简单,对于只需要在各级界面跳转和简单点击的游戏,当然是一个不错的选择,但是对于在各级界面跳转间有复杂情况的游戏来适用性并不高,此框架即是为能适应复杂跳转情况而构建。
本项目以实况足球手游为示例演示开发一个完整的task
。
CFG
,为全局定义一个完整的脚本任务task
由一系列流程processes
组成,而流程又由多个流程片process
组成,每一个流程片由流程片初始界面page
和事件函数actionFunc
,以及等待page
到来期间执行的等待函数waitFunc
组成。
run
方法首先会从taskList
中提取对应的processes
,然后以process
为单位具体执行。程序首先会等待流程片初始界面page
的到来,期间有可能执行waitFunc
,但并不关心之前的任何流程,然后开始执行流程片的具体的逻辑操作函数actionFunc
,执行完成后释放流程片控制权,同时不关心后续流程。
注:GFM可能不支持流程图,如不支持可自行COPY代码在其他工具上查看
skipStatus
属性来控制是否跳过流程片根据是否为首次运行,是否为断点任务,当前界面是否存在可跳过的情况来设置skipStatus
。
在脚本运行期间,如果流程中某一个流程片界面没有出现,或者因为用户主动点击了一下歩而跳过了某一个流程片,那么在循环等待的过程中,如果等待时间超过CFG.WAIT_CHECK_SKIP
,流程函数将尝试判定是否可以执行跳过流程片的处理。判定原则是:当前的界面CURRENT_PAGE
符合当前流程片之后的某个流程片的界面PROCESS_PAGE
,那么就判定从CURRENT_PAGE
至PROCESS_PAGE
(不包括PROCESS_PAGE
本身)为可跳过界面,设置skipStatus
属性为true,并直接跳转到PROCESS_PAGE
继续执行流程。
通过skip机制,可以让脚本可以从流程中的任何一个界面开始任务,主要解决以下问题:
比如流程为{A,B,C,D,E,F,G}
,以界面A跳转至界面B为例:
if catchPage(PAGE_B) == PAGE_B then nextAction end
这样在捕获到界面B以前,将会忽略掉其他所有的界面,避免造成干扰
while
catchPage({PAGE_B, PAGE_NOTICE}, {points_contract, points_energy})
if PAGE_B then break --出口
if PAGE_NOTICE then closeNotice()
if PAGE_points_contract then chargeContract()
if PAGE_points_energy then chargeEnergy()
end
nextAction
你可能会注意到,catchPage机制其实同样能实现skip的效果,那如果抉择呢?skip效果的触发,是需要经过等待CFG.WAIT_CHECK_SKIP
时间后才进入检测是否发生的流程,一般为3s以上,如果把一个极低概率才会出现的界面用skip机制处理,会导致每次运行到那个流程片均需要等待CFG.WAIT_CHECK_SKIP
的时间才能跳过,增加了流程的大量的等待时间,但使用catchPage则无需等待延时,出现任何一个列出的界面即可马上响应。
从本质上来说,catchPage机制就是一个无延时的,功能加强版本的skip机制,但是它增加了流程片间的耦合度。
注:demo中多使用的为原型函数catchFewProbabilityPage
,catchPage
为其扩展,推荐优先使用catchPage
这是一个能稳定跳转并简化操作的机制,比如以流程为{A,B,C,D}
为例,流程执行顺序为在A点击下一步到达B,然后在B上点击下一步按钮到达C,在C点击下一步到达D,具体流程为:
--方式一:使用延时的方式,稳定性极差,易受网络和硬件配置影响,本框架本不作讨论
tab A.button
delay(time)
find B.button
tab B.button
delay(time)
find C.button
tab C.button
delay(time)
do nextAction
--方式二:检测界面已经到达一下个界面后再进行点击,稳定,但繁复
tab A.button
while
if checked PAGE_B then
find B.button
tab B.button
end
end
while
if checked PAGE_C then
find C.button
tab C.button
end
end
while
if checked PAGE_D then
do nextAction
end
end
goNextByCatchPoint
本质上就是简化了的方式二,只需要传入B.button的特征点,然后它将循环检测B.button是否到达,在检测到B.button到达的情况下,PAGE_B肯定也已经到达,到达后将执行tap点击操作,示例:
--方式三:使用goNextByCatchPoint,稳定,且精简
goNextByCatchPoint(points_A.button)
goNextByCatchPoint(points_B.button)
goNextByCatchPoint(points_C.button)
do nextAction
在运行阶段所有的异常均交由catchError处理,由catchError打印记录LOG信息,然后执行错误处理方式。当判定为可以通过重启解决时,会尝试重启应用和脚本来解决问题,否则终止脚本任务。
由于模拟器或者手机运行应用可能会出现卡死闪退的情况,必要的重启恢复机制能保证挂机的稳定性。在catchError中,被判定为可以通知重启应用解决的错误,将执行restartAPP操作,然后通过skip机制续接任务。在restart的过程中,通过getLastTaskStatus来设置是否为断点重启任务,以标识一些初始化流程的执行。
在线收集ERROR信息
:玩家反馈的非稳定复现的错误极难追踪,即使开启写LOG文件的功能,操作也极为麻烦,因此构思将报错信息发送至服务器,用户只需要提供ID便可直接查看错误,方便调试。通过服务器收集脚本使用情况的信息
。全分辨率适配
:开始构建次框架时离我接触叉叉平台不到一周,所以当时并不了解全分辨适配,后来想做的时候,却发现实况这个游戏界面布局既不是简单的等比缩放,也不是基于锚点的短边缩放的布局,加之框架构建之初并未做出相应的预留和兼容,因此很难直接参考现有的方案。实况会在19年初更新UE4游戏引擎,不出意外应该会采用基于锚点的短边缩放的布局,故而全分辨率适配的方案放将放在后续构建。2.0引擎
:框架构建时,2.0引擎还处于内测阶段,一开始也确有尝试使用2.0引擎开发,但陆续发现了多个致命BUG(比如findColor内存泄露),尽管官方陆续在修复,但目前因时间限制,以稳为主,还是先基于1.9引擎开发,待新引擎基本稳定后将迁移至新引擎。HUD信息提示
:目前的取点方式容易影响到色点判定,新引擎后再行支持。UI
:1.9引擎不支持动态UI,为省时暂时使用Zui,2.0引擎已支持,故在迁移2.0后会整理一个简单是UI实现欢迎交流。
请不要直接用此代码发布实况足球手游的脚本,其它随意,利益相关,见谅。
cndy1860@gmail.com