Skip to content
BaiRuic's Blog
Go back

autojs开发的脚本

Updated:

最近在玩一款游戏,叫部落冲突,里面又一个夜世界,操作呆瓜,很耗时,明显是用来提高用户的上线时间的,这我肯定不能忍,于是开始想着怎么用程序来提高效率,接着便发现了autojs这个神器。

目前autojs在维护的版本好像只有了 https://github.com/SuperMonster003/AutoJs6 ,由于比较小众,网上的资源其实并不多,最要命的是它文档还不齐全。在折腾了一天之后,终于被我开发出了一个可用的自动化版本。本文记录过程中的一些坑和一些可复用的代码片段。

首先是环境的配置,按照Github上项目的readme文档来,大概率可以正确的配置好。比较坑的一点是:写的代码可以自动同步到手机端,但是图片文件夹不行,这样每次截图就得手动通过数据线传到手机目录,感觉很愚蠢,但是还没找到解决方法。另外,该项目配套的AutoJs6 文档似乎没有在维护了,且已有的内容结构也很混乱,目前看下来最好的文档是在收集app上的示例代码。

常用函数

写游戏脚本,其实不需要UI,常用的函数大概只有如下几个。

点击函数

可以根据输入坐标来点击屏幕

/**
 * @see Internal.Automator.click
 */
declare function click(x: number, y: number): boolean;

长按函数

/**
 * @see Internal.Automator.press
 */
declare function press(x: number, y: number, delay: number): boolean;

可以根据输入的坐标和按下时间来长按屏幕

屏幕滑动

在游戏中,有时候需要在地图上不断的滑动,然后才能找到某个图标。

/**
 * @see Internal.Automator.swipe
 */
declare function swipe(x1: number, y1: number, x2: number, y2: number, duration: number): boolean;

子图匹配

autojs内置的子图匹配函数签名如下:

/**
 * @param img
 * @param template
 * @param [options={}]
 * @param [options.threshold=0.9]
 * @param [options.weakThreshold=0.6]
 * @param [options.level=-1]
 * @param [options.region]
 * @see images.findImage
 */
declare function findImage(img: ImageWrapper, template: ImageWrapper, options?: {
    threshold?: number;
    weakThreshold?: number;
    level?: number;
    region?: OmniRegion;
}): OpenCV.Point;

使用案例如下:

var tar = images.read(imgPath); 
var p = findImage(captureScreen(), tar, {
        threshold: options && options.threshold || 0.6
})
tar.recycle();

其中:

更加完整的使用示例见下一小节。

子图匹配场景

用来操作游戏的脚本中,有很多是需要 先匹配一个子图的位置,然后点击该位置,其实就是子图匹配的问题,autojs也提供了一个接口,但是游戏页面对于不同的皮肤,那些需要点击的按钮经常是颜色样式不一样的。于是就有了以下技巧,首先是把统一目标的多个皮肤子图都給截图截下来,按照如下的风格保存好:

    const recognizable = {
    "收集圣水车": {
        text: "收集圣水车",
        path: "images/收集圣水车_full_ysj.jpg"
    },
    "收集圣水车2": {
        text: "收集圣水车2",
        path: "images/收集圣水车_full2_ysj.jpg"
    },
    "收集圣水车3": {
        text: "收集圣水车3",
        path: "images/收集圣水车_full3_ysj.jpg"
    }
    }

然后通过一个while true循环来不断的找,只要匹配到一个,那么就可以break,代码如下:

function collect_sheng_shui_che(){
    let paths = [
        imgs['收集圣水车'].path,
        imgs['收集圣水车2'].path,
        imgs['收集圣水车3'].path,
    ]
    let is_success = false
    while(true){
        for (let i = 0; i < paths.length; i++) {
            if(cp.clickOne(paths[i])){
                is_success = true
                break;
            }
        }
        if (is_success){
            break;
        }
        sleep(3000)
    }
    toastLog("收集圣水车" + is_success)
}

该代码中用到了cp.clickOne(paths[i]) 函数,该函数参考自别人的代码,现拷贝如下:

/**
 * 
 * 随机点击小图的某个位置
 * @param {Number} pixel - 偏移像素最大值, 默认10
 */
capture.clickOne = function(imgPath, pixel, options) {
    //取得随机值<=pixel
    var i = 0;
    pixel = pixel || 10;
    var pix = Math.floor(Math.random() * pixel);
    prompt = prompt || true;
    if (capture.getOne(imgPath, function(p) {
            click(p.x + pix, p.y + pix);
            //log('点击了%d,%d', p.x + pix, p.y + pix);
            sleep(500);
        }, options)) {
        return true;
    }
    return false;
}


/** 
 * 当前界面里找小图,自动回收,返回该图坐标,支持回调函数, 参数是小图坐标
 * 
 * @param {string} imgPath - 匹配图片路径
 * @callback callback  找到则执行该函数
 * @param {Objcet} [threshold=0.6] - 图片相似度。取值范围为0~1的浮点数
 * @return {Point|null} - 找到返回Point对象,否则null
 */
capture.getOne = function(imgPath, callback, options) {
    var tar = images.read(imgPath);
    var p = findImage(captureScreen(), tar, {
        threshold: options && options.threshold || 0.6
    });
    tar.recycle();
    if (p) {
        if (callback && typeof callback === "function") {
            var fn = callback;
            res = fn(p);
            if (res) return res;
        }
        return p;
    } else {
        console.warn('没有找到图:' + imgPath);
        return null;
    }
}

Share this post:

Next Post
奇异值分解 Why What How