From fa2e36b1cc6f6ec533597ed3ba72faf0047825e0 Mon Sep 17 00:00:00 2001 From: yan Date: Fri, 27 Feb 2026 19:08:22 +0800 Subject: [PATCH] =?UTF-8?q?feat(AutoPlan):=20=E6=9B=B4=E6=96=B0=E7=A7=98?= =?UTF-8?q?=E5=A2=83=E9=80=80=E5=87=BA=E6=A3=80=E6=B5=8B=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 isInOutDomainUI 函数改为异步函数,使用 OCR 文本识别替代模板匹配 - 添加 findText 函数用于在指定区域内查找文本内容,支持多次尝试和重试机制 - 修改 outDomainUI 函数逻辑,优化退出秘境流程和错误处理 - 增加最大尝试次数限制,避免无限循环等待 - 添加详细的 JSDoc 注释文档说明 findText 函数参数和返回值 --- repo/js/AutoPlan/utils/tool.js | 125 +++++++++++++++++++++++++-------- 1 file changed, 97 insertions(+), 28 deletions(-) diff --git a/repo/js/AutoPlan/utils/tool.js b/repo/js/AutoPlan/utils/tool.js index 4744184a5..01125a9a8 100644 --- a/repo/js/AutoPlan/utils/tool.js +++ b/repo/js/AutoPlan/utils/tool.js @@ -135,56 +135,125 @@ async function toMainUi() { } -const isInOutDomainUI = () => { - // let name = '主界面' - let main_ui = getJsonPath('out_domain'); - // 定义识别对象 - let paimonMenuRo = RecognitionObject.TemplateMatch( - file.ReadImageMatSync(`${main_ui.path}${main_ui.name}${main_ui.type}`), - 0, - 0, - genshinJson.width / 3.0, - genshinJson.width / 5.0 - ); - let captureRegion = captureGameRegion(); - try { - let res = captureRegion.find(paimonMenuRo); - return !res.isEmpty(); - }finally { - captureRegion.Dispose() +const isInOutDomainUI = async () => { + // // let name = '主界面' + // let main_ui = getJsonPath('out_domain'); + // // 定义识别对象 + // let paimonMenuRo = RecognitionObject.TemplateMatch( + // file.ReadImageMatSync(`${main_ui.path}${main_ui.name}${main_ui.type}`), + // 0, + // 0, + // genshinJson.width / 3.0, + // genshinJson.width / 5.0 + // ); + // let captureRegion = captureGameRegion(); + // try { + // let res = captureRegion.find(paimonMenuRo); + // return !res.isEmpty(); + // }finally { + // captureRegion.Dispose() + // } + //509, 259, 901, 563 + const text = "退出秘境"; + const ocrRegion = { + x: 509, + y: 259, + w: 901, + h: 563 } + const find = await findText(text, ocrRegion.x, ocrRegion.y, ocrRegion.w, ocrRegion.h) + log.info("识别结果:{1}", find) + return find && find.includes(text) }; async function outDomainUI() { + const ocrRegion={ + x: 509, + y: 259, + w: 901, + h: 563 + } let ms = 300 let index = 1 + let tryMax=false await sleep(ms); - while (!isInOutDomainUI()) { + //点击确认按钮 + await findTextAndClick('地脉异常') + await sleep(ms); + while (!await isInOutDomainUI()) { await sleep(ms); await keyPress("ESCAPE"); - await sleep(ms); + await sleep(ms*2); if (isInMainUI()){ break - } else if (isInOutDomainUI()) { - try { - //点击确认按钮 - await findTextAndClick('确认') - }catch (e) { - // log.error(`多次尝试点击确认失败 假定已经退出处理`); - } - } if (index > 3) { log.error(`多次尝试匹配退出秘境界面失败 假定已经退出处理`); + tryMax=true break } index += 1 } - + if ((!tryMax)&&await isInOutDomainUI()) { + try { + //点击确认按钮 + await findTextAndClick('确认',ocrRegion.x, ocrRegion.y, ocrRegion.w, ocrRegion.h) + }catch (e) { + // log.error(`多次尝试点击确认失败 假定已经退出处理`); + } + } } +/** + * 在指定区域内查找文本内容 + * @param {string} text - 要查找的文本内容 + * @param {number} x - 查找区域的左上角x坐标,默认为0 + * @param {number} y - 查找区域的左上角y坐标,默认为0 + * @param {number} w - 查找区域的宽度,默认为1920 + * @param {number} h - 查找区域的高度,默认为1080 + * @param {number} attempts - 尝试查找的次数,默认为5 + * @param {number} interval - 每次尝试之间的间隔时间(毫秒),默认为50 + * @returns {Promise} 返回找到的文本内容,如果未找到则返回空字符串 + */ +async function findText( + text, + x = 0, + y = 0, + w = 1920, + h = 1080, + attempts = 5, + interval = 50, +) { + const keyword = text.toLowerCase(); // 将搜索关键字转换为小写,实现不区分大小写的搜索 + for (let i = 0; i < attempts; i++) { // 循环尝试查找文本,最多尝试attempts次 + const gameRegion = captureGameRegion(); // 捕获游戏区域图像 + try { + const ro = RecognitionObject.Ocr(x, y, w, h); // 创建OCR识别对象,指定识别区域 + const results = gameRegion.findMulti(ro); // 在区域内查找所有匹配的文本 + + // 遍历查找结果 + for (let j = 0; j < results.count; j++) { + const res = results[j]; + // 检查结果是否存在、包含文本内容,并且文本包含搜索关键字 + if ( + res.isExist() && + res.text && + res.text.toLowerCase().includes(keyword) + ) { + return res.text; // 找到匹配文本,直接返回 + } + } + } finally { + gameRegion.dispose(); // 确保释放游戏区域资源 + } + + await sleep(interval); // 等待指定的时间后进行下一次尝试 + } + + return ""; // 未找到匹配文本,返回空字符串 +} /** * 通用找文本并点击(OCR) * @param {string|string[]} text 目标文本(单个文本或文本列表,列表时需全部匹配)