Skip to content

小地图定位方式

DoctorReid edited this page Mar 22, 2024 · 10 revisions

定位能力

整个脚本的基础能力,就是如何通过界面左上角的小地图,匹配大地图,获取角色当前所在的位置坐标,从而判断后续往哪个方向移动。

效果展示可以看 B站视频,目前整体定位方案(包含小地图处理)在充分缓存情况下,平均耗时 20ms (AMD Ryzen 5 5600U + 16G内存)。

截取小地图

默认配置中 game_sample.yml 有一个截取小地图的定位配置 mini_map

用户可以进行重新校准,使用 calibrator._check_mini_map_pos,可直接使用exe应用上的校准功能。

小地图特征

截取小地图后,我们需要在大地图上匹配小地图,了解小地图特征将有利于理解具体的定位算法。

颜色风格

  • 基本格调为黑白风,在没有特殊点(传送点、商店等)的时候,整个图基本没有什么特征点可用。
  • 道路颜色的RGB色值接近,例如当前楼层的道路颜色在(55,55,55)附近。
  • 人物朝向是在小地图上加了一层蓝色的半透明雷达。
  • 怪物的位置和朝向是在小地图上加了一个点和一层红色的半透明雷达。

地图的缩放比例

经验证,人物在静止不动时,小地图的缩放比例是跟大地图的最小缩放比例一样的;而人物在跑动时候,小地图会有一个渐变的缩小。

另外,大地图上,进行缩放后,传送点等的图标(特殊点)大小是不会改变的,而小地图因人物跑动而缩小时,传送点等的图标是会跟着缩小的。

因此,使用使用最小缩放比例的大地图进行坐标判断是最方便的。

小地图特殊元素

小地图部分,如果只是对大地图进行简单的截取展示,那匹配就简单很多了。可是事实上没这么简单,小地图上还有些其他元素:

  • 中心代表人物的小箭头,以及代表人物朝向的浅蓝色扇型
  • 非道路部分,使用透明的方式,展示了下面的游戏界面的图层
  • 被怪物锁定时,小地图的红色色道有有所提高

小地图匹配

了解上述小地图特征后,就可以理解怎么使用小地图匹配大地图了。

  • 特征匹配 - 小地图有特殊点的情况,可以利用特殊点进行特征匹配。具体代码见
    • cal_pos.cal_character_pos_by_sp_result - 根据特殊点在小地图和大地图上的位置,直接计算出人物坐标。
  • 模板匹配 - 小地图没有特殊点的情况,可以使用模板匹配。具体代码见
    • cal_pos.cal_character_pos_by_road_mask - 使用颜色扣取的道路掩码,使用黑白图所以匹配速度较快。
    • cal_pos.cal_character_pos_by_gray - 使用小地图灰度图,在大地图上匹配,配合道路掩码,速度慢一点点,准确率会提高。
    • cal_pos.cal_character_pos_by_original - 使用小地图原图直接在大地图上匹配,配合道路掩码,作为最后兜底。
    • mini_map.get_road_mask_for_world_patrol - 道路掩码的获取代码。

坐标记录和预估

两种匹配方式都会面临一个问题,就是大地图很大的时候,匹配效率会很慢,而且准确度会下降。

因此脚本中进行了如下的优化

  1. 假设所有指令都从某个传送点开始,且我们能事先知道传送点的落地坐标,即可记录第一个点(开始点)。
  2. 移动时,根据移动时间可以预估人物的移动距离,即可以预估当前坐标的一个范围。
  3. 使用预估的范围,进行大地图的截取,然后只在这一小部分的大地图上进行匹配,可以达到一个又快又准的效果。
  4. 移动途中持续记录坐标,保持使用小范围的大地图进行匹配。

其他小优化

  • 人物朝向的蓝色雷达位置相对固定,可以通过与道路颜色的差值去除掉。
  • 模板匹配时,需要使用多个缩放比例进行计算,这里可以并发进行。
  • 匹配结果,可以用预估移动距离和人物朝向对结果校验,剔除一些偏移较远的结果。
  • 匹配失败时,可以禁止人物疾跑,甚至停止人物移动,避免乱跑导致人物卡死。

模拟宇宙

模拟宇宙的地图有以下特征

  • 没有普通的特殊点,只有事件的问号。
  • 副本中地图都只是截取了大世界地图的一部分,且不会出现跨楼层。

基于以上特征,模拟宇宙中定位仅做了以下调整

  • 模板匹配不能使用直接道路掩码匹配,因为这是不完整的,准确率很低。