ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

基于CGA规则引擎的游戏自动化工具:MLAssist的设计与实现

基于CGA规则引擎的游戏自动化工具:MLAssist的设计与实现 简介本资源是面向C开发者与《魔力宝贝》资深玩家的游戏辅助工具开源项目基于CGACross Game Assistant框架深度定制解决自动化任务执行、角色状态监控及脚本化扩展等核心需求。压缩包含2000个文件总大小82.42MB其中C/C头文件h/hpp共1935个构成主体逻辑与插件接口少量cpp/c文件实现核心服务如gameservice、mqtt通信、SQLite加密模块辅以css、json、md等配置与文档文件体现工程化架构设计。已有3379人学习下载适合具备C基础并熟悉Lua/Python脚本开发的用户深入研究辅助工具底层机制。读者可直接获取完整可编译源码、支持中文Lua脚本的运行时环境、实时角色信息同步的MLAssistTool账号管理模块以及迷宫地图同步与游戏ID创建等实用功能模块代码结构清晰便于二次开发与功能裁剪。1. 项目概述与核心价值最近在整理一些老项目的代码仓库翻到了一个挺有意思的东西——一个基于CGA开源代码为《魔力宝贝》这款老游戏设计的辅助工具我把它叫做MLAssist。这玩意儿不是什么商业外挂更不是破坏游戏平衡的脚本而是一个纯粹基于图像识别和模拟操作旨在帮助玩家处理一些重复性、机械性任务的“小帮手”。魔力宝贝这款游戏承载了很多人的青春记忆但游戏里诸如采集、生产、跑图等环节确实需要投入大量重复劳动。MLAssist的设计初衷就是想用技术手段把玩家从这些枯燥的“搬砖”中解放出来更专注于享受游戏的剧情、社交和策略乐趣。CGA全称CityEngine CGA原本是Esri公司用于城市三维建模的一种规则描述语言其开源版本提供了一套强大的形状语法和规则系统。你可能会好奇一个做城市建模的玩意儿怎么能跟游戏辅助扯上关系这恰恰是这个项目最有趣的技术切入点。CGA规则的核心思想是“基于规则的生成”它通过定义一系列条件和动作来描述一个复杂对象如建筑如何从简单形态演化而来。我们将这个思想“移植”到了游戏场景的理解上把游戏画面视为一个由各种UI元素、角色、NPC、地形构成的“场景”然后通过一套自定义的规则去描述、识别并与之交互。MLAssist本质上就是一套用CGA规则思想驱动的、高度可配置的游戏场景自动化交互引擎。这个工具适合谁呢首先是那些对《魔力宝贝》有深厚感情但苦于时间有限的老玩家它能帮你自动完成材料收集、生产制造等基础积累。其次是对游戏自动化、图像识别技术感兴趣的技术爱好者这个项目提供了一个非常具体且完整的案例展示了如何将学术界的规则生成思想应用到实际的软件工程问题中。最后它也适合那些需要处理大量重复性GUI操作任务的开发者其设计思路具有相当的通用性。接下来我就把这个项目的设计思路、核心技术细节以及踩过的坑毫无保留地分享出来。2. 整体架构设计与技术选型2.1 为什么选择CGA规则引擎作为核心在项目启动初期技术选型上我们考虑过几种主流方案。一种是直接使用成熟的图像识别库如OpenCV配合坐标点击这种方式直接但僵硬任何UI改动都会导致脚本失效。另一种是读取游戏内存数据这种方式效率最高但涉及游戏进程风险极大且不道德是我们坚决摒弃的。最终选择基于CGA开源代码来构建主要基于以下几点考量声明式与可维护性CGA规则是一种声明式语言。我们不需要写“如何找到那个按钮”的过程式代码比如截屏-模板匹配-计算坐标-点击而是定义“按钮是什么样子的”规则比如一个位于屏幕右下区域、红色矩形、上面有‘确定’文字的区域。当游戏UI更新时我们通常只需要调整规则描述而非重写整个识别逻辑维护成本大大降低。强大的模式匹配与空间关系描述CGA规则天生擅长描述几何形状、纹理模式以及它们之间的空间关系如相邻、包含、在上方。这完美契合了游戏UI的识别需求。我们可以轻松写出诸如“寻找一个被蓝色边框包围且内部包含一个黄色感叹号图标的对话框”这样的规则。分层与继承机制CGA规则支持规则继承和覆盖。我们可以先定义一些基础UI元素的通用规则如“按钮”、“文本框”、“血条”然后为特定的游戏场景如“战斗界面”、“交易窗口”创建更具体的规则这些规则继承并特化了基础规则。这种设计极大地提升了代码的复用性和组织清晰度。开源与可扩展性CGA的开源代码为我们提供了一个纯净的规则解析与执行引擎。我们可以在其之上构建针对2D图像识别和模拟输入的“后端”而无需从零开始实现一个规则引擎节省了大量基础工作。注意这里使用的“CGA”是指其规则描述的思想和引擎内核我们并没有用它来生成3D城市模型而是对其进行了“改造”让其输入从3D几何参数变为2D游戏截图和像素信息输出从建模指令变为鼠标键盘操作指令。2.2 MLAssist系统架构拆解整个MLAssist工具可以划分为四个核心层次自底向上分别是驱动层、感知层、决策层、任务层。驱动层这是工具与操作系统和游戏客户端交互的桥梁。它不依赖任何游戏内部接口完全通过系统API实现。主要包含两个模块图像采集模块负责以一定频率捕获指定游戏窗口的屏幕图像。这里我们使用了高性能的屏幕抓取库如DXGI Desktop Duplication API on Windows以确保获取画面的效率和稳定性避免因抓图导致游戏卡顿。输入模拟模块负责模拟鼠标和键盘操作。我们使用系统级的输入事件模拟如Windows的SendInput确保操作能被游戏正常接收。这里的关键是模拟的“人性化”需要加入随机延时、小幅鼠标移动轨迹波动等以避免被简单的行为检测机制识别。感知层这是系统的“眼睛”核心是基于改造后的CGA规则引擎。它接收驱动层传来的原始图像并应用一系列规则进行解析。规则库存放所有定义好的CGA规则文件。这些规则文件用类XML或自定义的DSL领域特定语言编写描述了各种游戏元素的特征。规则引擎加载并解释规则库。它将图像像素数据作为“初始形状”应用规则进行匹配和推导。例如一条“识别血条”的规则可能描述为一个长条形区域通常位于屏幕上方左侧为红色代表当前生命右侧为黑色或灰色代表生命上限。引擎会扫描图像找出所有符合该描述的区域并将其标记为“血条”对象同时计算出其位置、长度比例等属性。场景图生成引擎输出的不是一个简单的坐标列表而是一个结构化的“场景图”。这个图记录了当前画面中识别出的所有对象如玩家角色、NPC、按钮、对话框、物品图标以及它们之间的空间关系如物品A在背包格子的第3行第2列对话框D包含一个“确定”按钮B。这张图是决策层做出判断的基础。决策层这是系统的“大脑”。它根据感知层提供的场景图以及任务层下达的目标决定下一步执行什么操作。决策逻辑同样可以用规则来描述但更偏向于状态机和行为树。状态机定义工具在某个任务中的不同状态。例如在“自动采集”任务中状态可能包括寻找采集点-移动到采集点-执行采集动作-等待采集完成-整理背包。决策层根据当前场景图如是否看到可采集物角色是否在移动来判断是否进行状态切换。行为树对于一些更复杂的任务如自动完成一系列任务链我们引入了轻量级的行为树。每个行为节点如“点击某个NPC”、“使用某个物品”的执行结果成功、失败、运行中会决定后续执行哪个分支提供了更强的逻辑表达能力和容错性。任务层这是面向用户的接口定义了具体的自动化流程。用户可以通过配置文件或简单的GUI来选择和配置任务。例如Task_Mining自动挖矿任务。配置参数包括挖矿地点、使用的工具、背包满后的处理方式回城存放或丢弃低级矿石。Task_Production自动生产任务。配置参数包括要制作的物品、材料清单、制作次数。 任务层将用户的高层意图翻译成一系列由决策层和感知层协作完成的低级目标序列。3. 核心模块实现细节3.1 改造CGA规则引擎用于图像识别这是项目中最具挑战性也最有趣的部分。原始的CGA引擎处理的是三维几何体我们需要将其适配到二维图像像素世界。第一步重新定义“形状”。 在原始CGA中“形状”是一个三维体块。在我们的系统中一个“形状”被定义为一个图像上的感兴趣区域ROI附带一系列属性。初始形状就是整张游戏截图。规则的作用就是将一个大形状整张图逐步分解、识别出其中包含的特定小形状UI元素。!-- 一个简化的规则示例识别“确定”按钮 -- Rule nameIdentify_OK_Button !-- 匹配条件这是一个矩形区域宽高比大约为3:1主色调为绿色 -- Condition ShapeFilter typerect aspectRatioMin2.5 aspectRatioMax3.5/ ColorFilter dominantColor#00FF00 tolerance30/ /Condition !-- 执行动作将该区域标记为“OK_Button”并提取其文本内容如果可能 -- Action Label valueUI_Button_OK/ ExtractText regionentire/ !-- 调用OCR模块提取文字用于二次验证 -- /Action /Rule第二步实现规则中的“操作”。 原始CGA操作是挤出、分割等几何变换。我们的操作则是图像处理和属性提取Split 不再分割几何体而是根据颜色连通域、边缘检测或模板匹配将一个大区域分割成多个可能包含子元素的小区域。例如将“技能栏”区域分割成一个个独立的“技能图标”区域。Component 标记一个区域为特定组件并为其附加属性。如将某个区域标记为PlayerHealthBar并计算其填充比例当前血量/最大血量作为一个属性fillRatio。Texture 分析区域的纹理特征如是否具有按钮常见的渐变效果、边框等。OCR 集成轻量级OCR引擎如Tesseract用于提取区域内的文字这是识别NPC名称、物品名称、对话框内容的关键。第三步空间关系描述。 利用CGA规则中描述空间关系的语法我们很容易定义如下的规则// 规则识别一个典型的NPC对话窗口 // 它通常包含一个顶部标题栏深色一个中部文本区域和一个底部按钮区域。 // 按钮区域内通常包含“确定”和“取消”两个按钮。 Rule NPC_Dialog { // 首先找到一个大矩形区域作为窗口候选 ... // 然后在这个候选区域内寻找标题栏位于顶部、文本区中部、按钮区底部 // 按钮区内必须包含至少一个被识别为“OK_Button”或“Cancel_Button”的子形状 ... }这种基于上下文的识别比孤立地匹配一个按钮图片要稳定得多。即使按钮的皮肤换了只要窗口的整体布局和按钮的相对位置没变规则依然有效。3.2 图像识别策略与优化纯粹依赖像素颜色和形状的规则在游戏画面变化如光线效果、角色遮挡时容易失效。我们采用了多策略融合的方式特征金字塔匹配对于重要的、固定的UI元素如主菜单按钮、系统图标我们仍然保存其模板图像。但匹配时不是在原图上直接进行而是在构建的图像金字塔不同缩放比例上进行。这解决了游戏分辨率变化或UI轻微缩放带来的问题。匹配算法上我们结合了归一化互相关NCC和特征点匹配如ORB在速度和准确性间取得平衡。OCR文字识别这是提高识别鲁棒性的关键。很多UI元素的核心是文字。我们训练了一个针对《魔力宝贝》游戏字体的专用OCR模型基于Tesseract数据微调显著提升了小字体、艺术字体的识别率。规则可以写成“寻找一个区域其OCR识别结果包含‘提交’或‘交付’字样并将其标记为任务提交按钮”。颜色统计与主色调分析游戏状态常常通过颜色变化反映。比如角色中毒时血条可能变紫怪物可攻击时名字显示为红色。我们为规则增加了颜色直方图对比和主色调提取的功能。一条规则可以描述为“寻找一个长条其左侧区域占比70%的主色调为红色RGB值在某个范围将其识别为健康血条如果主色调为紫色则识别为中毒血条”。动态阈值与自适应游戏内昼夜更替、天气效果会导致整体画面明暗、色调变化。我们所有的颜色匹配都不是固定值而是基于当前画面局部统计信息的动态范围。例如识别血条时我们先定位血条的大致区域然后计算该区域在最近N帧内的颜色均值与方差用这个动态范围来判断当前是“满血”的红色还是“空血”的灰色。实操心得不要追求100%的识别率那是徒劳的。我们的策略是分层验证与投票机制。一个“战斗开始”的判断可能由三个独立规则共同决定1) 检测到“战斗”按钮高亮2) OCR识别到战场倒计时数字3) 检测到敌方单位的血条出现。只有其中至少两个规则被触发决策层才认为“战斗开始”。这极大地降低了误判率。3.3 模拟操作的人性化与防检测直接、精确、周期固定的操作是自动化脚本的典型特征极易被检测。MLAssist在这方面做了大量工作随机化延迟任何两个操作之间如点击之间、点击与按键之间都加入随机延迟。延迟时间不是固定的500ms而是从一个范围内随机选取例如[450ms, 1200ms]。更进一步的我们模拟了人类的反应时间分布大部分操作间隔在600-800ms偶尔会有一些较快的300ms或较慢的1500ms操作使其更接近真人操作模式。鼠标移动轨迹模拟鼠标从一个点移动到另一个点不是走直线而是模拟带有一点弧度和抖动的贝塞尔曲线并且移动速度是变速的先加速后减速。我们甚至引入了“手抖”算法在移动终点附近加入几个像素的随机微小抖动避免每次都精准点击在同一个像素点上。操作容错与重试工具不会假设一次点击必然成功。每次操作后它会等待一小段时间如300-500ms然后通过感知层检查场景是否发生了预期变化如点击按钮后相应的窗口是否弹出。如果没有它会记录一次失败并可能从稍有不同的位置再次尝试点击或者等待更长时间后重试。这种“观察-行动-验证”的循环是模仿人类在遇到界面无响应时的自然行为。引入“休息”与“断点”长时间不间断运行本身就是可疑点。MLAssist允许配置“工作时间”和“休息时间”。例如运行45分钟后自动暂停15分钟期间可能执行一些无规律的、小幅度的视角转动模拟玩家在看风景或暂时离开。此外工具支持设置多个“安全断点”在运行到特定步骤如完成10次采集后暂停等待手动确认后再继续这既是安全措施也增加了行为的不确定性。4. 典型任务流程实战解析让我们以“自动伐木”这个经典任务为例拆解MLAssist的完整工作流程。假设我们已经配置好了伐木地点例如芙蕾雅岛某树林、使用的工具伐木斧、背包满后的策略回城存入仓库。4.1 任务初始化与环境检查工具启动后首先进入初始化阶段游戏窗口定位通过进程名或窗口标题定位到《魔力宝贝》的游戏窗口并获取其位置和大小。这里要处理游戏窗口化、全屏等不同模式。加载任务配置读取Task_Lumbering.xml配置文件解析目标地点、工具、策略等参数。状态重置将内部状态机重置为初始状态Idle空闲。环境基准采样连续捕获5-10帧游戏画面进行背景建模和颜色基准计算。这有助于后续识别时排除临时性光影干扰如技能特效。4.2 状态机流转与核心操作任务的核心是一个状态机以下是其典型状态流转状态A导航至伐木点目标从当前位置移动到配置的伐木区域。决策与感知感知层持续识别小地图、当前坐标、以及屏幕中的路标如树木、桥梁的独特形状。决策层将目标坐标与当前坐标对比计算移动方向。操作通过模拟键盘的方向键或鼠标点击地面进行移动。移动过程中会间歇性地按Tab键切换视角模拟玩家观察周围环境的行为。验证当感知层识别到小地图上的角色图标进入预设的伐木区域坐标范围时状态切换。踩坑记录直接朝目标坐标直线移动很容易撞上障碍物或NPC。我们的解决方案是采用“分段导航”。将路径分成多个短线段每移动一小段就重新评估当前位置和前方障碍通过识别屏幕中障碍物的颜色块。如果发现障碍则稍微绕行。这比实现一套完整的寻路算法要简单实用得多。状态B寻找可砍伐的树木目标在伐木区域内找到一棵可以交互的树。决策与感知感知层应用“树木”识别规则。这个规则比较复杂结合了颜色树干的棕色、树叶的绿色、纹理树皮的粗糙感、以及形状近似圆柱体加上不规则的树冠轮廓。更重要的是规则会寻找树木上是否有一个微小的、闪烁的“交互光标”当鼠标移动到可交互物体上时游戏显示的光标变化。决策层控制角色缓慢转动视角让感知层扫描更大范围的区域。操作一旦识别到符合条件的树木且其带有“交互光标”则模拟鼠标移动至该树木的中心偏下位置模拟点击树干。验证点击后观察是否出现“砍伐中”的进度条或角色播放砍伐动画。状态C执行砍伐与等待目标完成一次砍伐动作并等待其完成收集产物。决策与感知进入此状态后工具进入“监控”模式。感知层主要监控1) 砍伐进度条如果游戏有2) 角色动画是否停止3) 屏幕下方是否出现获得物品的系统消息通过OCR识别“获得了[木材]”。操作在砍伐期间不进行任何操作或仅进行非常低频的视角微调。验证当收到获得物品的消息或确认砍伐动画结束时状态切换。同时工具会记录本次获得的物品类型和数量。状态D背包检查与后续决策目标检查背包是否已满并根据预设策略决定下一步行动。决策与感知感知层识别背包界面如果未打开则模拟按B键打开。应用规则识别背包格子状态空的格子特定背景色、有物品的格子有图标。计算已使用的格子数。决策如果背包未满则返回状态B寻找下一棵树。如果背包已满则根据配置策略执行分支策略1回城状态切换至“导航回城”前往仓库NPC存入木材然后返回伐木点。策略2丢弃定义丢弃规则如丢弃所有“一级木材”模拟打开背包将指定物品拖出背包区域丢弃然后返回状态B。4.3 异常处理与恢复机制自动化流程不可能一帆风顺强大的异常处理是保证工具长时间稳定运行的关键。被意外攻击感知层持续监控角色血条和屏幕中出现的战斗相关UI如敌人血条、战斗指令框。一旦检测到进入战斗立即暂停当前采集任务状态机切换到“紧急战斗处理”子状态。这个子状态可以配置为简单的“逃跑”模拟点击逃跑指令或“使用预设技能防御”。处理完毕后再尝试返回之前的任务状态。游戏弹窗网络延迟、任务完成等都可能触发游戏内弹窗。我们定义了一个高优先级的“弹窗处理”规则集专门用于识别和关闭各种常见弹窗如“断线重连”、“获得新称号”等。一旦感知层检测到弹窗决策层会立即中断当前流程优先处理弹窗。角色卡住如果状态机在某个状态如移动停留时间远超预期例如2分钟还没走到目标点工具会触发“卡住检测”。它会尝试一些恢复操作随机向几个方向移动一小段使用回城羽毛或技能甚至模拟按下PrintScreen截图用于后期人工分析原因然后暂停任务并报警如日志记录高亮错误。规则匹配失败如果某个关键UI元素如背包按钮在连续多次尝试中都无法识别工具不会无限重试。它会记录错误并尝试备用方案如使用不同的快捷键打开背包如果备用方案也失败则判定为“环境异常”安全暂停。5. 开发中的挑战与解决方案实录在开发MLAssist的过程中我们遇到了无数坑这里挑几个有代表性的分享一下。5.1 挑战一游戏画面动态干扰问题描述游戏内天气效果雨、雪、技能光影、其他玩家和宠物的移动都会严重干扰UI元素的静态识别。例如一个技能特效可能刚好覆盖在“确定”按钮上导致颜色和形状规则完全失效。解决方案时序滤波我们不再只依赖单帧画面做判断。对于重要的UI状态我们引入了一个“状态持续计数器”。例如要判定“确定按钮存在”要求它在连续3帧约100毫秒内都被识别到才被认为是有效状态。瞬间出现的特效通常只持续1-2帧会被过滤掉。背景减除对于相对静止的UI如技能栏、聊天框我们定期如每10秒更新一次它们的“干净”背景截图作为参考。在识别时先将当前帧与背景参考图做差分排除掉背景中不变的静态部分专注于变化的部分如按钮高亮、技能冷却。这需要谨慎处理因为UI本身也可能被拖动。区域重要性屏蔽我们将屏幕划分为不同区域并为每个区域分配一个“动态容忍度”。例如屏幕中央的战斗区域动态容忍度最高识别规则更宽松而四周的技能栏、背包区域容忍度低规则更严格。对于高动态区域的关键信息如怪物血条我们更依赖OCR提取的文字信息而非颜色形状。5.2 挑战二规则编写的复杂性与维护问题描述随着要识别的UI元素越来越多规则文件变得庞大而难以管理。一条规则可能长达上百行且规则之间可能存在冲突或重复。解决方案模块化与继承充分利用CGA规则的继承特性。我们建立了完整的UI元素类库。定义一个基础按钮规则BaseButton包含按钮的通用特征矩形、有边框、有文字。然后OKButton规则继承BaseButton并特化其颜色为绿色、文字为“确定”。CancelButton则特化颜色为红色、文字为“取消”。这样通用逻辑只需写一次。规则调试可视化工具我们开发了一个内嵌的调试器。它可以加载规则文件对当前游戏画面运行规则并用不同颜色的半透明框高亮显示出每个规则匹配到的区域并显示匹配的置信度。这极大地加快了规则编写和调试的速度可以直观地看到为什么某条规则没有匹配上或者匹配到了错误的地方。版本化与差分更新我们将规则文件进行版本控制。当游戏更新导致UI改动时我们可以快速对比新旧规则定位需要修改的部分。同时我们设计了一套“规则热重载”机制可以在工具运行时更新部分规则而无需重启整个程序。5.3 挑战三性能与效率的平衡问题描述高频率的屏幕截图、复杂的规则匹配、OCR识别都是计算密集型操作。如果处理不当会严重占用系统资源甚至影响游戏本身的流畅度。解决方案自适应采样频率工具并非以固定频率如60FPS运行所有流程。它采用“事件驱动”和“状态依赖”的采样策略。在“等待”状态如砍伐中感知层可以休眠每秒只检查1-2次关键状态如进度条。在“导航”或“寻找”状态则需要较高的采样频率如10-15FPS来及时响应环境变化。区域化识别不是每一帧都对全屏图像应用所有规则。决策层会告诉感知层“当前我需要关注背包区域和快捷栏区域”。感知层就只对这两个区域的图像进行裁剪和规则匹配大大减少了计算量。OCR优化OCR是性能瓶颈。我们做了两点优化1)预筛选只有那些被规则初步判定为“可能包含文字”的区域如具有文本框特征、颜色对比度高的区域才会送入OCR引擎。2)缓存对于频繁出现且不变的文字如NPC名称、固定按钮文字第一次识别后会进行缓存后续直接使用缓存结果。异步处理流水线我们将图像采集、规则匹配、决策逻辑、模拟操作放在不同的线程中形成一个流水线。采集线程只管抓图并放入队列匹配线程从队列取图分析将结果放入结果队列决策线程消费结果并发出操作指令。这样避免了某个环节卡住导致整体卡顿。6. 伦理、安全与未来思考开发这样一个工具绕不开伦理和安全问题。我必须强调MLAssist的设计遵循几个核心原则零内存修改绝不读取或修改游戏进程内存。所有行为基于外部图像识别和模拟输入这与使用宏鼠标键盘在物理层面没有本质区别。不破坏公平性工具的设计目标是替代重复劳动而非获取超越正常玩家的能力。它不能自动战斗、不能瞬移、不能复制物品。它的效率上限就是一个非常熟练、永不离线、永不犯错的“真人”玩家。用户风险自知在工具说明中明确告知用户使用任何自动化工具都可能违反游戏服务条款存在账号被封禁的风险。工具本身不提供任何绕过游戏检测的“保护”功能。从技术演进的角度看这个项目给我带来了很多启发。将CGA这类生成式规则引擎用于理解和交互复杂GUI系统是一条非常有意思的路径。它比纯粹的深度学习方案更具可解释性和可控性规则就像一份给机器的“说明书”。未来结合少量深度学习进行特征提取如用CNN判断一个区域是不是“按钮”再用规则系统进行逻辑推理和决策可能会创造出更强大、更通用的GUI自动化框架。这个项目也让我深刻体会到软件工程中“合适的才是最好的”。没有追求最前沿的AI技术而是巧妙地将一个现有领域的成熟思想CGA规则跨界应用到另一个领域游戏辅助并解决了大量工程细节问题最终做出了一个稳定可用的工具。这个过程本身其价值远大于工具的输出结果。本文还有配套的精品资源点击获取
返回列表