好友
阅读权限 10
听众
最后登录 1970-1-1
本帖最后由 spawn_fly 于 2021-4-15 11:31 编辑
拼多多在“多多果园”里上线了“多多斗地主”游戏,找了一圈也没找到能用的记牌器,索性用Autojs自己写了一个。
测试环境是MIUI11,安卓9,分辨率为1920x1080,Autojs4.1.1
思路就是将截图灰度并阈值化处理,然后找图(每次找图输出的时机是轮到本方出牌时)
使用过程中的几张截图,见下(最上面的记牌器是拼多多需使用道具购买的记牌器,下方的是我的记牌器,我的记牌器没记录大小王,因为灰度处理截图后大小王是一样的,而且这两张牌也没多大必要记录,一般人都能记得住 )
2021年4月15日更新:
不少人不知道怎么用,因为没有适配不同分辨率,所以不是1920x1080的,需要自行修改。
将找图文件(见附件)放入/sdcard/360/文件夹下。
特意做了个说明图(见下),看看这个脚本的获取区域是怎样的。
添加了打开拼多多的代码。
每次启动记牌器的时机是等叫地主环节结束后,一局游戏结束后,停止记牌器(按音量键),新游戏开始时再运行一次即可。
为了方便多次运行记牌器,在Autojs的“示例代码”文件夹下有个叫“悬浮窗”的文件夹,在里面有个“悬浮运行脚本按钮”的脚本,编辑它,将第一行的路径设置为记牌器脚本的完整路径,保存,运行“悬浮运行脚本按钮”。这时在手机左上角会有个“开始运行”按钮,通过这个按钮就能启动和停止记牌器了。为了方便大家操作,我也将这个“悬浮运行脚本按钮”的脚本发到最下面。
---------------------------------------------更新分隔线---------------------------------------------
[JavaScript] 纯文本查看 复制代码
//请求截图
if(!requestScreenCapture()){
toast("请求截图失败");
exit();
}
//测试环境:MIUI11,安卓9,分辨率为1920x1080,Autojs4.1.1
//找图思路:截图→灰度自适应阈值化处理→找图→每当本方回合→输出已出牌到记牌器
//使用前准备:将所有牌的灰度自适应阀值化处理后的小图存到basePath下
//使用方法:游戏开始时,点悬浮窗的“开始运行”即可。
var basePath = "/sdcard/360/"; //找图文件所在路径
var cardList = [2,"A","K","Q","J",10,9,8,7,6,5,4,3]; //显示在记牌器中的牌组(不含大小王)
var numList = [2,1,13,12,11,10,9,8,7,6,5,4,3]; //找图用,牌组文件名(不含扩展名)
var numCount = [4,4,4,4,4,4,4,4,4,4,4,4,4]; //初始时各牌的最大数量
var curCount = []; //已出牌的数组
var switchMode = 0; //记录上一次已出牌的数组,为了防止重复匹配
var myTurn = 0; //判断是否为本方回合
var window;
main();
//主函数
function main() {
launchApp("拼多多");
sleep(2000);
initCard(); //检索本方手牌
initWindow(); //初始化记牌器
checkCard(); //循环检索打出的牌
}
//初始化记牌器
function initWindow() {
window = floaty.window(
<frame gravity="center" bg="#f4f5f6">
<text id="card" textSize="14sp" textColor="#62220f" padding="13 4 0 0"/>
<text id="num" textSize="14sp" textColor="#ca3331" padding="13 5 0 3"/>
</frame>
);
window.exitOnClose();
window.setSize(880, 185); //记牌器的尺寸
window.setPosition(135, 145); //记牌器的位置
window.num.click(()=>{
window.setAdjustEnabled(!window.isAdjustEnabled());
});
//将本方手牌输出到记牌器
ui.run(function(){
window.card.setText(cardList.join(' '));
window.num.setText("\n"+curCount.join(" "));
});
}
// 循环检索打出的牌并输出到记牌器
function checkCard() {
setInterval(()=>{
switchMode = myTurn;
myTurn = isMyTurn();
// print("myTurn:"+myTurn);
// print("switchMode:"+switchMode);
if (myTurn == 1 && switchMode!=myTurn) {
// print("又轮到我了!!");
sleep(500); //炸弹、飞机、连对时有特效,延迟一会等特效消失才能更好的判断是否为本方回合
ui.run(function(){
window.card.setText(cardList.join(' ')); //输出本方手牌到记牌器
window.num.setText(dynamicNum()); //输出打出的牌到记牌器
});
}
}, 1000);
}
//检索打出的牌
function dynamicNum() {
getCard();
str = "\n"+curCount.join(" ");
return str;
}
//检索全部牌,返回检索到的手牌数组(按numList数组排序)
//参数mode默认为检索打出的牌,当为'own'时则表示检索本方手牌
//TODO 先判断已出牌的数量,再进行检索
function findAllNum(mode) {
var img = captureScreen();
var g = images.grayscale(img);
var bgImg = images.adaptiveThreshold(g, 200, "MEAN_C", "BINARY", 25, 10);
var mybg = "/sdcard/360/mybg.png";
images.saveImage(bgImg, mybg);
var tempArr = [];
img = images.read(mybg);
for (var nl=0;nl<13;nl++) {
var curTotal = 0;//计数
if (mode == 'own') {
var curDes = basePath + numList[nl] + ".png";
var mydes = images.read(curDes);
var point = images.matchTemplate(img, mydes,{region:[20,1215,1030,400],threshold:0.9,max:4, level:1}); // 本方的手牌
if (point!=null) {
curTotal = curTotal + point.matches.length;
}
} else {
var curDes = basePath + numList[nl] + "s.png";
var mydes = images.read(curDes);
var point = images.matchTemplate(img, mydes,{region:[0,592,1030,563],threshold:0.8,max:4, level:1}); // 出牌的部分
if (point!=null) {
curTotal = curTotal + point.matches.length;
}
}
mydes.recycle();
tempArr.push(curTotal);
}
img.recycle();
return tempArr;
}
// 初始化牌(即将自己的手牌排除在剩余牌组外)
function initCard() {
own = findAllNum('own');
// print("own :"+own.join(","))
curCount = makeDiffArr(numCount, own);
print("curCoun:"+curCount.join(","));
curCount[3] = " "+ curCount[3]; //细调位置
curCount[5] = " "+ curCount[5]; //细调位置
}
// 获取出牌时的牌,并计算剩余牌组
function getCard() {
other = findAllNum('other');
print("other :"+other.join(","))
var re = 0;
while (sum(other) == 0) {
if (re > 4) {
break;
}
other = findAllNum('other');
re++;
}
curCount = makeDiffArr(curCount, other);
print("curCoun:"+curCount.join(","));
curCount[3] = " "+ curCount[3]; //细调位置
curCount[5] = " "+ curCount[5]; //细调位置
}
//计算数组内所有数值相加后的结果
function sum(arr) {
return eval(arr.join("+"));
}
// 看看是不是已经到了我的回合,通过判断小闹钟的上左右 3 个坐标是否是二进制灰度后的黑色来进行的
function isMyTurn() {
var n = 0;
var img = captureScreen();
var g = images.grayscale(img);
var adaptiveImg = images.adaptiveThreshold(g, 200, "MEAN_C", "BINARY", 25, 10);
var myTurnBg = "/sdcard/360/myturnbg.png";
images.saveImage(adaptiveImg, myTurnBg);
adaImg = images.read(myTurnBg);
if (adaImg != null) {
if(images.detectsColor(adaImg, "#000000", 675, 1186)){ //本方能出得起牌时的小闹钟颜色和坐标(通过这个来判断的)
n++;
}
if(images.detectsColor(adaImg, "#000000", 404, 1187)){ //本方出不起牌时的小闹钟颜色和坐标
n++;
}
if (n >= 1) {
print("轮到我了!");
adaImg.recycle();
return 1;
}
}
adaImg.recycle();
return 0;
}
// 返回两个数组的差所能成的新数组
function makeDiffArr(arr1, arr2) {
var tempArr = [];
for (var i=0;i<arr1.length;i++) {
var t = arr1[i]-arr2[i];
if (t<0) t = 0;
tempArr.push(t);
}
return tempArr;
}
** 以上文件可以命名为 jpq **
[JavaScript] 纯文本查看 复制代码
var path = "/sdcard/脚本/jqp.js";
if(!files.exists(path)){
toast("脚本文件不存在: " + path);
exit();
}
var window = floaty.window(
<frame>
<button id="action" text="开始运行" w="90" h="40" bg="#77ffffff"/>
</frame>
);
setInterval(()=>{}, 1000);
var execution = null;
//记录按键被按下时的触摸坐标
var x = 0, y = 0;
//记录按键被按下时的悬浮窗位置
var windowX, windowY;
//记录按键被按下的时间以便判断长按等动作
var downTime;
window.action.setOnTouchListener(function(view, event){
switch(event.getAction()){
case event.ACTION_DOWN:
x = event.getRawX();
y = event.getRawY();
windowX = window.getX();
windowY = window.getY();
downTime = new Date().getTime();
return true;
case event.ACTION_MOVE:
//移动手指时调整悬浮窗位置
window.setPosition(windowX + (event.getRawX() - x),
windowY + (event.getRawY() - y));
//如果按下的时间超过1.5秒判断为长按,退出脚本
if(new Date().getTime() - downTime > 1500){
exit();
}
return true;
case event.ACTION_UP:
//手指弹起时如果偏移很小则判断为点击
if(Math.abs(event.getRawY() - y) < 5 && Math.abs(event.getRawX() - x) < 5){
onClick();
}
return true;
}
return true;
});
function onClick(){
if(window.action.getText() == '开始运行'){
execution = engines.execScriptFile(path);
window.action.setText('停止运行');
}else{
if(execution){
execution.getEngine().forceStop();
}
window.action.setText('开始运行');
}
}
**以上为悬浮运行脚本按钮的脚本,第一行就是记牌器脚本的路径,改成你手机上记牌器的路径后,保存,运行
免费评分
查看全部评分