[关闭]
@cndy1860 2020-08-27T01:28:41.000000Z 字数 5142 阅读 1131

X-Framework 设计与思路

叉叉助手 框架 自适应分辨率 控件锚点


写在前面

因一些原因此项目在很长一段时间里没有进行维护,最近整理了一下一直未更新的新版的代码重新上传。
本意是想开发一个自用的简洁并尽可能通用的框架,但在没有开发过其他游戏脚本的情况下,直接以实况手游为蓝本进行开发难免会导致很多地方以适应这个游戏为主,且易有疏漏,仅供参考。

框架说明

目前手游脚本的实现主要是在多级界面之间不断的跳转,并在其间穿插各状态判定和逻辑操作,流程模式大致可以归结为:界面-->>事件-->>界面-->>事件...本项目即是依据此模型构建的一个的基本框架。
目前流行的框架基本上采用了在每个界面上锚定控件位置,然后在每个控件上加上一个简单的事件(多为tap点击操作),添加一个任务只需要依次列出界面和对应要点击的控件,这样的好处是逻辑简单,对于只需要在各级界面跳转和简单点击的游戏,当然是一个不错的选择,但是对于在各级界面跳转间有复杂情况的游戏来适用性并不高,此框架即是为能适应复杂跳转情况而构建。
本项目以实况足球手游为示例演示开发一个完整的task

框架特性

实况足球(示例游戏)界面跳转的一些特点

设计原则

模块说明

框架流程执行

一个完整的脚本任务task由一系列流程processes组成,而流程又由多个流程片process组成,每一个流程片由流程片初始界面page和事件函数actionFunc,以及等待page到来期间执行的等待函数waitFunc组成。
run方法首先会从taskList中提取对应的processes,然后以process为单位具体执行。程序首先会等待流程片初始界面page的到来,期间有可能执行waitFunc,但并不关心之前的任何流程,然后开始执行流程片的具体的逻辑操作函数actionFunc,执行完成后释放流程片控制权,同时不关心后续流程。

Task.Run流程图

注:GFM可能不支持流程图,如不支持可自行COPY代码在其他工具上查看

Created with Raphaël 2.1.2exec.Run循环执行任务(流程)是否执行完指定的任务次数完成Task根据justFirstRun和justBreakingRun设置各流程片的默认skip属性设置进入skip检测的等待时间遍历执行当前(次)任务的流程片是否执行完当前(次)流程的所有流程片是否为需要跳过的流程片循环检测当前界面是否为当前流程片对应的界面执行actionFunc执行流程片等待事件函数waitFunctimeout检测是否需要skip部分流程片设置skip属性yesnoyesnoyesnoyesnoyesno

核心机制说明

skip机制:通过设置skipStatus属性来控制是否跳过流程片

根据是否为首次运行,是否为断点任务,当前界面是否存在可跳过的情况来设置skipStatus
在脚本运行期间,如果流程中某一个流程片界面没有出现,或者因为用户主动点击了一下歩而跳过了某一个流程片,那么在循环等待的过程中,如果等待时间超过CFG.WAIT_CHECK_SKIP,流程函数将尝试判定是否可以执行跳过流程片的处理。判定原则是:当前的界面CURRENT_PAGE符合当前流程片之后的某个流程片的界面PROCESS_PAGE,那么就判定从CURRENT_PAGEPROCESS_PAGE(不包括PROCESS_PAGE本身)为可跳过界面,设置skipStatus属性为true,并直接跳转到PROCESS_PAGE继续执行流程。
通过skip机制,可以让脚本可以从流程中的任何一个界面开始任务,主要解决以下问题:

catchPage机制:处理界面跳转可能出现多个不确定界面的情况

比如流程为{A,B,C,D,E,F,G},以界面A跳转至界面B为例:

  1. if catchPage(PAGE_B) == PAGE_B then nextAction end

这样在捕获到界面B以前,将会忽略掉其他所有的界面,避免造成干扰

  1. while
  2. catchPage({PAGE_B, PAGE_NOTICE}, {points_contract, points_energy})
  3. if PAGE_B then break --出口
  4. if PAGE_NOTICE then closeNotice()
  5. if PAGE_points_contract then chargeContract()
  6. if PAGE_points_energy then chargeEnergy()
  7. end
  8. nextAction

你可能会注意到,catchPage机制其实同样能实现skip的效果,那如果抉择呢?skip效果的触发,是需要经过等待CFG.WAIT_CHECK_SKIP时间后才进入检测是否发生的流程,一般为3s以上,如果把一个极低概率才会出现的界面用skip机制处理,会导致每次运行到那个流程片均需要等待CFG.WAIT_CHECK_SKIP的时间才能跳过,增加了流程的大量的等待时间,但使用catchPage则无需等待延时,出现任何一个列出的界面即可马上响应。
从本质上来说,catchPage机制就是一个无延时的,功能加强版本的skip机制,但是它增加了流程片间的耦合度。
注:demo中多使用的为原型函数catchFewProbabilityPagecatchPage为其扩展,推荐优先使用catchPage

goNextByCatchPoint机制:检测界面上的按钮(点集)并点击

这是一个能稳定跳转并简化操作的机制,比如以流程为{A,B,C,D}为例,流程执行顺序为在A点击下一步到达B,然后在B上点击下一步按钮到达C,在C点击下一步到达D,具体流程为:

  1. --方式一:使用延时的方式,稳定性极差,易受网络和硬件配置影响,本框架本不作讨论
  2. tab A.button
  3. delay(time)
  4. find B.button
  5. tab B.button
  6. delay(time)
  7. find C.button
  8. tab C.button
  9. delay(time)
  10. do nextAction
  11. --方式二:检测界面已经到达一下个界面后再进行点击,稳定,但繁复
  12. tab A.button
  13. while
  14. if checked PAGE_B then
  15. find B.button
  16. tab B.button
  17. end
  18. end
  19. while
  20. if checked PAGE_C then
  21. find C.button
  22. tab C.button
  23. end
  24. end
  25. while
  26. if checked PAGE_D then
  27. do nextAction
  28. end
  29. end

goNextByCatchPoint本质上就是简化了的方式二,只需要传入B.button的特征点,然后它将循环检测B.button是否到达,在检测到B.button到达的情况下,PAGE_B肯定也已经到达,到达后将执行tap点击操作,示例:

  1. --方式三:使用goNextByCatchPoint,稳定,且精简
  2. goNextByCatchPoint(points_A.button)
  3. goNextByCatchPoint(points_B.button)
  4. goNextByCatchPoint(points_C.button)
  5. do nextAction

catchError机制:错误处理

在运行阶段所有的异常均交由catchError处理,由catchError打印记录LOG信息,然后执行错误处理方式。当判定为可以通过重启解决时,会尝试重启应用和脚本来解决问题,否则终止脚本任务。

restart机制:重启断点续接运行

由于模拟器或者手机运行应用可能会出现卡死闪退的情况,必要的重启恢复机制能保证挂机的稳定性。在catchError中,被判定为可以通知重启应用解决的错误,将执行restartAPP操作,然后通过skip机制续接任务。在restart的过程中,通过getLastTaskStatus来设置是否为断点重启任务,以标识一些初始化流程的执行。

ToDo

其他

欢迎交流。
请不要直接用此代码发布实况足球手游的脚本,其它随意,利益相关,见谅。

联系方式

cndy1860@gmail.com

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注