Auto.js游戏脚本编写全攻略:从入门到进阶,带你玩转主动化 ...

打印 上一主题 下一主题

主题 1004|帖子 1004|积分 3012

1 先容


利用Autojs写游戏脚本,不像一般的APP可以直接操作控件,而只能通过基于坐标的操作完成。以是Autojs里关于控件的部分可以略过不看(除了多账号登录时的登录界面可能会用到一点控件操作,其他基本用不到),大致的学习流程:

  • 软件安装及情况搭建(版本选择、运行测试)
  • JavaScript基础语法学习(变量范例、流程操作…)
  • Auto.js分模块学习,如系统交互(文件读写、设备信息、打开应用…)、找图找色(游戏脚本的核心)、UI界面、多线程…
2 安装及情况设置

我用的是最新的AutojsPro9311版;app安装好了就可以在手机上编脚本了,但由于效率低大多数情况都是在电脑上编连接手机(或模拟器)举行测试,官方是通过VSCODE的一个插件来实现这一交互的。
安装好后把Auto.js-Pro-Ext这个插件装上,任意创建个.js文件会发现右边有个绿色的小安卓图标,点击后(或者通过快捷键Ctrl+Shift+p)发现可以通过输入IP(和电脑同一网络)、adb(插USB)两种方式连接,手机的话一般连接不会有什么问题,连接乐成的话右下角会有一行提示。 要注意的是如果利用的是模拟器,这时间的网络设置就有点麻烦了。比如我用的雷电模拟器,必要开启网络桥接模式、并设置好静态IP才气连接上。 连接上了之后当然是必不可少的hello world测试,常用的输出方式有3种:
  1. toast() //输出到手机屏幕
  2. log()   //输出到日志
  3. toastLog()  //前两者之和
  4. console.log()   //输出到控制台,console模块的一个成员函数,可以通过console.show()在手机上显示
复制代码
3 JavaScript基础

推荐直接去w3school或者runoob过一遍,这里只枚举一些我以为要注意的地方。


  • 直观感受,很多语法和C\C++一模一样(除了声明变量要用var、函数要加function…)。
  • undefined:只声明过但未赋值的变量。
  • ==与===: 前者是equality、后者为identity,即后者不会举行范例转换,范例差别的效果一定不等。
  • JS的数据范例:
    1. var length = 7;                             // 数字
    2. var lastName = "Gates";                      // 字符串
    3. var cars = ["Porsche", "Volvo", "BMW"];         // 数组
    4. var x = {firstName:"Bill", lastName:"Gates"};    // 对象
    复制代码
  • null:范例是对象,不存在的事物。
    1. null === undefined            // false
    2. null == undefined             // true
    复制代码
  • 对象: 通过关键词 “new” 来声明 JavaScript 变量,则该变量会被创建为对象。
    1. //也可以通过person.firstName="..."的方式初始化
    2. var person = {
    3.     firstName: "Bill",
    4.     lastName : "Gates",
    5.     id       : 678,
    6.     fullName : function() {   //成员函数
    7.       return this.firstName + " " + this.lastName;
    8.     }
    9. };
    复制代码
  • 在字符串中换行,必要加一个反斜杠(非ECMAScript标准):
    1. document.getElementById("demo").innerHTML = "Hello \
    2. Kitty!";
    复制代码
  • String和Number相加时,会将数字转为字符串;String和Number相减时,会将字符串转为数字;
  • 数组添加元素: array.push("value")
  • 常用对象: Date() (获取时间)、 Math() (常用数学工具)
  • use strict;: 定义 JavaScript 代码应该以“严酷模式”执行。
  • JavaScript的对象通过引用来寻址:
    1. //person是个对象
    2. var x = person;  // 这不会创建 person 的副本,x相当于person的别名,即引用
    复制代码
4 Auto.js常用下令及模块

下面分几个部分把编写游戏脚本时可能用到的模块全部讲一下吧,顺便对自己也是个学习完满的过程,全部学完花的时间可能比较多,自己也还有别的事要做,只管每天写一点吧。 官方文档地址:https://hyb1996.github.io/AutoJs-Docs/#/
官方文档已失效,本站已完美修复AutojsPro文档:https://www.wuyunai.com/docs
4.1 系统读写等操作

4.1.1 App、Device


  • 启动应用,有两种方式:

    • app.launchApp(appName),通过应用名称启动,即图标下显示的名称;
    • app.launch(packageName),通过包名启动,关于如何获取应用的包名后面会讲到,举个栗子:app.launch("com.bilibili.priconne");

  • 获取包名: app.getPackageName(appName),与此相对的还有根据包名获取应用名,举个栗子:
    1. appName = app.getPackageName("微信")
    2. toastLog(appName)
    3. //输出:com.tencent.mm
    复制代码
  • 读写系统剪切板
    1. setClip("将剪切板设置为这段话")
    2. //getClip()返回剪切板内容
    3. toastLog("当前剪切板:"+getClip())
    复制代码
  • 停止脚本: exit()
  • 设置脚本必要的安卓版本号
    1. requiresApi(24)// 需要至少Android 7.0
    2. requiresAutojsVersion("3.0.0")//指定Autojs最低版本号
    3. //会自动检测当前版本号,若过低会报错
    复制代码
  • 获取屏幕分辨率
    1. var Width=device.width;
    2. var Height=device.height;
    3. toastLog(Width+"x"+Height);
    复制代码
  • 获取设备识别码。Autojs里常用的设备标识是IMEI和ANDROID_ID。IMEI(International Mobile Equipment Identity)是15位数字构成的国际移动设备身份码,写在主板上和硬件绑定,就算刷机也没法改变。AndroidId 是一串64位的编码(十六进制字符串),是随机生成的设备的第一个引导,通过它可以知道设备的寿命;在设备规复出厂设置或刷机后,该值可能会改变,故和系统绑定。 当脚本要商业化的时间,可以通过设备码区分差别用户;如果脚本写出来只是一个人用,获取设备码应该也没啥用。
    1. var deviceId=device.getIMEI(); // 注意在Android10及后续版本失效
    2. var androidId=device.getAndroidId();
    3. toastLog(deviceId+"\n"+ androidId);
    复制代码
  • Device模块有很多功能,比如调整音量、屏幕亮度、获取内存和电量…但感觉写游戏脚本都用不到以是直接跳过吧。
4.1.2 Files

稍微复杂一点的脚本可能涉及到日志记录,比如刷了多少次图、有没有error之类,以是对文件的处置惩罚照旧挺有效的。

  • 返回路径
    1. var path1=files.cwd();   //当前工作文件夹绝对路径
    2. var path2=files.path(".");  //相对路径转绝对路径
    3. //还有一些不太常用的如files.getSdcardPath()、files.listDir(path[, filter])
    复制代码
  • 文件(夹)操作(返回bool)
    1. var path="/sdcard/newFolder/"
    2. if(!files.create(path)){}   //创建文件或文件夹,若已存在则返回false,(需要上一级文件夹已存在)
    3. files.createWithDirs("/sdcard/newFolder1/newFolder2"); //若不存在会创建一系列文件夹,比上一个命令更强大
    4. //还有些如删除文件、判断空文件夹等功能、略过。
    复制代码
  • 文件读写(和python似乎- -)
    1. var path = "/sdcard/1.txt";
    2. var text = "Hello, AutoJs";
    3. //以写入模式打开文件
    4. var file = open(path, "w");
    5. //open函数还可以指定文件编码
    6. // "r":读, "w":写 , "a":从文件末尾附加
    7. file.write(text);   //还可以:file.writeline()、file.writelines()
    8. // var text=file.read() ,或者file.readlines()
    9. file.close();
    复制代码
4.1.3 Shell

Autojs有shell函数和shell对象,前者适合执行单次下令,后者由于利用同一个shell进程以是对多条下令效率高:
  1. //shell函数,返回result对象;result.code返回码,成功为0;result.result,运行结果(字符串);result.error,无错误时为空,若未获取到root权限可能返回"Permission denied"。
  2. var result=shell("ls",true);
  3. if(result.code==0){toast("执行成功");}
  4. //shell对象
  5. var sh=new Shell(true); //构造函数
  6. sh.exec("ls");  //执行命令,注意该函数没有返回值!!  并且命令执行是"异步"的,不会等待上一步执行完成。
  7. sh.exit();  //强制退出
  8. sh.exitAndWaitFor();    //等待执行完成并退出
复制代码
4.1.3.1 Android常用shell下令



  • am
    1. # 感觉对写脚本没太大帮助...
    2. am start ...
    3. am kill ...
    4. am force-stop ...
    5. am restart ...
    复制代码
  • pm
    1. pm list packages #列出所有APP包,这个命令感觉有点用
    2. pm install ...
    3. pm uninstall ...
    复制代码
  • wm
    1. wm size #查看屏幕尺寸
    2. wm size 720x1280 # 修改尺寸
    3. wm size reset #还原
    复制代码
4.2 游戏脚本核心

4.2.1 触摸模拟(基于坐标)、Keys


  • sleep(n):停息运行n毫秒,游戏脚本中最常出现的一个下令;有一些操作必须给它一定的缓冲时间才气精确运行完成。
  • 随机数: random(min,max)指定区间、random()范围是[0,1);点击坐标时常设置一个随机偏移,防止被检测到(每次都点同一个点照旧太明显了)
  • 分辨率适配问题,setScreenMetrics(1080, 1920);、表现脚本适合的屏幕宽高为1080×1920(编脚本时基于的设备),如果在别的分辨率手机上运行则会主动放缩光标。听上去很好的一个功能,一般游戏脚本必加这一行,但具体效果如何我没有测试过。
  • click(x,y):点击坐标(无需root权限),返回是否乐成,点击过程约莫150ms,可能被其他变乱中断。更长时间的点击如longClick(x,y)、持续600ms。
  • press(x,y,duartion):按住坐标,一般超过500ms才被系统认为是长按。
  • swipe(x1,y1,x2,y2,duration): 从(x1,y1)滑动到(x2,y2),持续duration。
  • RootAutomator 上面的几个触摸操作都是免root的,而基于RootAutomator对象的触摸必要root权限,长处是执行没有延迟,明显比click要快。
    1. var ra=new RootAutomator(); //初始化一个对象
    2. ra.tap(x,y,id); //id代表不同“手指”,用于多点触摸,不需要时可省略该参数
    3. ra.swipe(x1,y1,x2,y2,duration,id)
    4. ra.press(x,y,duration,id)
    5. // 这些命令组合在一起就能完成复杂的操作了~
    6. ra.touchDown(x,y,id)
    7. ra.touchMove(x,y,id)
    8. ra.touchUp(id)
    复制代码
  • 模拟按键;(返回bool值)
    1. if(back()){};    //按下返回键
    2. home()  //返回桌面
    3. 还有一些需要root权限的,开头字母大写:
    4. //Home()、Back()、Power()、Menu()、OK()、KeyCode()...
    复制代码
4.2.2 colors、images

4.2.2.1 colors

颜色常用十六进制值或RGB值来表现,如蓝色可表现为#0000FF或(0,0,255),一般都是#后面带6位十六进制数,分别表现R、G、B,但Autojs是8位,前面多了一个A(Alpha)、表现透明度,即ARGB。

  • Autojs通过一个16进制整数或一个字符串表现一个颜色,两者可以相互转换
    1. var myBlue=colors.toString(color.BLUE); //返回#ff0000ff,colors.BLUE代表蓝色,后面必须大写。
    2. var numBlue=colors.parseColor("#ff0000ff"); //返回-16776961,至于为什么是这个数我也不清楚,平时还是用字符串表示比较好。
    复制代码
  • colors对象里还有一些判断两个颜色的相似度、返回A、R、G、B通道值的函数,平时也基本上用不上;颜色的用途主要表现在后面的多点找色上。
4.2.2.2 images

游戏脚本的灵魂所在,images主要有图片处置惩罚、找图、找色几个部分;想让脚本识别游戏的某个区域、如果该区域的位置是固定的,通过构造多点比色比较快,而如果位置不固定则常用找图的方式,虽然占用资源比较多但准确性有保障。

  • images对象利用完后必须接纳,防止内存泄漏。
    1. var img=images.read("./name.png");  //读取图片,错误时返回null
    2. //var img=images.load(url); //从网址获取图片
    3. //...图片操作后回收
    4. img.recycle();
    5. // 例外:captureScreen()返回的图片无需回收
    复制代码
  • images对象能对图像举行复制、生存、Base64编码解码、剪切、调整大小、放缩、旋转、拼接、灰度化、阈值化、颜色控件转换、二值化、模糊与平滑处置惩罚、滤波…(强是很强大,就是基本上用不上)
  • 获取截图权限:在找图找色之前通常要先获取当前屏幕的截图,这个截图一般是临时的、不会生存到文件(也可以设置生存)。 截图之前要向系统申请一次截图权限:
    1. if(!requestScreenCapture()){    //可指定参数true(横屏截图) 或者 false(竖屏截图)
    2.     toast("请求截图失败");
    3.     exit();
    4. }
    复制代码
  • 哀求截图: captureScreen
    1. //在此之前记住要请求一次截图权限
    2. var img=captureScreen();    //可以指定保存路径path
    复制代码
  • 颜色获取,很重要的一个函数,后面多点找色时可以先用它获取参数值。
    1. //获取某点的ARGB颜色值
    2. var color=images.pixel(img,100,200);    //img是之前创建的images对象
    复制代码
  • 区域找色(一种颜色);findColor、findColorInRegion、findColorEquals
    1. //首先说下region和threshold这两个参数,后面的找色函数options里都要用到:
    2. //region、找色区域,默认全图、指定[x,y]代表左上角点,从(x,y)到右下角;指定[x,y,width,height]则代表从(x,y)到(x+width,y+height)。
    3. //threshold、相似度临界值,0~255,默认为4;similarity=1-threshold/255,可以算出默认相似度达到了0.98,觉得太严了可以适当增大threshold
    4. var point = images.findColor(img, "#ff0000", { region: [100, 200], threshold: 10 });
    5. //如果找到则返回一个点,如:{463.0, 1242.0};找不到返回null。
    6. //这里颜色值是6位,8位也行不过会忽略A通道(透明度)。
    7. // findColorInRegion,功能和findColor一样,只是优化了下参数表示。
    8. var point=images.findColorInRegion(img,"#ff0000",100,200,1080,1920,10);
    9. // findColorEquals,要求颜色完全相等,相当于findColor的threshold参数设为0
    10. var point=images.findColorEquals(img,"#ff0000",100,200,1080,1920);
    复制代码
  • 多点找色:findMultiColors,先定位第一个点的颜色、根据(x,y)偏移获取并对比第二个点的颜色…以此类推,下令很麻烦,通常必要写一个函数来构造颜色列。
    1. var point = images.findMultiColors(img, "#ff949fc7",    //第一个点
    2.     [[60, 60, "#ffe6efe6"], //颜色Array,
    3.     [60, -60, "#ffeef3e6"],
    4.     [-60, 60, "#ffe6efe6"],
    5.     [-60, -60, "#ffeef3e6"]],
    6.     { region: [1548, 803, 140, 140] })  //指定区域
    复制代码
  • 检测某坐标颜色:前几个下令都是根据颜色找坐标,这个是给坐标、比较颜色
    1. if(images.detectsColor(img,"#fed9a8",100,200,16,"diff")){}
    2. //最后两个参数可省略,代表threshold和匹配算法;x=100,y=200
    复制代码
  • 找图:偶然间找颜色会匹配到一些奇怪的地方去,还得用找图来实现,有images.findImage、images.findImageInRegion、images.matchTemplate。
    1. var temp1=images.read(pathToImage);
    2. var point=images.findImage(img,temp1,{ region: [100, 200], threshold: 10 });
    3. //同样findImageInRegion只是优化了下参数排列
    4. //matchTemplate可以同时返回找到的多个位置,通过max控制最大的结果数量
    5. var result=images.matchTemplate(img,temp1,{ region: [100, 200], threshold: 10 ,max:5});
    6. //返回类型是一个MatchingResult对象,有point和similarity这两个数据成员。
    复制代码
4.3 脚本结构管理

4.3.1 Module

在一个文件里通过module.exports =...;把某个对象导出,从而可以在另一个文件通过var name=require('file.js');导入;相称于把整个文件当做一个函数,把exports的东西当做返回值。感觉用起来也不太方便,我选择不消这个功能。
4.3.2 Threads


  • 启动一个子线程,threads.start:
    1. //启动一个无限循环的线程
    2. var thread = threads.start(function(){  //用thread对象可以控制线程运行状态,如果不需要操作可以改为:
    3. //threads.start(function(){
    4.     while(true){
    5.         log("子线程运行中...");
    6.         sleep(1000);
    7.     }
    8. });
    9. sleep(5000);
    10. thread.interrupt();
    复制代码
  • threads.shutDownAll(): 停止所有通过threads.start()启动的子线程
  • 等待线程开始执行(一般start后必要一段时间):thread.waitFor();(这里thread是前面创建的thread变量)
  • 等待线程执行完成:thread.join();,参数可以指定一个等待时间
  • 中断线程运行:thread.interrupt();
  • 注意多线程中的变量问题,涉及到线程安全,文档里说的很详细
  • 线程间的通讯与通报变量,通过var connect = threads.disposable();实现;发送效果:connect.setAndNotify(s);,接收效果:connect.blockedGet(s);
4.4 交互界面

4.4.1 Events、Dialogs、Console

Events模块主要用来监听按键、触摸、关照等,但放在单线程里可能会因为步伐其他部分而无法及时执行,造成非预期的效果,常常和多线程`Threads`模块一起利用,如音量键关闭脚本的例子:
  1. auto();
  2. threads.start(function(){ //在子线程中调用observeKey()从而使按键事件处理在子线程执行
  3.     events.observeKey();    //启用按键监听
  4.     events.on("key_down", function(keyCode, events){
  5.     //常用事件有key、key_down、key_up、exit、toast、notification、touch(触摸某点)
  6.         if(keyCode == keys.volume_up){  //音量上键关闭脚本
  7.             exit();
  8.         }
  9.     });
  10. });
  11. events.on("exit", function(){   //脚本停止运行时会触发exit事件
  12.     toast("脚本已结束");
  13. });
  14. while(true){
  15.     log("脚本运行中...");
  16.     sleep(2000);
  17. }
复制代码
Dialogs 这部分提供对话框支持,但由于是弹出一个全屏的消息提示框,现实体验是并不太能用上;如果脚本和用户的交互性比较强的话可以考虑一下。
Console 控制台的作用更像是用于调试,但一般Windows下用VSCode写脚本也不必要在控制台上显示吧,以是这部分给人的感觉也是很鸡肋…不外console的UI是固定的,也可以悬浮、最小化;偶然不想设计UI的时间可以偷懒直接拿console过来凑合用用。
4.4.2 Floaty、UI

界面设计这部分内容相称多,而且官方文档也有很多写得很简略(甚至一笔带过),要想真正从零开始设计出一个实用悦目的UI出来照旧有难度的;我是建议去网上多找几个模板文件运行运行,在别人的基础上修改起来就快多了,看不懂的地方再去翻翻文档办理。一般UI设计好后再和步伐一对接(通过UI各组件的id),就可以打包做成apk了~
5 脚本实战:PriconneR

说来惭愧,作为一名二刺螈选手、PriconneR是我最近在玩的手游。一般我预备中长期玩的手游都会没事写写脚本,第一次从按键精灵转到用Autojs,就拿它作为案例练练手吧
5.1 差别机型适配

游戏脚本最开始要考虑的问题就是用户需求吧。如果只是自己用用,那就安卓模拟器任意选个分辨率就可以开始写了;但如果用户很多而且手机分辨率各不雷同,那在一开始写的时间就要注意适配的问题。我属于前者以是用模拟器就完事了~
5.2 需求分析

脚本必要实现哪些功能,这个必要对游戏有比较深的熟悉,至少要玩够一整天的游戏才会清楚哪些地方通过脚本实现比较方便、哪些地方手动就行了吧…把必要实现的功能全部列出来,偶然间可能总结的不够全面,这时间可以看看别人是怎么写的(下载个游戏蜂窝app,看看别人写的脚本有哪些功能),究竟论履历照旧这些专门靠写脚本赚钱的人比较丰富吧。
以PriconneR为例,我总结了一些重复性高、比较枯燥的部分(每日使命),如:公会点赞、技能强化、日常探索、领取礼品和使命嘉奖、刷地下城、免费扭蛋、装备升星… (玩过的肯定明白吧,每天都要刷的)
5.3 基础模块编写与调试

对于上面这些需求,可以按顺序来编写,比如可以拍一拍脑袋、就决定先实现日常探索这个功能吧!接下来要做的就是进一步分解,把要实现这个功能的每一个步骤列出来,把每一步作为一个基础模块写成一个function或是别的。
比如日常探索这个功能,起首要进入探索页面吧,为此必要定位的基准(如游戏主页)吧,究竟在哪个页面运行的脚本谁也说不准,那么第一个模块就是backToMainPage()了;进入探索页面后还必要决定刷哪一关、用券刷照旧手动刷、手动刷的话如何判断战斗结束、用券刷那么券没有了怎么办、刷完后会弹出一些确认窗口必要处置惩罚…一开始必要考虑的问题比较多没办法,但这些模块有很多是能直接放到别的功能中的,一般写着写着就会感觉越来越顺,之后要多考虑的通常是模块间的衔接,比如加个sleep(time)保证动作能够顺利完成。
然后是整合模块举行调试,看能不能完成目标功能,如果不能那么是哪一步出问题了(图片识别失败?、动作间停顿时间过短?、没考虑不测情况出现?…)。偶然间并不能立刻发现问题,而要比及用一段时间后。
5.4 功能实现

这一部分没啥好说的,一个功能完成、调试也没问题之后,那就下一个呗,只到实现所有当初列的需求功能。
5.5 UI制作

官方提供了很多案例,网上也有许多大佬自己做的美丽UI,选一个自己举行修改就行了。我选择的是一个悬浮窗范例的界面,可以最小化到窗口边沿不占位置,也方便及时调整脚本的运行状态。 一般勾选框比较常用,其次是下拉选择以及按钮,功能这块最好加一个中断当前脚本运行,防止脚本不精确运行。

5.6 利用中微调

一般最经常调整的东西有两大块:一是间隔时间,即动作之间的sleep(time)如何决定,这个要不停地尝试改良,没别的;二是图片识别,偶然间换个电脑换个模拟器脚本就没法识图了,这时通常要考虑:

  • 是不是图片选取不恰当,太小或者太大或者特性不明显
  • 识图函数准确度参数是不是设置的太高或太低了
  • 是不是用多点找色、区域找色等函数代替识图更好

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

反转基因福娃

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表