From 7762aff95ae9ebf4b79489a09ec4fcb753bcfce2 Mon Sep 17 00:00:00 2001 From: 5117600049 <511760049@qq.com> Date: Sun, 22 Jun 2025 16:43:07 +0800 Subject: [PATCH] =?UTF-8?q?JS=E8=84=9A=E6=9C=AC=EF=BC=9A=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E9=A2=86=E5=8F=96=E6=88=90=E5=B0=B1=E5=A5=96=E5=8A=B1=E9=A2=86?= =?UTF-8?q?=E5=8F=96=E9=80=BB=E8=BE=91=E9=87=8D=E5=86=99=EF=BC=8C=E6=95=88?= =?UTF-8?q?=E7=8E=87=E8=87=B3=E5=A4=9A=E6=8F=90=E9=AB=988000%=20(#1164)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update manifest.json * Update main.js * Add files via upload --- .../自动领取成就奖励/assets/exclamation.png | Bin 0 -> 361 bytes repo/js/自动领取成就奖励/main.js | 243 ++++++++++++++---- repo/js/自动领取成就奖励/manifest.json | 2 +- 3 files changed, 190 insertions(+), 55 deletions(-) create mode 100644 repo/js/自动领取成就奖励/assets/exclamation.png diff --git a/repo/js/自动领取成就奖励/assets/exclamation.png b/repo/js/自动领取成就奖励/assets/exclamation.png new file mode 100644 index 0000000000000000000000000000000000000000..a846b4ebf946a3f1f7b25a9380698bdd6dc7ef29 GIT binary patch literal 361 zcmV-v0ha!WP)Px$BS}O-R5(wKlD|s>F&KuQG}nlWDEPOyI15fXIlC$y6rui_99)%xP@$*?;^t6v z6rFSvL2z*>B8WwhQUwROTrP4~yrcEfn)QA1=FRuLqB%8h>2unEZ!|BSLJWd`eXb(Y z4a=EH9wi?I=kyQNe#mv@d2_GS(=L8$^dbWB4QP={-Y7~MArE2n=}m5ok- zw=@TlC9KvVG!8h9k#~BE&~X-^sw*%&1lFR<``FeeIAMPy8(ZTQy?yMCk*r#D@|d$5 zO#Rvoi}6vs#aW_QFnf_0K#L 1 ? (bottomRight.x - topLeft.x) / (cols - 1) : 0; // 处理单列情况 - let stepY = rows > 1 ? (bottomRight.y - topLeft.y) / (rows - 1) : 0; // 处理单行情况 - // 从左到右,从上到下依次点击 - for (let row = 0; row < rows; row++) { - for (let col = 0; col < cols; col++) { - // 计算当前点的坐标并四舍五入 - let x = Math.round(topLeft.x + col * stepX); - let y = Math.round(topLeft.y + row * stepY); - // 执行点击 - click(x, y); - await sleep(1000); - log.info(`第${sum}次识别`); - sum++; - let receive = captureGameRegion().find(receiveRo); - await sleep(1000); - while(receive.isExist()){ - receive.click(); - await sleep(500); - sum1++; - log.info(`成功识别${sum1}次`); - - click(400,1010);//点击空白处 - await sleep(500); - receive = captureGameRegion().find(receiveRo); - } - click(400,1010);//如果是本行最后一个成就会自动翻页 - await sleep(500); - keyPress("ESCAPE"); - // 等待1秒 - await sleep(1000); +/** + * 检测指定区域的文字内容 + * @param {number} x - 区域的X坐标 + * @param {number} y - 区域的Y坐标 + * @param {number} width - 区域的宽度 + * @param {number} height - 区域的高度 + * @param {string|undefined} targetText - 需要匹配的目标文字(可选) + * @returns {Promise} - 返回检测到的文字或false + */ +async function detectTextInRegion(x, y, width, height, targetText) { + try { + // 获取游戏区域截图 + let captureRegion = captureGameRegion(); + + // 创建OCR识别对象,指定检测区域 + let ocrRo = RecognitionObject.Ocr(x, y, width, height); + + // 在指定区域内进行OCR识别 + let resList = captureRegion.findMulti(ocrRo); + + // 如果没有识别到任何结果,返回false + if (resList.count === 0) { + log.info("未检测到任何文字"); + return false; + } + + // 获取第一个识别结果 + let firstResult = resList[0]; + let detectedText = firstResult.text; + + // 如果没有传入目标文字,则只要检测到非空内容就算成功 + if (targetText === undefined) { + return detectedText.trim() !== "" ? detectedText : false; + } + + // 如果传入了目标文字,则进行匹配 + if (detectedText.includes(targetText)) { + log.info(`检测到目标文字:${targetText}`); + return detectedText; + } + + log.info(`检测到文字但不匹配:${detectedText} (目标:${targetText})`); + return false; + } catch (error) { + log.info("文字检测出错:", error); + return false; } - } +} +// 使用示例1:检测特定区域的文字是否为"确认" +/* + let result = await utils.detectTextInRegion(0, 0, 400, 400, "合成"); + if (result) { + log.info(`检测到目标文字:${result}`); + } else { + log.info("未检测到目标文字"); + } + +*/ + +// 使用示例2:只检测区域是否有文字(不指定目标文字) +// let result = await detectTextInRegion(100, 200, 300, 50); +// if (result) { +// log.info("检测到文字:", result); +// } else { +// log.info("未检测到任何文字"); +// } + +/** + * 等待图片出现并点击 + * @param {string} imageName 图片名称(不带.png后缀) + * @param {number} [x=0] 裁剪区域左上角X坐标 + * @param {number} [y=0] 裁剪区域左上角Y坐标 + * @param {number} [width=1920] 裁剪区域宽度 + * @param {number} [height=1080] 裁剪区域高度 + * @param {number} [timeout=10000] 超时时间(毫秒),默认1秒 + * @param {number} [checkInterval=500] 检查间隔(毫秒),默认500毫秒 + * @returns {Promise} + * @throws 如果超时未找到图片则抛出错误 + */ +// 使用示例: +// (1) 使用默认裁剪区域(0,0,1920,1080) +// await waitAndClickImage("paimon_menu"); +// +// (2) 自定义裁剪区域和超时时间 +// await waitAndClickImage("confirm_button", 100, 100, 800, 600, 500); +const waitAndClickImage = async ( + imageName, + x = 0, + y = 0, + width = 1920, + height = 1080, + timeout = 500, + checkInterval = 500 +) => { + const startTime = Date.now(); + const imagePath = `assets/${imageName}.png`; + + // 读取模板图片 + const templateMat = file.ReadImageMatSync(imagePath); + // 创建识别对象,使用默认阈值0.8 + const recognitionObj = RecognitionObject.TemplateMatch(templateMat, x, y, width, height); + + while (Date.now() - startTime < timeout) { + // 捕获游戏区域 + const captureRegion = captureGameRegion(); + // 查找图片 + const result = captureRegion.Find(recognitionObj); + + if (!result.isEmpty()) { + log.info(`找到图片 ${imageName},位置(${result.x}, ${result.y}),正在点击...`); + result.Click(); + await sleep(300); // 点击后稍作等待 + return; + } + + await sleep(checkInterval); + } + + throw new Error(`等待图片 ${imageName} 超时(${timeout}ms)`); +} +/** + * 滚动页面 + * @param {number} totalDistance - 总滚动距离 + * @param {number} [stepDistance=10] - 每次滚动的步长 + * @param {number} [delayMs=5] - 每次滚动后的延迟(毫秒) + * @returns {Promise} + */ +async function scrollPage(totalDistance, stepDistance = 10, delayMs = 5) { + moveMouseTo(400, 540); + await sleep(50); + leftButtonDown(); + + const steps = Math.ceil(Math.abs(totalDistance) / stepDistance); + const direction = Math.sign(totalDistance); + for (let j = 0; j < steps; j++) { + const remainingDistance = Math.abs(totalDistance) - j * stepDistance; + const moveDistance = remainingDistance < stepDistance ? remainingDistance : stepDistance; + moveMouseBy(0, -moveDistance * direction); // 注意这里的负号 + await sleep(delayMs); + } + + await sleep(700); + leftButtonUp(); + await sleep(100); } //主流程 + await genshin.returnMainUi(); await sleep(1000); keyPress("ESCAPE"); await sleep(1000); click(670 ,420 );//点击成就 await sleep(2000); -await autoClick(topLeft, bottomRight, rows, cols); -for (let i = 0; i < 6; i++) { -await autoClick(topLeft1, bottomRight1, rows1, cols1); +click(200, 300); // 进入详细界面 +await sleep(1500); +click(675, 990); // 点到底部 +await sleep(1000); +click(675, 990); // 点到底部 +await sleep(1000); +click(675, 990); // 点到底部 +await sleep(1000); +click(675, 990); // 点到底部 +await sleep(1000); +for (let j = 0; j < 500; j++) { + + try { + await waitAndClickImage("exclamation", 600, 50, 100, 1000, 500); + await sleep(1000); + + } catch (error) { + await sleep(100); + let result = await detectTextInRegion(110, 200, 150, 50, "天地"); + if (result) { + log.info(`检测到目标文字:${result}`); + await genshin.returnMainUi(); + break; + } else { + await sleep(100); + } + await scrollPage(-600); + await sleep(600); + continue; + } + + for (let i = 0; i < 1500; i++) { + try { + await waitAndClickImage("receive"); + await sleep(500); + click(870, 420); // 点击任意位置 + await sleep(800); + } catch (error) { + await sleep(500); + break; + } + } + } +log.info(`领取结束`); + })(); diff --git a/repo/js/自动领取成就奖励/manifest.json b/repo/js/自动领取成就奖励/manifest.json index 50fb993f..dcb19069 100644 --- a/repo/js/自动领取成就奖励/manifest.json +++ b/repo/js/自动领取成就奖励/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "自动领取成就奖励", - "version": "1.0", + "version": "1.2", "description": "所以米桑什么时候实装一键领取?", "tags" : [ "OCR" ], "authors": [