触动精灵脚本开发
下载地址
https://www.zhengdianxue.com/wp-content/uploads/skills/org-4nzlhlow--touchsprite.zip将提示词发送给你的 AI 安装该 skills
请根据 https://skillhub.cn/install/skillhub.md,安装 @org-4nzlhlow/touchsprite。触动精灵(TouchSprite)Lua 脚本开发辅助。
阅读全文 (展开查看完整说明)
概述
概述
触动精灵是模拟手机触摸、按键操作的自动化软件,底层用 Lua 5.2.3,在标准语法之上提供取色、找色、找图、发送触摸事件、原生 UI 等扩展函数,支持 iOS 与 Android。写脚本的核心思路是:用引擎给的能力拼装流程,而不是用 Lua 重新实现引擎已有的能力。
六条铁律(优先级最高,与后文冲突时以本节为准)
铁律 1 — 只用触动自有函数,不自造轮子
选实现方式按这个阶梯往下走,能用上层就绝不往下走:
| 层级 | 来源 | 举例 |
|---|---|---|
| ① 引擎全局函数 | 触动内置 | touchDown/touchUp、findColorInRegionFuzzy、findMultiColorInRegionFuzzy、findImage、snapshot、keepScreen、getColorRGB、dialog、showUI、mSleep、vibrator、writePasteboard、runApp |
| ② 官方函数库 | require 后使用 | TSLib(便捷 UI)、ts.so(文件/plist/数据库/加密/ts.json)、tsnet.so(http/ftp)、webview、event、thread |
| ③ Lua 标准库 | 语言自带 | io、os、string、table、math |
| ④ 自写算法 / 外部方案 | 最后手段 | 自写像素扫描、自写 JSON、外部命令行、第三方 Lua 库 |
硬性禁止:
- 使用
sz.so(require("sz")、sz.json、sz.pos):该库已停止运营,见到就换 —— JSON 用 ts.so 的ts.json,屏幕坐标相关用getColorRGB/findImage/moveTo - 已有原生实现却自己重写:找色找图、截图、JSON 编解码、文件读写、UI、OCR、震动、剪贴板、日志
- 用
os.execute/ shell / 外部工具做脚本内能做的事(如图色处理、文件搬运) - 引入第三方 Lua 库、外部服务或自建 socket 替代
tsnet.so - 为「以后可能要兼容」预先手写大段适配层(见铁律 2)
允许自写的情形(必须先用一句话说明为什么,代码一般 ≤ 15 行,且内部只调触动原生函数):
- 原生函数在部分引擎版本缺失或必报错(
file_exists、os.mclock、ts.json) - 原生返回值结构不稳定,需要薄封装(
catchTouchPoint跨版本返回格式不一致) - 原生能力确实不够(如需要多点批量采样做画面指纹)
反例对照(写之前先自查):
| 需求 | 不要这样 | 应该这样 |
|---|---|---|
| 找色/找图 | 遍历像素自己算相似度 | findColorInRegionFuzzy / findMultiColorInRegionFuzzy;找图 snapshot 截小图 + findImage(两端都支持) |
| 滑动 | 手写 touchMove 循环算插值 | moveTo(x1,y1,x2,y2,step,ms,index,stop)(step 默认 10、ms 默认 50、stop=1 治惯性) |
| 安卓点击没反应 | 换 os.execute 或死磕 touchDown | touchInputDown/Move/Up(仅 Android v3.1.0+,专治 H5 页面) |
| 找字 | 自己切图比对点阵 | ppOcrText / tsFindText / tsOcrText |
| 截图取色 | 外部 adb / 读图逐像素 | snapshot()、getColorRGB() + keepScreen() |
| JSON | 手写编码器 | require("ts").json(仅缺失时兜底) |
| 文件操作 | os.execute("cp ...") | io.open / readFile / ts.hlfs.copyFile |
| 网络请求 | 自写 socket | require("tsnet") 后 http.* / ftp.* |
| 界面 | WebView 里塞 HTML 堆控件 | 便捷 UI / showUI |
| 延时等待 | os.time 忙等 | mSleep(ms) |
| 提醒用户 | 弹系统通知 | vibrator() / toast / dialog |
| 输入文字 | 模拟系统输入法点击 | writePasteboard + 粘贴,或 dialogInput 取值后按业务写入 |
铁律 2 — 要兼容多种情况,先问,不要自己铺兼容层
命中下列任一情况,先停下提问,说明「这里可以只按一种情况写,也可以做兼容」,给 1~3 个选项 + 各自代价,用户选定再动手:
| 兼容维度 | 可选档位(由简到繁) |
|---|---|
| 分辨率 | ① 只按给定分辨率写死(推荐) ② 比例坐标 / setScreenScale() 缩放 ③ 逐机型偏移表 |
| 平台 | ① 只写一端(推荐) ② 双端 + getOSType() 分支 + 独占 API 走 pcall |
| 机型/系统版本 | ① 只管用户手上这台 ② 按 getDeviceType() 分支 |
| app 版本 / 界面差异 | ① 只认当前版本(推荐) ② 多点比色做多状态判断 |
| 异常情况 | ① 只处理主流程 ② 补掉线/弹窗/超时兜底 |
默认立场:写死是合法的。 用户没要求兼容,就不要顺手加 getOSType() 分支、分辨率表、多套坐标、满屏 pcall。兼容层是用户点了才加的东西。
提问示例(照这个格式说):
这个坐标要不要兼容别的分辨率?① 只按 720×1280 写死(最简单,10 行搞定)② 改成
w*0.5比例坐标(多改 3 处,多数机型能跑)③ 逐机型偏移表(多 40 行,最稳)
铁律 3 — 最短能跑,禁止过度设计
默认交付「能跑的最短版本」,而不是「功能齐全的框架」:
- 只写用得到的函数。没有第二个调用者就不要抽工具函数,直接内联
- 不预埋模块:没要求就不给 UI、不给日志系统、不给配置文件读写、不给设备适配表、不给错误码体系
- 单文件交付,不拆多文件、不写
require自有模块、不写 class 式封装 - 行数预期:常规需求 40~150 行。超过 200 行必须说明为什么(几个模块、各占多少行);超过 400 行先给骨架再分段补,不要一次性抛几百行
- 注释只写「为什么」,不写「这行在做什么」。关键决策处一行足够
pcall只包已知会报错的调用(双端差异、版本差异),不无脑包裹每一个函数- 不做没要求的抽象:不写通用配置框架、不写状态机、不写插件式任务注册
- 用户明确要「完整版 / 一次性全给」时才展开
铁律 4 — 需求缺口先问清
写第一行代码前确认这五项,缺哪项问哪项,一次问完,每项给候选方案 + 推荐项(不要让用户回答开放式问题):
| 维度 | 需要确认 | 缺省推荐 |
|---|---|---|
| 平台 | iOS / Android / 双端 | 按用户手上设备写一端;未说明则问 |
| 分辨率 | 具体值 / 自适应 | 按用户给的写死,不做自适应 |
| 场景 | 目标 app、关键流程、判定依据 | 必须问清,不臆造坐标与色值 |
| UI | 无 / 便捷 UI / showUI / WebUI | 简单配置用便捷 UI;多功能分页用 showUI |
| 运行 | 单次 / 循环 / 定时 | 循环 + 手动停止 + 超时退出 |
确认完用一句话复述(平台 / 分辨率 / UI / 运行方式),得到认可再开工。素材(坐标、色值、截图、字库)必须用户提供,不许编。
铁律 5 — 卡住先提问,不硬猜
遇到这些先问再动代码:API 签名或版本不确定、iOS/Android 行为不一致、需求与已写代码冲突、缺关键参数。提问固定三件套:
- 一句话说清卡在哪(带函数名或行号)
- 给 1~3 个可选方案,标出推荐
- 每个方案的代价(改多少代码 / 要不要补素材 / 兼容性差异)
用户选定后只改选中的那套,不要同时铺两套实现让用户挑代码。
铁律 6 — 省 token,但不牺牲准确性
- 按需读参考:
references/合计 100k+ 字符,先 Grep 函数名拿行号,再带offset/limit局部读,禁止整文件读入 - 不重复输出:已交付的代码不复述,改动只给片段(函数名 + 改哪 + 前后 3 行)
- 一次写对:交付前跑 luaparser 语法校验 + Python 正则审计,返工最费 token
- 少解释多代码:文字只讲关键决策和易踩的坑,不复述 API 参数表
开发流程
1. 确认需求
按铁律 4 的五项问完并复述。运行时信息在脚本内确认:getTSVer()(引擎版本,影响 API 可用性)、init(rotate) 定屏幕方向(0=竖屏、1=Home右、2=Home左)。
2. 写脚本
默认从 references/script_templates.md 的「精简脚本模板」(约 40 行)起步,按需求往上加;不要拿完整版框架往下删。硬性底线:
- 开头
init(rotate);路径用userPath(),不硬编码 touchDown/touchMove/touchUp之间必须mSleep(≥ 20ms)- 颜色写成
0xffffff形式,注意 RGB 顺序 keepScreen(true)之后必须keepScreen(false)释放
3. 构建 UI
| 方式 | 说明 | 适用 |
|---|---|---|
| 便捷 UI(TSLib) | 函数式逐条加控件,代码最少 | 简单配置(默认选它) |
| showUI | table 定义,支持多页 Tab 与自定义布局 | 多个分组 / 多页设置 |
| WebUI | WebView + HTML/JS | 仅当需要图表、动态渲染等原生做不了的视觉 |
用户偏好(实测):用户说的「高大上 / 功能复杂的 UI」指用触动原生函数堆出来的界面,不是 WebView 里塞 HTML。这类需求默认走 showUI 多页 Tab,逻辑层配 catchTouchPoint / getColorRGB / findMultiColorInRegionFuzzy / touchDown。
可视化设计器:登录 https://account.touchsprite.com 可拖拽生成便捷 UI / showUI 代码。各控件完整属性见 references/convenient_ui_guide.md、references/api_reference.md 第 3 节。
showUI 多页 Tab 骨架(真机验证:pagetype="multi" + pagenumtype="tab" + titles 逗号分隔 + pages={}):
local ts = require("ts")
local ui = {
["style"] = "default",
["rettype"] = "table",
["config"] = "cfg_v3.txt", -- 改结构就换文件名,旧配置不会失效
["pagetype"] = "multi",
["pagenumtype"] = "tab",
["titles"] = "基本,高级",
pages = {
{ {["type"]="Label", ["text"]="模式:"}, {["type"]="RadioGroup", ["id"]="mode", ["list"]="普通,精英", ["select"]="0"} },
{ {["type"]="Edit", ["id"]="cnt", ["prompt"]="次数", ["text"]="10", ["kbtype"]="number"} },
},
}
local ret, v = showUI(ts.json.encode(ui))
if ret == 1 then nLog(v.mode .. "/" .. v.cnt) end4. 调试与交付前校验
nLog(msg)输出到 TS Studio 远程日志;toast看即时值;dialog(msg, 0)阻塞查看变量catchTouchPoint()取点定位;string.format("0x%06x", getColor(x,y))打印色值- 交付前必做:luaparser 语法校验
# pip install luaparser(本机已装)
from luaparser import ast
ast.parse(open("脚本.lua", encoding="utf-8").read()) # 语法错误会抛异常luaparser 只认语法、不认触动扩展函数,逻辑仍需上机验证。再加一轮 Python 正则审计(见「常见陷阱 · 交付校验」)。
本机环境提示:PowerShell 工具不回传 stdout,需把结果写文件再读;ls/grep 不可用,文件操作用 Python 脚本完成。
代码格式规范(对齐 open_code 真实源码)
依据 chudongjingling/open_code 里
万能点击.lua、通用无限点击脚本.lua、精准滑动.lua、多点模糊比色.lua、热血传奇源码V3.2.lua的实际写法。这几份是圈内流传的成品,代表触动开发者的默认习惯——照着写,不要按自己的审美重排。
结构与调用
- 单文件
.lua,文件名用中文或拼音描述功能(万能点击.lua),不拆模块、不 require 自有文件 - 函数全部先定义,最后一行顺序调用入口(
Main()/setDirection() main());入口叫Main/main/zhuchengxu都行 - 短脚本不写
beforeUserExit,直接lua_exit()收尾;只有要keepScreen(false)、关日志、关 view 时才补回调 - 不用
-- ==== 初始化 ====那种大 banner,靠函数名 + 一行中文注释分段
缩进与空白
- 缩进用 Tab(TS Studio 默认),不要空格、不要混用;连续赋值处用 Tab 对齐等号:
ClickInterval = tonumber(ClickInterval)
Interval = tonumber(Interval)命名
- 函数和变量用全小写拼音直拼,长就长,不缩写成看不懂:
zhuchengxu(主程序)、piliangfenjiejiange(批量分解间隔)、huichengxueliang(回城血量)、pd前缀做判断(pddengji、pdzhidongzhandou);也接受My+ 中文混写(My主函数),但纯拼音复制不易乱码 - 全局状态用
g_前缀的表:g_t_Table(多点比色表) - 不要为省事全用 local:真实成品几乎全是全局函数。规则——函数和脚本级配置变量用全局,循环里的临时变量用
local
配置与界面
- showUI 优先 JSON 长括号串(不依赖任何库,还能直接拼运行时数值);控件多、要程序生成时用 ts.so 的
ts.json.encode(table)。不要用sz.json,sz.so 已停运
MyJsonString = [[
{ "style":"default", "config":"wuxiandianji", "width":]]..w..[[, "height":]]..h..[[,
"okname":"开始", "cancelname":"取消", "views":[ ... ] }
]]
ret, x, y = showUI(MyJsonString)config 写文件名即可(带不带 .dat 都行,官方默认 uiconfig.dat);页容器单页 views、多页 pages;默认模式按控件顺序返回多值,rettype="table" 才按 id 返回
- 能不用 UI 就别用 UI:一两项设置直接
dialogRet选分支 +dialogInput取值 +catchTouchPoint取点,比搭 showUI 少几十行
注释
- 函数上方一行中文说明;带参数时用对齐的参数表:
“lua --[[单击方法参数说明:ClickX = 点击X坐标ClickInterval = 按下抬起间隔]]-- “
- 行内注释只写单位 / 默认值 / 枚举含义(
-- 按下抬起间隔 默认30、-- 0:竖屏 1:Home右),不逐行复述代码,不写英文
成品里的固定套路
- 多值配置一行逗号接:
ret,dengji,shezhi1,putongrenwu = shezhi() - 多选值判断用包裹法,避免
2@误匹配12@:if string.find("@"..v.."@","@2@") then tonumber就地转、失败给默认值兜底,不做统一校验层- 滑动用原生
moveTo(x1,y1,x2,y2,step,ms,index,stop)(step 默认 10、ms 默认 50、stop=1治惯性滑动),末尾补一次 1~2 像素的反向moveTo压回弹;不要手写touchMove循环 - 多点比色分两种:全屏绝对坐标 → 自写
multiColor(array,s)+keepScreen批量取色;已知区域内相对偏移 → 原生findMultiColorInRegionFuzzy
禁止:class 封装、插件式注册、满屏 pcall、拆成多个 require 文件、为「通用」而抽象
API 速查(只列高频,签名细节查 references)
- 触控:
touchDown/touchMove/touchUp、moveTo(x1,y1,x2,y2,step,ms,index,stop)(原生滑动,优先用它,需require "TSLib")、touchInputDown/Move/Up(仅 Android,H5 页面点击无效时用)、catchTouchPoint、mSleep - 图色:
init(rotate)、getScreenSize()、setScreenScale()、keepScreen(flag)、getColor/getColorRGB、findColorInRegionFuzzy、findMultiColorInRegionFuzzy、findMultiColorInRegionFuzzyExt、findImage/findImageInRegionFuzzy、snapshot、getSnapshotData(直接拿 png/jpg/rgb 二进制) - UI:
dialog(text,time)、toast、dialogRet、dialogInput、showUI(json)、showFloatButton - 便捷 UI(TSLib):
UINew / UIShow / UILabel / UIRadio / UICheck / UIEdit / UITextArea / UICombo / UIComboRlt / UIImage - 脚本控制:
lua_exit、lua_restart、luaExitIfCall、beforeUserExit、nLog、vibrator - 文件:
userPath()、isFileExist(path)(判存在,返回bool, kind,需 TSLib)、io.open、getFileSize、delFile、ts.hlfs.copyFile;file_exists/readFile/copyfile是官方示例里让你自己定义的辅助函数,引擎没有 - 系统:
runApp/closeApp/isFrontApp/frontAppBid/openURL、writePasteboard/readPasteboard、setVolumeLevel/setBacklightLevel - 设备:
getTSVer、getOSType("ios"/"android")、getOSVer、getDeviceType、getMemoryInfo;电池用batteryStatus()(无getBattery);网络类型 iOS 用ts.getNetType()(无getNetworkType),IP 用getNetworkIP()(仅 Android)
函数库选择:网络请求优先 tsnet.so(require("tsnet") 后 http.*/ftp.*),其次 ts.so;文件/plist/数据库/加密走 require("ts") 的 ts.*。
文字识别优先级:ppOcrText(飞桨,精度最高)> 百度云端(需 token)> tsOcrText/tsFindText(点阵字库)> ocrText(谷歌字库,中文差)。
常见陷阱(按类合并,交付前逐条自查)
A. 坐标与图色
- 截图/找图区域右下角写
width-1, height-1:旧版本越界会 iOS 报错、Android 截白图(新版本已修复,但沿用不亏) findImage/findImageInRegionFuzzy的图片默认从 res 目录找,自建目录要写相对路径degree建议 85~95,过低性能暴跌posandcolor里是相对基准点的偏移,可为负- 批量
getColor前keepScreen(true),后必须keepScreen(false) - 雷电 9 平板模式
getScreenSize宽高相反 - RGB565 位域:
(R>>3)<<11 | (G>>2)<<5 | (B>>3),中间通道是 6 位
B. 版本与双端
file_exists/readFile/copyfile不是引擎函数,是官方教程里让你自己写的辅助函数(内部io.open/os.execute)。判存在用isFileExist(path)(TSLib,返回bool,kind),复制用ts.hlfs.copyFile——官方示例的os.execute("cp -rf ...")在高版本 iOS 上会失效,官方自己都标注了要换os.mclock等毫秒计时器不统一,os.clock在部分环境不随mSleep前进。先探测(睡 500ms 看差值量级),探测不到就降级跳过catchTouchPoint(n)传数字时返回 n 个点的 table(ret[i].x/ret[i].y);无参版返回单点。返回的是竖屏坐标,横屏要换算;部分安卓模拟器、虚拟大师不支持。取点前先mSleep(600+)lua_exit()不是立即结束,是执行到下一行才终止;想立刻断就在后面补一行mSleep(10),还不行换luaExit()moveTo/ 便捷 UI 全系列 /isFileExist等都在 TSLib 里,脚本开头要require "TSLib"(引擎已内置文件,不用自己放)- TSLib
touch()链式滑动:v1.4.4 及以下版本手指序号为空可能导致安卓手机重启,v1.4.5 已修;手指数不要超过 15 - 仅 Android:
getIMEI/getUUID/getDeviceBrand/getDeviceModel/getCPUType/getNetworkIP/getDPI/getSDCardPath/getStatusBarHeight/install/uninstallApp/closeAllApp/stopAudio/zip/touchInput* - 仅 iOS:
getRender/ts.getNetType/ts.system.udid/ts.system.space/ts.system.localwifiaddr/ts.img.*/ts.imgFindColor/ts.binaryzation/ts.plist.*/ts.config.*/ts.hlfs.getFileEncoding/ts.hlfs.codeConvert/sysLog/snapAndSave ts.httpGet两端签名不同:iOS(url, header_send, body_send);Android 新版(url, {tstab="tstab", header_send=..., body_send=...})- 基准分辨率常不同:Android 多用 720×1280,iOS 多用 750×1334
C. UI
UINew官方签名:UINew(pagination, titles, okname, cancelname, config, orient, timer, width, height, bgcolor, btnbkcolor, bg, pagenumtype, selpage, titlesize, titlealign)。第一位是页数,单页时可省略(引擎按类型判断);没有 x/y 位置参数。稳妥写法先pcall(UINew, title, ok, cancel, config)只传 4 个,逐级降级- 便捷 UI 控件第一个参数也是页码
num:UILabel(num,text,size,align,color,width,nowrap,valign);且「参数写了后面就必须带上前面所有」——想只设 text 就用 table 写法UILabel({text="标题"}) - 多页必须显式传页数:
UINew(3, "页1,页2,页3", ...),否则仍建 1 页,插第 2 页控件报「请在有效页数内插入」 width语义:-1自适应屏幕 /0占整行 /≥1具体数值(仅 Android v3.2.0+、iOS v3.1.5+);Android 只吃整数,给小数会报「UI 格式错误」nowrap是「下一个控件不换行」,填 1 会把下一个控件挤到同行;整行布局一律填 0- showUI 页容器字段:单页
views、多页pages(pagetype="multi"+titles);width ≥ 400、height ≥ 120;config不写就不保存配置 - iPad(iOS 9+)用 showUI 必须指定
orient,否则确定/取消按钮可能点不动 CheckBoxGroup返回的是索引串("0@2",索引从 0 开始),要string.gmatch(v,"%d+")拆再+1映射 key 数组;RadioGroup/ComboBox才返回文字- 选项文案里不能出现英文逗号(分隔符),需要时用
table.concat({...}, ",")拼 config会持久化,改 UI 结构后旧配置不失效 → 版本号写进文件名(cfg_v3.txt)Label的 text 可运行时拼(先采集设备信息再showUI,界面就成实时面板)- JSON 编码统一走 ts.so:
local ts = require("ts")然后ts.json.encode(tb)/ts.json.decode(str)。require("sz")那套(sz.json/sz.pos)随 sz.so 停止运营已不可用,老脚本里见到要换掉;ts.json也拿不到时才自写编码器(先转义再转义") keepScreen(true)钉住的是调用那一刻的帧:先取点 → 再keepScreen(true)→ 批量取色 →keepScreen(false)
D. 文件与文本
- 截图文件名必须每次唯一:
os.date("%Y%m%d_%H%M%S")+ 随机数,写前os.remove,写完轮询「存在 && 大小 > 1KB」,否则io.open会读到上一张旧图。snapshot相对名默认落 res 目录,不同引擎对绝对路径支持不一致 - 结果 txt 给记事本留 UTF-8 BOM(
"239187191"),json 不要 BOM。中文乱码多半是打开方式按 ANSI 解码,不是脚本 bug
E. 运行与协程
thread.create是协程,不是真并行xpcall参数与 5.1 不同、module已移除、goto标签不能纯数字- WebView 有计数保护,到阈值(如 5 次)后
lua_restart();JS 与 Lua 两端都要防抖 view.close()/event.unregister()用pcall包;view.show()后必须thread.waitAllThreadExit()
F. 交付校验(顺序固定)
luaparser语法校验- Python 正则审计四项:配置读取的
v.xxx都在 UI 里定义过;CheckBoxGroup选项数与 key 数组长度对齐;平台独占函数都在pcall或以字符串调用;touchDown到touchUp之间都有mSleep - 涉及色彩/数值换算的公式,用 Python 对着公开标准值比对
- 不要生成 HTML 预览页「看效果」——用户用的是手机原生 UI,桌面预览无参考价值
资源文件
| 文件 | 用途 |
|---|---|
references/api_reference.md | 完整 API 参考(触控/图色/UI/WebView/文件/设备/OCR/协程/网络) |
references/tsso_reference.md | ts.so 库参考(JSON/文件/plist/config/数据库/网络/FTP/二值化/加密)——sz.so 已停运,这类能力一律走这里 |
references/convenient_ui_guide.md | 便捷 UI(TSLib)全部控件文档 |
references/webview_ui_guide.md | WebUI 架构、通信、生命周期 |
references/community_patterns.md | 社区实战模式(命名、防卡死、多设备、紧凑写法) |
references/script_templates.md | 精简脚本模板(默认)、基础脚本模板(完整版)、浮动窗口 HUD、WebView 菜单模板 |
读取策略:合计 100k+ 字符,禁止全读。已知函数名 → Grep 定位后局部读;要骨架 → 只读 script_templates.md 的「精简脚本模板」段(40 行);UI 选型已定 → 只读对应那一份。
参考资源
- 官方开发手册:https://helpdoc.touchsprite.com/dev_docs/598.html — 函数页地址形如
/dev_docs/{章}/{节}.html(如 showUI =12/5、moveTo =7/17、isFileExist =13/26)。拿不准签名就站内搜函数名,别凭记忆写 - GitHub 真实成品集:chudongjingling/open_code
- 官网:https://www.touchsprite.com ;TS Studio(v3.0+ 内置抓色、远程日志):https://www.touchsprite.com/download