当前位置: 首页 > news >正文

从零实现《三角洲行动》手游自动跑刀脚本:ADB 直控 + OpenCV 视觉识别 + 固定点位搜刮)三角洲自动跑刀教程

从零实现《三角洲行动》手游自动跑刀脚本:ADB 直控 + OpenCV 视觉识别 + 固定点位搜刮

  • 从零实现《三角洲行动》手游自动跑刀脚本:ADB 直控 + OpenCV 视觉识别 + 固定点位搜刮
    • 一、前言
    • 二、整体架构与技术栈
    • 三、ADB 控制层:截图、点击、滑动
    • 四、核心难点一:怎么判断"真进游戏了"?
    • 五、核心难点二:识别"这把刷在哪个出生点"
      • 5.1 用圆检测把小地图"圆形抠出来"
      • 5.2 模板匹配识别出生点
    • 六、核心难点三:自动拾取物资
    • 七、把它串起来:固定路线
    • 八、一个诚实的工程结论
    • 九、总结
  • 源码链接:

从零实现《三角洲行动》手游自动跑刀脚本:ADB 直控 + OpenCV 视觉识别 + 固定点位搜刮

声明:本文仅用于分享 Android 自动化与计算机视觉的工程实践,所有内容面向技术学习。竞技游戏的用户协议通常禁止第三方自动化工具,请勿用于线上对局。Demo 与思路仅供研究,后果自负。
作者小金龙,代码可获取


先看看效果:

三角洲

https://www.bilibili.com/video/BV1AP7X6AEfh/?spm_id_from=333.1387.homepage.video_card.click

视频效果

一、前言

很多人见过 B 站、CSDN 上的"自动跑刀"脚本——进图后自动跑到几个固定点位搜刮物资。这类脚本到底怎么实现?本文以《三角洲行动》手游为例,完整复盘一套**「电脑 ADB 直控真机 + OpenCV 视觉识别 + 固定路线」**的实现方案,重点讲清楚四个工程难点:

  1. 怎么控制手机(截图 / 点击 / 滑动)
  2. 怎么判断"真进游戏了"(霍夫圆检测小地图)
  3. 怎么识别"这把刷在哪个出生点"(小地图模板匹配)
  4. 怎么自动拾取物资(物资标签检测)

以及一个绕不开的结论:为什么"固定点位"方案可行,而"自主智能跑图"不可行。


二、整体架构与技术栈

PC (Python) ├─ ADB 控制层 —— 截图 / input tap / input swipe ├─ 视觉识别层(OpenCV) │ ├─ 霍夫圆检测 —— 检测小地图 → 判定是否进图 │ ├─ 模板匹配 —— 小地图比对 → 识别出生点 │ └─ 区域裁剪/遮罩 —— 物资标签、按钮定位 └─ 决策/路线层 —— 每个出生点一条固定动作序列 ↓ ADB Android 真机 / 模拟器

技术栈

模块技术
设备控制ADB(platform-tools)input tap/swipeexec-out screencap
图像处理OpenCV-Python(HoughCirclesmatchTemplate、掩膜)
数值计算NumPy
语言Python 3.10

关键前提:MIUI / HyperOS 等系统默认禁用 ADB 模拟点击(INJECT_EVENTS权限),需在开发者选项中开启**「USB 调试(安全设置)」**(需插 SIM 卡 + 登录账号)。开启后adb shell input tap/swipe才可用,这是整套方案的基础。


三、ADB 控制层:截图、点击、滑动

一切的基础是「能截屏、能操作」。用subprocess包一层 ADB:

importsubprocess,timeimportnumpyasnpimportcv2 ADB=r"D:\platform-tools\adb.exe"SERIAL="你的设备序列号"# adb devices 查看defadb(*args,binary=False,timeout=20):cmd=[ADB,"-s",SERIAL]+list(args)r=subprocess.run(cmd,capture_output=True,timeout=timeout)returnr.stdoutifbinaryelser.stdout.decode("utf-8","ignore")defscreenshot():"""exec-out screencap 直接拿二进制 PNG,OpenCV 解码,无需落盘。"""raw=adb("exec-out","screencap","-p",binary=True)returncv2.imdecode(np.frombuffer(raw,np.uint8),cv2.IMREAD_COLOR)deftap(x,y,wait=1.2):adb("shell","input","tap",str(x),str(y))time.sleep(wait)defswipe(x1,y1,x2,y2,dur_ms=300):adb("shell","input","swipe",str(x1),str(y1),str(x2),str(y2),str(dur_ms))

对局内的"走位"和"转视角",本质也是 swipe:

  • 走位= 在左手虚拟摇杆上按住拖动一段时间(swipe的 duration 就是按住时长)。注意摇杆死区大,必须大幅度推满才会走:
defmove_forward(seconds):# 摇杆中心(430,760),向上推满 → 前进swipe(430,780,430,350,int(seconds*1000))deflook_right_90():# 右侧视角区横向滑动,约 480px ≈ 转 90°swipe(1700,500,2180,500,350)

横屏分辨率 2400×1080 下,这些坐标都是实测标定出来的。


四、核心难点一:怎么判断"真进游戏了"?

这是最坑的一步。游戏从「点击出发」到「真正进图」要经历:匹配 → 选干员 → 着陆确认 → 加载(约30s)→ 进图。早期我用"固定等 30 秒"或"识别匹配界面文字",都不稳——匹配时间不固定,加载界面文字时有时无,经常还没进游戏就开始乱跑刀

突破口:对局内左上角有个圆形小地图,而菜单/加载界面没有。于是用霍夫圆检测(HoughCircles):检测到小地图圆 = 真进游戏。

defdetect_minimap_circle(screen=None):"""检测左上角小地图圆,返回 (cx,cy,r) 或 None。"""ifscreenisNone:screen=screenshot()roi=screen[0:460,0:500]# 只在左上角找,提速g=cv2.medianBlur(cv2.cvtColor(roi,cv2.COLOR_BGR2GRAY),5)cs=cv2.HoughCircles(g,cv2.HOUGH_GRADIENT,dp=1,minDist=300,param1=100,param2=40,minRadius=140,maxRadius=215)ifcsisNone:returnNonec=cs[0][0]return(int(c[0]),int(c[1]),int(c[2]))defis_in_game(screen=None):returndetect_minimap_circle(screen)isnotNone

实测圆心稳定在(~277, 210)、半径~145,几乎每把一致。is_in_game()就是可靠的"进图判定",彻底解决了时序错位问题。


五、核心难点二:识别"这把刷在哪个出生点"

关键前提:很多人以为出生点随机,其实不少撤离类地图的出生点就那固定的几个。这意味着——只要识别出本把刷在哪个出生点,就能跑预先调好的对应路线。这正是"固定点位脚本"成立的根基。

识别靠小地图:它是北朝上 + 玩家居中的,所以同一个出生点,周围地形布局每次都一样,非常适合模板匹配

5.1 用圆检测把小地图"圆形抠出来"

直接方形裁剪会带进会变化的世界背景(四个角),干扰匹配。更好的做法是:圆检测定位 → 圆形掩膜把圆外涂黑 → 归一化尺寸

defget_minimap(screen=None):"""抠出圆形小地图(圆外涂黑),归一化 360x360。"""ifscreenisNone:screen=screenshot()circ=detect_minimap_circle(screen)ifcircisNone:returnNonecx,cy,r=circ r=min(r+8,cx,cy)crop=screen[cy-r:cy+r,cx-r:cx+r].copy()mask=np.zeros(crop.shape[:2],np.uint8)cv2.circle(mask,(crop.shape[1]//2,crop.shape[0]//2),r,255,-1)crop=cv2.bitwise_and(crop,crop,mask=mask)# 圆外涂黑returncv2.resize(crop,(360,360))

配图:圆检测 + 掩膜后抠出的干净圆形小地图。


有些出生点小地图上直接带地名(如"军营"“帐篷区”),还能用 OCR 读字辅助判断:

5.2 模板匹配识别出生点

提前在每个出生点出生瞬间采集一张圆形小地图存为模板(spawn1.pngspawn2.png…),进图后拿当前小地图逐一比对,取最高分:

importosdefdetect_spawn(screen=None,threshold=0.6):mm=get_minimap(screen)ifmmisNone:returnNonebest=Noneforfinos.listdir("templates/spawns"):tpl=cv2.imread(os.path.join("templates/spawns",f))iftplisNoneortpl.shape!=mm.shape:continueres=cv2.matchTemplate(mm,tpl,cv2.TM_CCOEFF_NORMED)_,maxv,_,_=cv2.minMaxLoc(res)ifbestisNoneormaxv>best[1]:best=(os.path.splitext(f)[0],float(maxv))returnbestifbestandbest[1]>=thresholdelseNone

采集规范(踩坑经验):模板必须统一风格才匹配得准——① 都在出生瞬间、未移动时采集(玩家居中、初始朝向);② 统一用"圆检测 + 掩膜 + resize 360×360";③ 小地图上的玩家箭头、队友标记、区域线是动态噪声,进阶可把中心圆区再挖掉,只比静态地形。


六、核心难点三:自动拾取物资

走到物资点后,画面右上方会弹出物资标签(如"9V电池")。坑点:拾取不是点屏幕固定的"交互键",而是点这个标签本身。

PICKUP_LABEL=(1600,280)# 右上角物资标签位置(横屏)defpickup():tap(*PICKUP_LABEL,wait=0.6)

点中后画面提示"已拾取 XX 到保险箱",即成功。

进阶可用模板匹配/颜色检测先判断"标签框是否存在",存在再点,避免空点。


七、把它串起来:固定路线

每个出生点配一条固定动作序列,识别到哪个出生点就跑哪条:

ROUTES={# 降落点:出生 → 前进2秒 → 右转90° → 点标签拾取"spawn2":[("forward",2),("look",480,0),("pickup",)],# 其它出生点继续补……}defrun_route(name):forstepinROUTES.get(name,[]):ifstep[0]=="forward":move_forward(step[1])elifstep[0]=="look":swipe(1700,500,1700+step[1],500,350)elifstep[0]=="pickup":pickup()

主循环:

defmain_loop():deploy()# 自动点出发/指挥出战进局ifnotwait_in_game(timeout=60):# 圆检测等进图returnspawn=detect_spawn()# 识别出生点ifspawn:run_route(spawn[0])# 跑对应固定路线extract()# 撤离/自杀back_to_lobby()# 退出结算 → 回大厅

八、一个诚实的工程结论

做下来最大的体会:"识别"不难,"导航"才难。

  • 能做到:CV 识别进图、识别出生点、识别物资标签;固定出生点 + 固定路线 + 自动进局/撤离/循环。
  • 做不到(靠脚本盲操作):像人一样"自主跑图、避开墙和障碍、找到好货"。3D 场景里盲走 ADB 反复撞墙撞围栏,这需要深度感知 + 路径规划(等于游戏 AI 自主导航),是另一个数量级的工程;而真正的"自动打人"= 目标检测自瞄 = 顶格外挂,必被反作弊封号。

所以"固定点位"方案之所以流行,正是因为它用确定性(固定出生点+固定路线)绕开了最难的自主导航——这是工程上的务实取舍。


九、总结

难点解法
控制手机ADBinput tap/swipe+screencap
进图判定霍夫圆检测小地图is_in_game()
出生点识别圆形小地图掩膜 +matchTemplate
物资拾取点右上角物资标签
智能跑图❌ 用"固定出生点+固定路线"务实绕开

整套方案把Android 自动化OpenCV 模板匹配 / 霍夫圆检测结合起来,是一个很好的"CV + 自动化"工程练习。

再次提醒:仅供学习计算机视觉与自动化技术,切勿用于线上竞技对局

源码链接:


如果这篇对你有帮助,欢迎点赞收藏。技术交流,理性使用。

http://www.cnnetsun.cn/news/3658021.html

相关文章:

  • 数据库挂了服务就瘫?我用PostgreSQL主从流复制搭了高可用架构,cpolar打通远程访问
  • 豆包直接生成 word 效率提升优选,AI 导出鸭整合多类文档导出方式,一站式搞定办公文档转换难题
  • 百考通:AI赋能标准化的格式,让学术梳理高效又专业,实现全流程智能化支撑
  • SCALE: Upscaled Continual Learning of Large Language Models
  • 焊线机与防火墙——楔子:凌晨三点的Fab
  • MFC List Control动态数据管理:从增删改查到虚拟列表与性能优化
  • API中转站选型指南:12项关键指标评估模型服务稳定性与成本优化
  • 深入解析TI MibSPI DMA寄存器:从原理到汽车电子高可靠应用
  • UniUGG系统:3D理解技术革新Linux文件管理
  • 5步彻底解决显卡驱动残留问题:DDU深度清理终极指南
  • 第五节 为什么工程师最容易把 bit 和 Byte 算错?一个大小写,让整个Camera带宽差了8倍!
  • Unity深度冲突解决方案:Reversed-Z原理与实战配置指南
  • 如何免费突破百度网盘限速:Python直链解析工具终极指南
  • 解决Windows中mfcm90u.dll缺失问题的完整指南
  • Token 消耗量,能否成为预测经济活跃度的新指数?-龍德明宇
  • Unity构建报错MSB3774:找不到WindowsMobile SDK的四种解决方案
  • Elasticsearch与Jina AI构建混合搜索引擎实践
  • XGBoost原理与贝叶斯优化调参实战
  • AI产品经理核心能力与技术栈全解析
  • Java:Spring/SpringBoot 核心注解全景总结(附极简Demo)
  • 微信DAT文件解密与EXE工具开发:从异或加密到PyInstaller打包实战
  • 三月七小助手:星穹铁道终极自动化解决方案
  • 电力系统智能运维:配电主站日志分析与AI异常检测
  • 写放大效应WAF:为什么你写入100GB,闪存却承受了300GB的磨损?
  • OpenAI自建数据中心:AI算力基础设施的技术变革与开发者影响
  • 量子思维在AI提示优化中的突破与应用
  • AI大模型工业级部署实战:从理论到落地的关键策略
  • 微信小程序电商项目实战uni-app(四)
  • Transformer在马尔可夫动态系统中的理论与应用
  • 2026金华企业GEO选型必备清单:10个关键问题帮你锁定合适服务商