分享一 AutoJs 蚂蚁森林自动收取能量和偷取能量
首先声明,代码不是本人所写,只是做了点改动。本文的目的一是分享给大家,二算是记个笔记方便以后看。
最近看到AutoJs可以收蚂蚁森林的能量,自己也想写一个,所以就搜了几个大神的代码,在此基础上,边看边改,终于成功了,代码来自:https://blog.csdn.net/kimipoker/article/details/79845261。此代码只用于1920x1080分辨率,别的手机需要自己改动。还有,AutoJs的App提供了定时任务功能(像闹钟一样),可以设置你的脚本什么时候运行,一般来说能量在早上7点多熟,所以夜间需要哦开着AutoJs会消耗比较多的电量。
首先说下AutoJs怎么用:下载一个AutoJs的App,然后在里面编写Js代码就可以运行了,因为刚开始看AutoJS,只看到别人写的代码,也不知道这代码怎么运行。有2.,3.,4. 几的版本,我只下了3.几的版本,安装好后开启无障碍模式就可以了。
开发环境:小米Note3(1920x1080分辨率,密码1111),AutoJS 3.版本(地址 http://shouji.baidu.com/software/23334313.html)Android版本7.0以上,Mi UI 9
其实,个人觉得完成这个事情就是在模仿我们手动的收能量,步骤如下:
1.解锁(点亮屏幕,切换到输入密码界面,输入密码)
2.打开支付宝
3.收取自己的能量
4.偷取他人能量
以下是代码:.
var myEnergeType=["线下支付","行走","共享单车","地铁购票","网络购票","网购火车票","生活缴费","ETC缴费","电子发票","绿色办公","咸鱼交易","预约挂号"];
var morningTime="07:20";//自己运动能量生成时间
unlock();
sleep(1000);
mainEntrence();
//解锁
function unlock(){
if(!device.isScreenOn()){
//点亮屏幕
device.wakeUp();
sleep(1000);
//滑动屏幕到输入密码界面
swipe(500, 1900, 500, 1000, 1000);
sleep(1000);
//输入四次 1 (密码为1111) 数字键1的像素坐标为(200,1000)
click(200,1000);
sleep(500);
click(200,1000);
sleep(500);
click(200,1000);
sleep(500);
click(200,1000);
sleep(500);
}
}
function tLog(msg) {
toast(msg);
console.log(msg)
}
/**
* 获取权限和设置参数
*/
function prepareThings(){
setScreenMetrics(1080, 1920);
//请求截图
if(!requestScreenCapture()){
tLog("请求截图失败");
exit();
}
}
/**
* 设置按键监听 当脚本执行时候按音量减 退出脚本
*/
function registEvent() {
//启用按键监听
events.observeKey();
//监听音量上键按下
events.onKeyDown("volume_down", function(event){
tLog("脚本手动退出");
exit();
});
}
/**
* 获取截图
*/
function getCaptureImg(){
var img0 = captureScreen();
if(img0==null || typeof(img0)=="undifined"){
tLog("截图失败,退出脚本");
exit();
}else{
return img0;
}
}
/**
* 默认程序出错提示操作
*/
function defaultException() {
tLog("程序当前所处状态不合预期,脚本退出");
exit();
}
/**
* 等待加载收集能量页面,采用未找到指定组件阻塞的方式,等待页面加载完成
*/
function waitPage(type){
// 等待进入自己的能量主页
if(type==0){
desc("消息").findOne();
}
// 等待进入他人的能量主页
else if(type==1){
desc("浇水").findOne();
}
//再次容错处理
sleep(3000);
}
/**
* 从支付宝主页进入蚂蚁森林我的主页
*/
function enterMyMainPage(){
launchApp("支付宝");
tLog("等待支付宝启动");
sleep(2000)
click("蚂蚁森");
//等待进入自己的主页
waitPage(0);
}
/**
* 进入排行榜
*/
function enterRank(){
tLog("进入排行榜");
//滑动到最低端
swipe(520,1860,520,100,1000);
swipe(520,1860,520,100,1000);
swipe(520,1860,520,100,1000);
clickByDesc("查看更多好友",0,true,"程序未找到排行榜入口,脚本退出");
//等待排行榜主页出现
sleep(1000)
}
/**
* 从排行榜获取可收集好有的点击位置
* @returns {*}
*/
function getHasEnergyfriend(type) {
var img = getCaptureImg();
var p=null;
if(type==1){
//img 是图片
//"#30bf6c" 第一个颜色
//[0, 33, "#30bf6c"] 第二颜色和它的相对坐标
//[34,45, "#ffffff"] 第三个颜色和他的相对坐标
//region: [1030, 100, 1, 1700] 第一个颜色的检测区域1030,100为起始坐标,1,1700为区域宽度!!!
p = images.findMultiColors(img, "#30bf6c",[[60, 0, "#30bf6c"], [46,45, "#ffffff"]], {
region: [1018, 100, 1, 1700]
});
}
if(p!=null){
return p;
}else {
return null;
}
}
/**
* 判断是否好有排行榜已经结束
* @returns {boolean}
*/
function isRankEnd() {
if(descEndsWith("没有更多了").exists()){
var b=descEndsWith("没有更多了").findOne();
var bs=b.bounds();
if(bs.centerY()<1920){
return true;
}
}
return false;
}
/**
* 在排行榜页面,循环查找可收集好友
* @returns {boolean}
*/
function enterOthers(){
tLog("开始检查排行榜");
var i=1;
var ePoint=getHasEnergyfriend(1);
//确保当前操作是在排行榜界面
while(ePoint==null && textEndsWith("好友排行榜").exists()){
swipe(520,1800,520,300,1000);
sleep(3000);
ePoint=getHasEnergyfriend(1);
i++;
//检测是否排行榜结束了
if(isRankEnd()){
return false;
}
//如果连续32次都未检测到可收集好友,无论如何停止查找(由于程序控制了在排行榜界面,且判断了结束标记,基本已经不存在这种情况了)
else if(i>32){
tLog("程序可能出错,连续"+i+"次未检测到可收集好友");
exit();
}
}
if(ePoint!=null){
//点击位置相对找图后的修正
tLog(ePoint.x,ePoint.y);
click(ePoint.x,ePoint.y+20);
waitPage(1);
clickByDesc("可收取",80);
//进去收集完后,递归调用enterOthers
back();
sleep(2000);
var j=0;
//等待返回好有排行榜
if(!textEndsWith("好友排行榜").exists() && j<=5){
sleep(2000);
j++;
}
if(j>=5){
defaultException();
}
enterOthers();
}else{
defaultException();
}
}
/**
* 根据描述值 点击
* @param energyType
* @param noFindExit
*/
function clickByDesc(energyType,paddingY,noFindExit,exceptionMsg){
if(descEndsWith(energyType).exists()){
descEndsWith(energyType).find().forEach(function(pos){
var posb=pos.bounds();
click(posb.centerX(),posb.centerY()-paddingY);
sleep(2000);
});
}else{
if(noFindExit!=null && noFindExit){
if(exceptionMsg !=null){
tLog(exceptionMsg);
exit();
}else{
defaultException();
}
}
}
}
/**
* 根据text值 点击 * @param energyType * @param noFindExit
*/
function clickByText(energyType,noFindExit,exceptionMsg){
if(textEndsWith(energyType).exists()){
textEndsWith(energyType).find().forEach(function(pos){
var posb=pos.bounds();
click(posb.centerX(),posb.centerY()-60);
});
}else{
if(noFindExit!=null && noFindExit){
if(exceptionMsg !=null){
tLog(exceptionMsg);
exit();
}else{
defaultException();
}
}
}
}
/**
* 遍历能量类型,收集自己的能量
*/
function collectionMyEnergy(){
var energyRegex=generateCollectionType();
var checkInMorning=false;
//如果是早上7点20分左右的话.等待主页能量出现 每隔一秒检测一次
while(isMorningTime() && descEndsWith("行走").exists()){
if (!checkInMorning){
tLog("等待运动能量生成中...");
checkInMorning=true;
}
descEndsWith("行走").find().forEach(function(pos){
var posb=pos.bounds();
click(posb.centerX(),posb.centerY()-80);
sleep(1500);
});
}
if(checkInMorning){
tLog("运动能量收集完成");
}
if(descMatches(energyRegex).exists()){
if(!checkInMorning){
tLog("防止小树的提示遮挡,等待中");
sleep(3000);
}
//这里存在一定的问题:如果sleep时间短的话,就会出现循环代码在运行,循环之后的代码也在运行,感觉出现了异步,具体原因不明
descMatches(energyRegex).find().forEach(function(pos){
var posb=pos.bounds();
//tLog( posb.centerX());
click(posb.centerX(),posb.centerY()-100);
sleep(3000);
});
}
tLog("自己能量收集完成");
sleep(1000);
}
/**
* 结束后返回主页面
*/
function whenComplete() {
tLog("结束");
back();
sleep(1500);
back();
exit();
}
/**
* 根据能量类型数组生成我的能量类型正则查找字符串
* @returns {string}
*/
function generateCollectionType() {
var regex="/";
myEnergeType.forEach(function (t,num) {
if(num==0){
regex+="(\\s*"+t+"$)";
}else{
regex+="|(\\s*"+t+"$)";
}
});
regex+="/";
return regex;
}
function isMorningTime() {
var now =new Date();
var hour=now.getHours();
var minu=now.getMinutes();
var targetTime=morningTime.split(":");
if(Number(targetTime[0])==hour && Math.abs(Number(targetTime[1])-minu)<=2){
return true;
}else{
return false;
}
}
//程序主入口
function mainEntrence(){
//前置操作
prepareThings();
//注册音量下按下退出脚本监听
registEvent();
//从主页进入蚂蚁森林主页
enterMyMainPage();
//收集自己的能量
collectionMyEnergy();
//进入排行榜
enterRank();
//在排行榜检测是否有好有的能量可以收集
enterOthers();
//结束后返回主页面
whenComplete();
}
比较麻烦的一个地方:偷能量的时候怎么分辨哪些人的能量可以偷,方法是截图分析图片识别。这里用的是:
p = images.findMultiColors(img, "#30bf6c",[[0, 33, "#30bf6c"], [34,45, "#ffffff"]], {
region: [1030, 100, 1, 1700]
});
这个函数的注释在代码里有就不多说了。主要是区别手型,倒计时数字,和邀请按钮:
它们的共同点是都有绿色的背景,区别是手型的白色区域比数字的高,而邀请按钮的右边绿色背景没有到手机的边缘,利用这个差别,我们就可以分辨出来。我的做法是用了三个点(如下图,红色的三个点),第一个为绿色,第二个在第一个的右边并且颜色相同,第三个在第一个右下方为白色。第一个点的横坐标为1018,第二个点在第一个点的[60,0]方向,第三个在第一个的[46,45]位置,这就是为什么第一点的取点区域为[1018, 100, 1, 1700],这样就可以保证取到的第一个点一定是左上角的绿点。
最后代码中有个比较奇怪的问题,就是下面这个循环遍历,有兴趣可以实验下,把sleep的时间缩短到一秒,就会发现收了第一能量后就开始下拉准备偷能量了,求大神解决。
descMatches(energyRegex).find().forEach(function(pos){
var posb=pos.bounds();
//tLog( posb.centerX());
click(posb.centerX(),posb.centerY()-80);
sleep(3000);
});
上一篇: golang unsafe 和 uintptr 指针
下一篇: 在Vue中实现打字机的效果