feat: 自动检测地图是否为多阶段地图, 判断是否需要使用 view[0].x 修正镜头 (#15371)

This commit is contained in:
Status102
2026-01-11 18:38:58 +08:00
committed by GitHub
parent efc4a57d74
commit eb85bf2f36
5 changed files with 37 additions and 10 deletions

View File

@@ -115,15 +115,15 @@ static constexpr double rel_pos_x = 1.3143386840820312;
static constexpr double rel_pos_y = 1.314337134361267;
static constexpr double rel_pos_z = -0.3967874050140381;
inline auto get_retreat_screen_pos(const Level& level)
inline auto get_retreat_screen_pos(const Level& level, bool has_multi_stages = false)
{
const vec3d relative_pos = { -rel_pos_x + level.view[0].x, +rel_pos_y, rel_pos_z };
const vec3d relative_pos = { -rel_pos_x + (has_multi_stages ? level.view[0].x : 0), +rel_pos_y, rel_pos_z };
return world_to_screen(level, relative_pos, true);
}
inline auto get_skill_screen_pos(const Level& level)
inline auto get_skill_screen_pos(const Level& level, bool has_multi_stages = false)
{
const vec3d relative_pos = { +rel_pos_x + level.view[0].x, -rel_pos_y, rel_pos_z };
const vec3d relative_pos = { +rel_pos_x + (has_multi_stages ? level.view[0].x : 0), -rel_pos_y, rel_pos_z };
return world_to_screen(level, relative_pos, true);
}

View File

@@ -105,14 +105,37 @@ asst::TilePack::result_type asst::TilePack::calc_(const Map::Level& level, doubl
const bool ret = proc_data(result.normal_tile_info, loc, screen_pos, tile);
const bool ret_side = proc_data(result.side_tile_info, loc, screen_pos_side, tile);
if (tile.tileKey == "tile_start" || tile.tileKey == "tile_end") {
// 检查 screen_pos 是否在允许的范围内带5%容差)
constexpr double MIN_X = 0.0;
constexpr double MAX_X = 1280.0;
constexpr double MIN_Y = 0.0;
constexpr double MAX_Y = 720.0;
constexpr double TOLERANCE = 0.05;
constexpr double x_tolerance = MAX_X * TOLERANCE;
constexpr double y_tolerance = MAX_Y * TOLERANCE;
constexpr double min_x_bound = MIN_X - x_tolerance;
constexpr double max_x_bound = MAX_X + x_tolerance;
constexpr double min_y_bound = MIN_Y - y_tolerance;
constexpr double max_y_bound = MAX_Y + y_tolerance;
if (screen_pos.x < min_x_bound || screen_pos.x > max_x_bound || screen_pos.y < min_y_bound ||
screen_pos.y > max_y_bound) {
LogInfo << "Tile" << tile.tileKey << "at" << loc << ", screen position:" << screen_pos
<< ", map has multi stages";
result.has_multi_stages = true;
}
}
if (!ret || !ret_side) {
Log.info("Tiles calc error!");
return {};
}
}
}
auto retreat = Map::TileCalc2::get_retreat_screen_pos(level);
auto skill = Map::TileCalc2::get_skill_screen_pos(level);
auto retreat = Map::TileCalc2::get_retreat_screen_pos(level, result.has_multi_stages);
auto skill = Map::TileCalc2::get_skill_screen_pos(level, result.has_multi_stages);
result.retreat_button = { retreat.x, retreat.y };
result.skill_button = { skill.x, skill.y };

View File

@@ -60,6 +60,7 @@ public:
std::unordered_map<Point, TileInfo> side_tile_info;
Point retreat_button;
Point skill_button;
bool has_multi_stages = false;
};
public:

View File

@@ -74,6 +74,7 @@ bool asst::BattleHelper::calc_tiles_info(const std::string& stage_name, double s
m_side_tile_info = std::move(calc_result.side_tile_info);
m_retreat_button_pos = calc_result.retreat_button;
m_skill_button_pos = calc_result.skill_button;
m_has_multi_stages = calc_result.has_multi_stages;
return true;
}
@@ -335,7 +336,8 @@ bool asst::BattleHelper::update_deployment(bool init, const cv::Mat& reusable, b
}
// if side = true, get top view of the selected operator, tile size is 5x5
cv::Mat asst::BattleHelper::get_top_view(const cv::Mat& cam_img, bool side)
// has_multi_stages: does map have multi stages, e.g. TN-1 ~ TN-4
cv::Mat asst::BattleHelper::get_top_view(const cv::Mat& cam_img, bool side, bool has_multi_stages)
{
if (!side) {
return cv::Mat {}; // TODO
@@ -355,7 +357,7 @@ cv::Mat asst::BattleHelper::get_top_view(const cv::Mat& cam_img, bool side)
};
std::vector<cv::Point2f> screen_points;
for (const auto& point : world_points) {
cv::Vec3d temp { point.x + m_map_data.view[0].x, -point.y, Map::TileCalc2::rel_pos_z };
cv::Vec3d temp { point.x + (has_multi_stages ? m_map_data.view[0].x : 0), -point.y, Map::TileCalc2::rel_pos_z };
auto screen_pt = Map::TileCalc2::world_to_screen(m_map_data, temp, true);
screen_points.push_back(screen_pt);
}
@@ -872,7 +874,7 @@ bool asst::BattleHelper::click_skill(bool keep_waiting)
if (keep_waiting && retry > 0 && (retry % 10 == 0) && !check_in_battle(image)) {
return false;
}
top_view = get_top_view(image, true);
top_view = get_top_view(image, true, m_has_multi_stages);
Matcher skill_analyzer { top_view };
skill_analyzer.set_task_info("BattleSkillReadyOnClick-TopView");
skill_analyzer.set_roi({ 250, 250, 250, 250 });

View File

@@ -56,7 +56,7 @@ protected:
bool update_kills(const cv::Mat& image, const cv::Mat& image_prev = cv::Mat());
bool update_cost(const cv::Mat& image, const cv::Mat& image_prev = cv::Mat());
cv::Mat get_top_view(const cv::Mat& cam_img, bool side = true);
cv::Mat get_top_view(const cv::Mat& cam_img, bool side = true, bool has_multi_stages = false);
bool deploy_oper(const std::string& name, const Point& loc, battle::DeployDirection direction);
bool retreat_oper(const std::string& name);
@@ -109,6 +109,7 @@ protected:
std::unordered_map<Point, TilePack::TileInfo> m_normal_tile_info; // 正常的坐标映射
Point m_skill_button_pos;
Point m_retreat_button_pos;
bool m_has_multi_stages = false;
std::unordered_map<std::string, battle::SkillUsage> m_skill_usage;
std::unordered_map<std::string, int> m_skill_times;
std::unordered_map<std::string, int> m_skill_error_count;