微信挑一挑

// 根据wangshub的Python代码修改而来(原项目地址https://github.com/wangshub/wechat_jump_game)

// 运行环境:安卓软件Auto.js(https://github.com/hyb1996/Auto.js), 下载地址: https://github.com/hyb1996/Auto.js/releases

// 需求root权限或者安卓7.0以上才能运行本脚本

// 在原算法基础上优化了找出棋子的算法(直接使用Auto.js内置使用opencv实现的找色函数, 比原算法快很多),但是在手机设备上找出跳跃位置的算法的效率还是不够理想

var press_coefficient = device.height == 1920 ? 1.392 : 2.099; // 长按的时间系数,请自己根据实际情况调节

const under_game_score_y = 300 // 截图中刚好低于分数显示区域的 Y 坐标,300 是 1920x1080 的值,2K 屏、全面屏请根据实际情况修改

//按压位置为再来一局的位置

const press_x = device.width / 2;

const press_y = 1584 * (device.height / 1920.0);

const piece_body_width = 80 // 棋子的宽度,比截图中量到的稍微大一点比较安全,可能要调节

const piece_dist_from_top_to_base = 188; //棋子最顶部到棋子底部中点的距离

// 下面的 (353, 859) 和 (772, 1100) 是游戏截图里的两个台子的中点坐标,主要用来算角度,可能要调节

const sample_board_x1 = 353;

const sample_board_y1 = 859;

const sample_board_x2 = 772;

const sample_board_y2 = 1100;

const piece_color = "#3d3752"; //棋子大致颜色

var w = device.width;

var h = device.height;

//使这些函数调用更方便

const red = colors.red;

const green = colors.green;

const blue = colors.blue;

const max = Math.max;

const abs = Math.abs;

//如果debug为true则开启调试,将会把每次计算的棋子位置和目标位置标记在截图中并保存在一下目录

const debug = false;

const debug_images_dir = "/sdcard/debug/";

prepare();

main();

function press_compat(x, y, duration) {

    if (device.sdkInt >= 24) {

        press(x, y, duration);

    } else {

        shell(util.format("input swipe %d %d %d %d %d", x, y, x, y, duration), true);

    }

}

function jump(distance) {

    var press_time = distance * press_coefficient;

    press_time = max(200, press_time);

    press_compat(press_x, press_y, parseInt(press_time));

}

function find_piece_and_board(im) {

    var piece = find_piece(im);

    if (!piece) {

        return null;

    }

    var board = find_board(im, piece);

    return {

        piece: piece,

        board: board

    };

}

function find_board(im, piece) {

    var board_x = 0;

    var board_y = 0;

    for (var i = parseInt(h / 3); i < parseInt(h * 2 / 3); i++) {

        last_pixel = im.pixel(0, i);

        if (board_x || board_y) {

            break;

        }

        var board_x_sum = 0

        var board_x_c = 0

        for (var j = 0; j < w; j++) {

            var pixel = im.pixel(j, i);

            // 修掉脑袋比下一个小格子还高的情况的 bug

            if (abs(j - piece.x) < piece_body_width) {

                continue;

            }

            // 修掉圆顶的时候一条线导致的小 bug,这个颜色判断应该 OK,暂时不提出来

            if (abs(red(pixel) - red(last_pixel)) + abs(blue(pixel) - blue(last_pixel)) + abs(green(pixel) - green(last_pixel)) > 10) {

                board_x_sum += j;

                board_x_c += 1;

            }

        }

        if (board_x_sum) {

            board_x = board_x_sum / board_x_c

        }

    }

    // 按实际的角度来算,找到接近下一个 board 中心的坐标

    var board_y = piece.y - abs(board_x - piece.x) * Math.sqrt(3) / 3;

    if (! (board_x && board_y)) {

        return null;

    }

    return {

        x: board_x,

        y: board_y

    }

}

function find_piece(im) {

    //使用内置找色函数找出棋子最顶部的位置

    var piece_top = findColor(im, piece_color, {

        threshold: 3

    });

    if (!piece_top) {

        return null;

    }

    var piece_start_x = -1;

    var piece_end_x = -1;

    //遍历该行找出棋子顶部中点位置

    for (var x = 0; x < w; x++) {

        var is_piece = images.detectsColor(im, piece_color, x, piece_top.y, 2);

        if (is_piece && piece_start_x < 0) {

            piece_start_x = x;

        }

        if (!is_piece && piece_start_x >= 0) {

            piece_end_x = x;

            break;

        }

    }

    //棋子顶部中点位置

    var piece_top_center_x = (piece_start_x + piece_end_x) / 2;

    var piece_x = piece_top_center_x;

    var piece_y = piece_top.y + piece_dist_from_top_to_base;

    return {

        x: piece_x,

        y: piece_y

    }

}

function main() {

    toast("请在5秒内打开游戏,并点击开始按钮");

    waitForPackage("com.tencent.mm");

    sleep(5000);

    while (currentPackage() == "com.tencent.mm") {

        var im = captureScreen();

        // 获取棋子和 board 的位置

        var result = find_piece_and_board(im);

        if (!result) {

            sleep(1000);

            continue;

        }

        var board = result.board;

        var piece = result.piece;

        log("find result: ", result);

        if (debug && result) {

            save_result(im, result);

        }

        jump(Math.sqrt(Math.pow(board.x - piece.x, 2) + Math.pow(board.y - piece.y, 2)));

        sleep(2000);

    }

}

function prepare() {

    //确保无障碍服务开启

    auto();

    //请求截图权限

    requestScreenCapture();

    device.keepScreenOn(1000 * 3600);

    events.on("exit", function() {

        device.cancelKeepingAwake();

    });

    if (debug) {

        files.ensureDir(debug_images_dir);

    }

    //从存储中读取系数

    var storage = storages.create("org.autojs.wxjumping");

    press_coefficient = storage.get("press_coefficient", press_coefficient);

    //让用户输入系数

    press_coefficient = dialogs.input("调整跳跃系数(可选)", press_coefficient);

    storage.put("press_coefficient", press_coefficient);

}

function save_result(im, result) {

    importPackage(android.graphics);

    var bmp = im.getBitmap();

    var canvas = new Canvas(bmp);

    var paint = new Paint();

    paint.setStyle(Paint.Style.FILL);

    paint.setColor(colors.rgb(255, 0, 0));

    drawCircle(canvas, result.piece, paint);

    paint.setColor(colors.rgb(0, 255, 0));

    drawCircle(canvas, result.board, paint);

    var out = new java.io.FileOutputStream(files.join(debug_images_dir, new Date().getTime() + ".png"));

    bmp.compress(Bitmap.CompressFormat.PNG, 100, out);

}

function drawCircle(canvas, point, paint) {

    canvas.drawCircle(point.x, point.y, 8, paint);

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335