资讯动态

绝区零一条龙深度解析:事件驱动状态机如何撑起全自动游戏框架

发布时间:2026/8/17 18:25:00 来源:尧图企业网站定制
绝区零一条龙深度解析事件驱动状态机如何撑起全自动游戏框架【免费下载链接】ZenlessZoneZero-OneDragon绝区零 一条龙 | 全自动 | 自动闪避 | 自动每日 | 自动空洞 | 支持手柄项目地址: https://gitcode.com/gh_mirrors/ze/ZenlessZoneZero-OneDragon《绝区零》的日常有多繁琐登录、签到、清体力、打空洞、收邮件、刷周本……一套下来少说半小时还得全程盯着屏幕。绝区零一条龙ZenlessZoneZero-OneDragon正是为解决这一痛点而生的开源自动化框架它基于Python 3.11 事件驱动状态机 计算机视觉把看得见画面和按得下按键两件事彻底打通实现自动闪避、自动每日、自动空洞、自动战斗甚至支持手柄操作。本文将从源码层面拆解它的设计思路与实现细节看看一个能自己玩游戏的程序到底是怎么搭出来的。图1绝区零一条龙的主界面左侧是任务列表右侧为运行日志与实时状态 痛点开场为什么写死的脚本总是翻车市面上的游戏脚本大多是一串坐标 延时的硬编码先点 (x1, y1)睡 3 秒再点 (x2, y2)。这类方案有三个致命伤界面一变就废游戏一更新 UI所有坐标全部失效没有眼睛脚本不知道当前屏幕处于什么状态点错了只能一路错下去没有脑子无法处理弹窗、加载、网络波动这类非预期分支流程一断就卡死。绝区零一条龙的思路完全不同它不信任任何写死的坐标而是先截图、再识别、后决策、最终才动手。整个框架围绕一条核心链路运转游戏画面 → 截图采集 → 画面识别模板/OCR/检测→ 状态机决策 → 输入模拟键盘/鼠标/手柄→ 游戏画面这条链路中的每个环节都被做成了可插拔的模块这才有了后面要讲的一整套状态机与识别体系。️ 全局地图四层架构与插件即应用的目录设计整个仓库的代码按职责分成四个互不依赖的层级每个层级只干一件事层级目录职责基础框架层src/one_dragon/状态机引擎、事件总线、模板匹配、屏幕信息、配置系统GUI 框架层src/one_dragon_qt/PyQt 界面、悬浮窗调试、输入窗口、主题样式业务逻辑层src/zzz_od/绝区零专属业务签到、空洞、战斗、巡逻等OCR 引擎层src/onnxocr/基于 ONNX Runtime 的文本识别推理服务业务逻辑层是理解整个项目最好的入口。打开src/zzz_od/application/你会看到一长串应用目录daily_signin每日签到、email_app邮件、coffee咖啡、charge_plan回体计划、notorious_hunt周本、shiyu_defense防卫战、hollow_zero空洞、world_patrol世界巡逻、redemption_code兑换码……每个目录都是一个独立插件自带xxx_app.py流程、xxx_factory.py工厂、xxx_config.py配置、xxx_run_record.py运行记录。这种一个功能一个包的目录哲学让新增功能变成了复制目录改业务而不是改核心框架。⚙️ 机制一装饰器定义的状态机把流程图写进函数解决什么问题传统的游戏自动化流程要么是面条式的if/else嵌套要么是单独的 XML/JSON 流程图配置——前者难维护后者难调试。绝区零一条龙要的是流程结构清晰可见、节点逻辑内聚、状态转移可追溯。怎么实现答案是一对精巧的 Python 装饰器operation_node把普通方法标记为状态机节点node_from声明节点之间的转移边。以每日签到应用为例源码中真实存在这样一段operation_node(name运行子应用, is_start_nodeTrue) def run_sub_app(self) - OperationRoundResult: 根据配置的商店代理运行具体的签到子应用。 sub_app_id: str self.config.selected_sign if not sub_app_id: return self.round_fail(status未选择子应用) # 失败也会走失败分支 app self.ctx.run_context.get_application(...) return self.round_by_op_result(app.execute()) # 成功进入下一个节点再看节点间的边是如何声明的node_from(from_name战斗开始检测, status战斗开始) # 只有状态匹配才转移 node_from(from_name战斗开始检测, status超时, ignore_statusTrue) # 兜底分支 operation_node(name执行战斗循环) def execute_battle_loop(self) - OperationRoundResult: ...关键设计在operation_node的实现里——装饰器并不修改函数行为而是把OperationNode对象作为属性挂到函数上def decorator(func): node OperationNode(cnname, op_methodfunc, is_start_nodeis_start_node, ...) setattr(func, operation_node_annotation, node) # 元数据挂载不改函数 return funcnode_from同理把边描述追加到operation_edge_annotation列表。等到Operation基类执行时会调用_analyse_node_annotations()扫描这些挂载的属性在运行期把节点和边组装成一张有向图再通过_get_next_node()根据上一轮的返回状态决定跳转。这样一个每轮截图 → 执行节点 → 拿结果 → 选边跳转的循环就转起来了。效果如何流程可视化节点名称就是中文日志出问题时能精确看到卡在哪个环节分支能力同一起点可以有多条出边分别匹配不同状态天然支持成功/失败/超时三态分流可重试每个节点自带node_max_retry_times异常情况自动重试而不是直接崩掉。 机制二事件总线 应用工厂解耦到谁都能写插件解决什么问题自动化的各个模块战斗、巡逻、通知、GUI彼此需要通信但不能互相 import 成一团乱麻。例如战斗结束这件事既要通知状态记录又要触发通知推送还要刷新界面日志。怎么实现发布-订阅事件总线ContextEventBus是一个标准的观察者模式实现所有组件通过listen_event订阅、通过dispatch_event广播彼此零引用class ContextEventBus: def __init__(self): self.callbacks: dict[str, list[Callable]] {} def dispatch_event(self, event_id: str, event_obj: Any None): 下发事件到所有订阅者异步不阻塞调用方 if event_id not in self.callbacks: return for callback in self.callbacks[event_id]: future _od_event_bus_executor.submit(callback, ContextEventItem(event_id, event_obj)) future.add_done_callback(thread_utils.handle_future_result)注意那个模块级线程池ThreadPoolExecutor(max_workers32)。事件回调全部丢进线程池异步执行主循环不会被慢回调拖住——这对毫秒级响应的战斗场景至关重要。怎么实现工厂模式发现插件ApplicationFactoryManager在启动时扫描应用目录用_find_factory_in_module()找到每个包里的工厂类注册成PluginInfo。业务侧拿到app_id就能通过run_context.get_application()创建实例、执行流程。整个注册表支持热重载discover_factories(reload_modulesTrue)可以卸载旧模块、重新扫描第三方插件放进来即插即用。效果如何新增功能只需实现一个ApplicationFactory子类框架零改动事件通信解耦后战斗、巡逻、GUI、通知各自独立演进20 内置应用全部复用同一套运行框架代码复用率极高。️ 机制三CV 流水线把识别做成可编排的积木解决什么问题识别画面不能只用一种手段找按钮图标用模板匹配最快读剩余次数得靠 OCR看血条状态又需要轮廓分析。不同场景识别逻辑差异巨大如果每种场景都写一套识别代码维护成本会爆炸。怎么实现步骤化 CV 管线框架抽象出了CvStep识别步骤和CvPipeline识别流水线。一条流水线就是一组按顺序执行的步骤每个步骤只做一件事输出交给下一步# 一条典型的找锁定目标流水线先找轮廓 → 按面积过滤 → 按HSV颜色过滤 → 输出中心点 pipeline.add_step(step_find_contours(modeEXTERNAL)) pipeline.add_step(step_filter_by_area(min_area500, max_area50000)) pipeline.add_step(step_filter_by_hsv(hsv_color(120, 150, 150), hsv_diff(10, 105, 105))) pipeline.add_step(step_contour_properties(show_bounding_boxTrue))从src/one_dragon/base/cv/的步骤清单就能看出积木的丰富程度模板匹配、OCR、灰度化、二值化、HSV 过滤、RGB 过滤、轮廓查找、面积/半径/长宽比/弧长过滤、形态学开闭运算、直方图均衡、按区域裁剪、按模板裁剪、环形裁剪……二十多种步骤自由组合。而 OCR 步骤内部走的就是src/onnxocr/的 ONNX 推理引擎。三级识别策略模板匹配TemplateMatcher匹配 UI 图标、按钮支持多尺度金字塔与掩码毫秒级响应用于高频操作判定OCR 识别读取剩余 3 次第 2 层这类动态文本带区域缓存相同区域 5 秒内结果复用目标检测/轮廓分析锁定目标、角色状态这类结构化信息走 YOLO 或轮廓流水线。图2锁定目标识别使用的模板raw 原图配合 mask 掩码只匹配目标区域忽略背景干扰效果如何识别逻辑从散落的代码变成了可配置的流水线同一个步骤积木在不同业务里反复复用模板资源统一放在assets/template/下新角色、新按钮只需要补充模板图不需要改识别代码。 机制四屏幕路由让程序永远知道自己在哪解决什么问题游戏里的界面是分层的主城 → 菜单 → 邮件 → 战斗。自动化操作时如果不知道当前在哪个界面任何点击都是盲的。怎么实现每个界面被建模成ScreenInfo界面上每个可交互区域被建模成ScreenArea全部用 YAML 定义在assets/game_data/screen_info/下。一个区域可以声明三种识别方式之一固定矩形pc_rect、文本text OCR 匹配、模板template_id 模板匹配。更重要的是goto_list字段——它声明了从这个界面能点到哪些界面# 屏幕定义片段示意主城界面某个按钮区域 主城: area-进入战斗: pc_rect: [600, 300, 800, 380] goto_list: [战斗]ScreenLoader会把这些goto关系编译成一张界面路由图。当程序想去某个目标界面时通过round_by_goto_screen()沿路由逐跳导航每轮截图先做check_and_update_current_screen()确认当前位置走错就回退重试。这就是永远知道自己在哪的底气。效果如何界面跳转从人肉记坐标变成图搜索路由自动兜底游戏更新后只需维护 YAML无需动代码支持窗口缩放坐标换算pc_game_window.get_scaled_game_pos不同分辨率下同样能点准。⚔️ 实战拆解一自动战斗如何在 0.02 秒内完成一次闪避自动战斗是这套框架技术含量最高的模块实现在src/zzz_od/auto_battle/。核心类AutoBattleOperator继承自ConditionalOperator——一个条件驱动的操作器由三个配置层驱动状态处理器auto_battle_state_handler识别当前该做什么例如是否被攻击、是否可释放连携技操作定义auto_battle_operation把闪避普攻特殊技等动作拆成最小原子操作配队模板config/auto_battle/不同队伍的执行策略支持作者、版本、配队信息等元数据缺失时自动回退到全配队通用模板。战斗循环是典型的周期轮询 状态机混合体各检测项有独立的轮询间隔self.check_dodge_interval 0.02 # 闪避检测每 20ms 一次最高优先级 self.check_agent_interval 0.5 # 当前角色检测每 0.5s self.check_chain_interval 1 # 连携技机会检测每 1s self.check_end_interval 5 # 战斗结束检测每 5s为什么闪避要 20ms 一次因为闪避窗口只有零点几秒识别慢了就等于没识别。而战斗结束检测 5s 一次就够了——它只在战斗间隙出现不需要抢时间。把不同频率的任务放进同一个循环用时间戳 间隔决定每轮执行谁既保证了闪避的实时性又不会让低优先级的检测白白消耗 CPU。原子操作也做了很好的抽象例如AtomicBtnLock锁定目标和AtomicTurn转向它们都被做成可复用积木战斗、巡逻都能用。所有操作通过PcControllerBase统一分发——键盘、鼠标、Xbox 手柄、DS4 手柄、虚拟手柄vgamepad各有一套实现但业务代码永远只调click()/btn_press()不关心底层是哪种输入设备。️ 实战拆解二世界巡逻让认路变成认图世界巡逻world_patrol解决的是在大地图上自动跑路线的问题。它的实现思路非常聪明把每张地图的道路预先渲染成一张掩码图road_mask程序通过当前位置 目标位置 掩码图计算可移动方向配合小地图识别持续校正一点点挪到目标点。图3世界巡逻使用的道路掩码图白色区域为可行走路径识别引擎据此规划移动方向路线本身以 YAML 配置存放在config/world_patrol_route/下每个区域一个文件可以声明在哪张图、往哪个方向走、到了做什么操作。新增一条路线 截张图 描个掩码 写段 YAML不需要改任何代码。这与前面的 CV 流水线、屏幕路由设计一脉相承一切可配置化代码只负责执行不负责记忆。⚖️ 技术选型为什么是状态机 ONNX决策点选项 A选项 B最终选择核心理由流程组织行为树事件驱动状态机状态机游戏流程是线性的界面→界面状态机天然契合节点图可调试、开销低识别模型运行时TensorRTONNX RuntimeONNX跨平台兼容、CPU/GPU 通吃、部署简单、与 Python 生态贴合输入模拟仅键盘鼠标键鼠 手柄 虚拟手柄多端统一支持前台/后台模式手柄用户同样享受自动化流程定义硬编码装饰器 YAML双轨并用短流程用装饰器写在代码里长策略用 YAML 配置热加载界面坐标写死像素模板 OCR 掩码识别优先版本更新、分辨率变化都不怕这套组合拳的核心逻辑只有一个把会变的东西全部交给数据和配置把不变的东西状态机引擎、识别管线、输入抽象留在代码里。所以游戏每次更新社区的响应速度才能快到当天修好。 落地价值性能数据与体验提升从工程实践看这套架构带来的直接收益是实打实的能力典型指标说明闪避响应~20ms 轮询关键帧不丢闪避成功率取决于游戏本身窗口模板匹配单次毫秒级多尺度金字塔 掩码UI 高频判定无压力OCR 识别区域级缓存相同区域重复识别直接命中缓存不重复推理多实例支持多账号并行OneDragonConfig管理多实例可配置全部跑完自动关机后台运行键鼠/手柄双模式前台被占用时可用虚拟手柄后台操作对玩家而言最直观的变化是每天点一下开始剩下的交给它。每日签到、邮件、体力、空洞、周本、防卫战全部按配置排队执行中途弹窗、加载、失败重试都由状态机自动消化。这也是一条龙这个名字的由来——你只需要负责启动它。 复盘教训与进阶路线从架构中学到的三件事状态机的威力在于显式把每个动作变成有名字的节点把每次跳转变成有条件的边调试复杂自动化流程时的体验远超隐式 if/else识别是自动化的地基模板 OCR 检测三层互补才能覆盖图标、文字、结构三类信息缺一层都会在真实游戏环境里翻车配置即代码代码即配置YAML 管策略、装饰器管流程、工厂管装配三者的边界划得越清楚社区贡献的门槛就越低。值得期待的演进方向识别智能化从模板匹配走向更多小模型检测用深度学习替换部分硬编码轮廓逻辑进一步降低对分辨率、主题的敏感度策略社区化自动战斗配队模板、世界巡逻路线目前已是 YAML 生态未来很可能形成路线市场 / 配队市场式的共享体系用户下载即用平台拓展当前以 PC 窗口 手柄为主Linux 兼容、云游戏串流场景是社区持续讨论的方向插件规范化第三方插件已支持动态扫描加载未来接口稳定后非游戏业务的自动化例如签到提醒、材料计算器也能长在同一个框架上。 结语绝区零一条龙最值得学习的地方不是它能自动打游戏而是它用一套克制的工程架构解决了自动化领域最棘手的两个问题怎么可靠地认识世界识别管线和怎么优雅地做出决策状态机。四层代码分层、事件总线解耦、工厂模式插件化、YAML 全面配置化——每一条设计都在为可持续维护服务。无论你是想给游戏写自动化工具还是单纯想看看 Python 如何撑起一套实时视觉决策系统这个仓库都是一份高质量的参考教材。它的下一步值得持续关注。【免费下载链接】ZenlessZoneZero-OneDragon绝区零 一条龙 | 全自动 | 自动闪避 | 自动每日 | 自动空洞 | 支持手柄项目地址: https://gitcode.com/gh_mirrors/ze/ZenlessZoneZero-OneDragon创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价