diff --git a/resource/battle/test.json b/resource/battle/test.json index c7e968d0c3..9cb5478ed2 100644 --- a/resource/battle/test.json +++ b/resource/battle/test.json @@ -14,7 +14,7 @@ "name": "嵯峨" }, { - "name": "橙闪" + "name": "澄闪" }, { "name": "临光" @@ -25,30 +25,30 @@ "name": "嵯峨", "location": [ 8, - 5 + 4 ], "direction": 2 }, { "name": "能天使", "location": [ - 9, + 8, 5 ], "direction": 2 }, { - "name": "橙闪", + "name": "澄闪", "location": [ 7, - 4 + 3 ], - "direction": 2 + "direction": 1 }, { "name": "临光", "location": [ - 8, + 7, 4 ], "direction": 2 diff --git a/resource/tasks.json b/resource/tasks.json index 612cf47f4a..82189f8487 100644 --- a/resource/tasks.json +++ b/resource/tasks.json @@ -3285,6 +3285,10 @@ 60 ] }, + "BattleAvatarData": { + "template": "empty.png", + "templThreshold": 0.8 + }, "BattleKillsFlag": { "roi": [ 150, @@ -4023,6 +4027,10 @@ [ "^1$", "山" + ], + [ + "姜哦", + "嵯峨" ] ], "roi": [ diff --git a/src/MeoAssistant/AsstBattleDef.h b/src/MeoAssistant/AsstBattleDef.h index c9dbbc3bf6..32fec01989 100644 --- a/src/MeoAssistant/AsstBattleDef.h +++ b/src/MeoAssistant/AsstBattleDef.h @@ -83,5 +83,6 @@ namespace asst Rect rect; cv::Mat avatar; std::string name; + size_t index; }; } diff --git a/src/MeoAssistant/BattleImageAnalyzer.cpp b/src/MeoAssistant/BattleImageAnalyzer.cpp index 2421e439e3..4cd35e089c 100644 --- a/src/MeoAssistant/BattleImageAnalyzer.cpp +++ b/src/MeoAssistant/BattleImageAnalyzer.cpp @@ -86,6 +86,7 @@ bool asst::BattleImageAnalyzer::opers_analyze() const auto cost_move = Task.get("BattleOperCostRange")->rect_move; const auto avlb_move = Task.get("BattleOperAvailable")->rect_move; + size_t index = 0; for (const MatchRect& flag_mrect : flags_analyzer.get_result()) { BattleRealTimeOper oper; oper.rect = flag_mrect.rect.move(click_move); @@ -108,6 +109,7 @@ bool asst::BattleImageAnalyzer::opers_analyze() Rect cost_rect = flag_mrect.rect.move(cost_move); oper.cost = oper_cost_analyze(cost_rect); + oper.index = index++; m_opers.emplace_back(std::move(oper)); } diff --git a/src/MeoAssistant/BattleProcessTask.cpp b/src/MeoAssistant/BattleProcessTask.cpp index 1155d864a1..2355e06dc7 100644 --- a/src/MeoAssistant/BattleProcessTask.cpp +++ b/src/MeoAssistant/BattleProcessTask.cpp @@ -7,6 +7,7 @@ #include "ProcessTask.h" +#include "MatchImageAnalyzer.h" #include "OcrImageAnalyzer.h" #include "BattleImageAnalyzer.h" @@ -91,7 +92,7 @@ bool asst::BattleProcessTask::analyze_opers_preview() } opers.at(i).name = oper_name; - m_cur_opers_info.emplace(std::move(oper_name), std::move(opers.at(i))); + m_opers_info.emplace(std::move(oper_name), std::move(opers.at(i))); // 干员特别多的时候,任意干员被点开,都会导致下方的干员图标被裁剪和移动。所以这里需要重新识别一下 analyzer.set_image(image); @@ -103,17 +104,87 @@ bool asst::BattleProcessTask::analyze_opers_preview() return true; } +bool asst::BattleProcessTask::update_opers_info() +{ + BattleImageAnalyzer analyzer(m_ctrler->get_image()); + analyzer.set_target(BattleImageAnalyzer::Target::Oper); + if (!analyzer.analyze()) { + return false; + } + const auto& cur_opers_info = analyzer.get_opers(); + // 干员数量没有变化,无需更新 + if (cur_opers_info.size() == m_opers_info.size()) { + return true; + } + decltype(m_opers_info) pre_opers_info; + m_opers_info.swap(pre_opers_info); + + const int size_change = static_cast(cur_opers_info.size()) - static_cast(pre_opers_info.size()); + const bool is_increased = size_change > 0; + for (const auto& cur_oper : cur_opers_info) { + int left_index = 0; + int right_index = 0; + // 干员数变多了,干员可能位于 [之前的位置, 之前的位置 + |size_change|] 之间 + if (is_increased) { + left_index = static_cast(cur_oper.index); + right_index = static_cast(cur_oper.index) + size_change; + } + // 干员数减少了,干员可能位于 [之前的位置 - |size_change|, 之前的位置] 之间 + else { + left_index = static_cast(cur_oper.index); + right_index = static_cast(cur_oper.index) - size_change; // size_change 是 负值 + } + + std::vector ranged_iters; + // 找出该干员可能对应的之前的谁 + for (auto iter = pre_opers_info.cbegin(); iter != pre_opers_info.cend(); ++iter) { + int pre_index = static_cast(iter->second.index); + if (left_index <= pre_index && pre_index <= right_index) { + ranged_iters.emplace_back(iter); + } + } + MatchImageAnalyzer avatar_analyzer(cur_oper.avatar); + avatar_analyzer.set_task_info("BattleAvatarData"); + decltype(ranged_iters)::value_type matched_iter; + MatchRect matched_result; + + // 遍历比较,得分最高的那个就说明是对应的那个 + for (const auto& iter : ranged_iters) { + avatar_analyzer.set_templ(iter->second.avatar); + if (!avatar_analyzer.analyze()) { + continue; + } + if (matched_result.score < avatar_analyzer.get_result().score) { + matched_result = avatar_analyzer.get_result(); + matched_iter = iter; + } + } + if (matched_result.score == 0) { + continue; + } + auto temp_oper = cur_oper; + temp_oper.name = matched_iter->first; + // 保存当前干员信息 + m_opers_info.emplace(matched_iter->first, std::move(temp_oper)); + } + return true; +} + bool asst::BattleProcessTask::do_action(const BattleAction& action) { if (!wait_condition(action)) { return false; } + while (!update_opers_info()) { + ; + } + const auto use_oper_task_ptr = Task.get("BattleUseOper"); const auto swipe_oper_task_ptr = Task.get("BattleSwipeOper"); // TODO,临时调试方案。正式版本这里需要对 group_name -> oper_name 做一个转换 - auto iter = m_cur_opers_info.find(action.group_name); - if (iter == m_cur_opers_info.cend()) { + auto iter = m_opers_info.find(action.group_name); + if (iter == m_opers_info.cend()) { Log.error("battle opers group", action.group_name, "not found"); return false; } @@ -126,7 +197,7 @@ bool asst::BattleProcessTask::do_action(const BattleAction& action) // 拖动到场上 Point placed_point = m_side_tile_info[action.location].pos; Rect placed_rect{ placed_point.x ,placed_point.y, 1, 1 }; - m_ctrler->swipe(oper_rect, placed_rect); + m_ctrler->swipe(oper_rect, placed_rect, swipe_oper_task_ptr->pre_delay); sleep(use_oper_task_ptr->rear_delay); @@ -155,6 +226,7 @@ bool asst::BattleProcessTask::do_action(const BattleAction& action) m_ctrler->swipe(placed_point, end_point, swipe_oper_task_ptr->rear_delay); } + sleep(use_oper_task_ptr->pre_delay); return true; } diff --git a/src/MeoAssistant/BattleProcessTask.h b/src/MeoAssistant/BattleProcessTask.h index 356fd033e3..e509eeb57b 100644 --- a/src/MeoAssistant/BattleProcessTask.h +++ b/src/MeoAssistant/BattleProcessTask.h @@ -23,6 +23,7 @@ namespace asst bool battle_pause(); bool cancel_selection(); // 取消选择干员 bool analyze_opers_preview(); + bool update_opers_info(); bool do_action(const BattleAction& action); bool wait_condition(const BattleAction& action); @@ -33,6 +34,6 @@ namespace asst std::unordered_map m_normal_tile_info; BattleActionsGroup m_actions; - std::unordered_map m_cur_opers_info; + std::unordered_map m_opers_info; }; } diff --git a/src/MeoAssistant/MatchImageAnalyzer.cpp b/src/MeoAssistant/MatchImageAnalyzer.cpp index 00917c1ebf..960eca8e0b 100644 --- a/src/MeoAssistant/MatchImageAnalyzer.cpp +++ b/src/MeoAssistant/MatchImageAnalyzer.cpp @@ -14,7 +14,7 @@ asst::MatchImageAnalyzer::MatchImageAnalyzer(const cv::Mat image, const Rect& ro bool asst::MatchImageAnalyzer::analyze() { - const cv::Mat templ = Resrc.templ().get_templ(m_templ_name); + const cv::Mat templ = m_templ_name.empty() ? m_templ : Resrc.templ().get_templ(m_templ_name); if (templ.empty()) { Log.error("templ is empty!"); return false; @@ -40,6 +40,13 @@ void asst::MatchImageAnalyzer::set_mask_range(std::pair mask_range) no void asst::MatchImageAnalyzer::set_templ_name(std::string templ_name) noexcept { m_templ_name = std::move(templ_name); + m_templ = cv::Mat(); +} + +void asst::MatchImageAnalyzer::set_templ(cv::Mat templ) noexcept +{ + m_templ = std::move(templ); + m_templ_name.clear(); } void asst::MatchImageAnalyzer::set_threshold(double templ_thres) noexcept diff --git a/src/MeoAssistant/MatchImageAnalyzer.h b/src/MeoAssistant/MatchImageAnalyzer.h index f057d1bb56..324b6a28ea 100644 --- a/src/MeoAssistant/MatchImageAnalyzer.h +++ b/src/MeoAssistant/MatchImageAnalyzer.h @@ -16,6 +16,7 @@ namespace asst void set_mask_range(int lower, int upper) noexcept; void set_mask_range(std::pair mask_range) noexcept; void set_templ_name(std::string templ_name) noexcept; + void set_templ(cv::Mat templ) noexcept; void set_threshold(double templ_thres) noexcept; void set_task_info(std::shared_ptr task_ptr); void set_task_info(const std::string& task_name); @@ -28,6 +29,7 @@ namespace asst void set_task_info(MatchTaskInfo task_info) noexcept; std::string m_templ_name; + cv::Mat m_templ; MatchRect m_result; double m_templ_thres = 0.0; bool m_use_cache = false;