从自动化测试到游戏脚本:使用Maafw开发

起因是想用自动化的流程做一些游戏任务,右面发现了MAA相关资源并尝试学习开发一些流程。这里总结一下踩坑和经验。

开发环境搭建

最早是从MaaAssistantArknights/MaaAssistantArknights中脱离的框架,目前用于MAA1999/M9A: 重返未来,overflow65537/MAA_SnowBreak等等项目。框架在下文中简称maa或maafw.

官方简介如下:

MaaFramework 是基于图像识别技术、运用 MAA 开发经验去芜存菁、完全重写的新一代自动化黑盒测试框架。低代码的同时仍拥有高扩展性,旨在打造一款丰富、领先、且实用的开源库,助力开发者轻松编写出更好的黑盒测试程序,并推广普及。

推荐vscode+neko-para/maa-support-extension进行开发,也方便使用插件测试。

注意,插件有个maa.agentTimeout设置超时时间,如果你发现连接不上,并且一般都是30秒关闭连接,那就有可能是超时了,可以把时间设置更长一点。

重点知识

官方文档1.1 快速开始 | MaaFramework

一般采用JSON+自定义逻辑扩展。JSON中会通过识别+动作定义节点。常用的动作包括点击,按键等等。

任务流水线协议

在/assets/resource下包含资源文件夹,例如image,model以及pipeline.

pipeline中定义任务流水线。3.1 任务流水线(Pipeline)协议 | MaaFramework

一个节点包含节点名称,以及识别和行为,后续,以及前后等待时间,识别等待时间和最多进入次数等。

对当前节点的 next 列表进行顺序检测,依次尝试识别每个子节点

若本轮均未命中,则继续下一轮检测;直到超时或有节点命中

当检测到某个子节点匹配成功时,立即终止后续节点检测。执行匹配节点的 action 定义的操作

从entry开始,针对第一个节点开始识别并进行动作,若该节点识别命中,并且动作成功,进入next列表。在next列表中循环检测,如果一个子节点识别命中则进入,如果动作成功进入其next列表重复流程,如果失败进入该节点on_error列表。

如果第一个节点识别命中但动作失败同样进入on_error列表,如果识别失败直接终止。

如果某个节点的next列表识别超时,则进入当前节点的on_error列表。如果全都走了一遍未命中且超时则终止。

设置timeout控制当前节点的 next 列表识别的超时时间

当满足以下任意条件时,任务流程终止:

  • 当前节点的 next 列表为空(若存在 [JumpBack] 回跳点,会先回跳)
  • 当前节点的 next 列表未命中且超时
  • 外部调用 post_stop 或执行了 StopTask 动作

核心:识别成功才算进入,如果一个节点下的next列表识别超时则走on_error(但next中节点还未识别完),如果都未命中且超时则退出

识别recognition类型包括默认 DirectHit 。
可选的值:DirectHit | TemplateMatch | FeatureMatch | ColorMatch | OCR | NeuralNetworkClassify | NeuralNetworkDetect | And | Or | Custom

动作action包括默认 DoNothing 。
可选的值:DoNothing | Click | LongPress | Swipe | MultiSwipe | Scroll | ClickKey | LongPressKey | InputText | StartApp | StopApp | StopTask | Command | Shell | Screencap | Custom

next接下来要执行的节点列表。可选,默认空。
按顺序识别 next 中的每个节点,只执行第一个识别到的

on_error 当本节点内的 next 列表中没有任何节点命中并且循环识别超时,或动作执行失败后,接下来会执行该列表中的节点。可选,默认空。

这里存在一点疑惑,next 列表中没有任何节点命中并且循环识别超时到底是走on_error列表还是直接中止

rate_limit: uint
识别速率限制,单位毫秒。可选,默认 1000 。
每轮识别最低消耗 rate_limit 毫秒,不足的时间将会 sleep 等待。

timeout: int
当前节点的 next 列表识别的超时时间,毫秒。可选,默认 20 * 1000(20 秒)

repeat: uint
动作重复执行次数。可选,默认 1 ,即不重复。

max_hit: uint
该节点最多可被识别成功多少次。可选,默认 UINT_MAX ,即无限制。
若超过该次数,其他 node 的 next 列表中的该 node 会被跳过,既不会被识别也不会被执行

anchor: string | list | object
锚点名称。可选,默认空。
当节点识别命中并执行动作后,会将该锚点名设置为对应的节点(无论动作成功或失败)。多个节点可设置同一个锚点名,后执行的会覆盖先执行的。

支持三种格式:

  • 字符串:"anchor": "MyAnchor" - 将锚点设置为当前节点

  • 字符串数组:"anchor": ["A", "B"] - 将多个锚点都设置为当前节点

  • 对象 💡 v5.7:"anchor": {"A": "TargetNode", "B": ""} - 将锚点 A 设置为 TargetNode,锚点 B 清除(空字符串表示清除该锚点)

    在 next 或 on_error 中可通过 [Anchor] 属性引用该锚点,运行时会解析为最后设置该锚点的节点。如果引用的锚点未设置或已被清除,该节点将被跳过(不会执行)。