Files
better-genshin-impact/BetterGenshinImpact/GameTask/MapMask/MapMaskTrigger.cs
辉鸭蛋 c9cd8fcd5f feat(地图遮罩): 新增小地图遮罩显示与自动记录路径功能
- 添加小地图遮罩显示功能,在游戏主界面显示玩家位置及附近点位
- 新增自动记录路径功能开关配置
- 实现 MiniMapPointsCanvas 控件用于小地图点位渲染
- 扩展 MapMaskTrigger 以支持小地图遮罩和路径记录逻辑
2026-02-24 01:44:44 +08:00

167 lines
5.8 KiB
C#

using System;
using BetterGenshinImpact.Core.Recognition.OpenCv;
using BetterGenshinImpact.GameTask.AutoPathing;
using BetterGenshinImpact.GameTask.Common.BgiVision;
using BetterGenshinImpact.GameTask.Common.Element.Assets;
using BetterGenshinImpact.GameTask.Common.Map.Maps;
using BetterGenshinImpact.GameTask.Common.Map.Maps.Base;
using BetterGenshinImpact.GameTask.Common.Map.Maps.Layer;
using BetterGenshinImpact.Helpers;
using BetterGenshinImpact.View;
using BetterGenshinImpact.ViewModel;
using Microsoft.Extensions.Logging;
using OpenCvSharp;
using Rect = System.Windows.Rect;
namespace BetterGenshinImpact.GameTask.MapMask;
/// <summary>
/// 地图遮罩触发器
/// </summary>
public class MapMaskTrigger : ITaskTrigger
{
private readonly ILogger<MapMaskTrigger> _logger = App.GetLogger<MapMaskTrigger>();
public string Name => "地图遮罩";
public bool IsEnabled { get; set; }
public int Priority => 1; // 低优先级
public bool IsExclusive => false;
public GameUiCategory SupportedGameUiCategory => GameUiCategory.BigMap;
private readonly MapMaskConfig _config = TaskContext.Instance().Config.MapMaskConfig;
private readonly string _mapMatchingMethod = TaskContext.Instance().Config.PathingConditionConfig.MapMatchingMethod;
private readonly TemplateMatchStabilityDetector _detector = new();
private DateTime _prevExecute = DateTime.MinValue;
// 图像连续稳定次数
private int _stableCount = 0;
private ISceneMap _teyvatMap => MapManager.GetMap(MapTypes.Teyvat, _mapMatchingMethod);
private OpenCvSharp.Rect _prevRect = default;
private const int RectDebounceThreshold = 3;
private readonly NavigationInstance _navigationInstance = new();
public void Init()
{
IsEnabled = _config.Enabled;
// 关闭时隐藏UI
if (!IsEnabled)
{
UIDispatcherHelper.Invoke(() =>
{
if (MaskWindow.InstanceNullable() != null)
{
if (MaskWindow.Instance().DataContext is MaskWindowViewModel vm)
{
vm.IsInBigMapUi = false;
}
}
});
}
}
public void OnCapture(CaptureContent content)
{
if ((DateTime.Now - _prevExecute).TotalMilliseconds <= 50)
{
return;
}
_prevExecute = DateTime.Now;
try
{
var region = content.CaptureRectArea;
var inBigMapUi = content.CurrentGameUiCategory == GameUiCategory.BigMap || Bv.IsInBigMapUi(region);
UIDispatcherHelper.Invoke(() =>
{
if (MaskWindow.Instance().DataContext is MaskWindowViewModel vm)
{
vm.IsInBigMapUi = inBigMapUi;
}
});
if (inBigMapUi)
{
if (_detector.IsStable(region.CacheGreyMat))
{
_stableCount++;
if (_stableCount >= 20)
{
_stableCount = 0;
}
}
else
{
_stableCount = 0;
}
if (_stableCount == 0)
{
var rect256 = BigMapTeyvat256Layer.GetInstance((SceneBaseMap)_teyvatMap).GetBigMapRect(region.CacheGreyMat, _prevRect);
if (rect256 != default)
{
// 过大或过小的区域不处理
if (rect256 is { Width: < 50, Height: < 40 } || rect256 is { Width: > 3000, Height: > 1800 })
{
_prevRect = default;
return;
}
// if (_prevRect != default)
// {
// var dx = Math.Abs(rect256.X - _prevRect.X);
// var dy = Math.Abs(rect256.Y - _prevRect.Y);
// if (dx <= RectDebounceThreshold && dy <= RectDebounceThreshold)
// {
// return;
// }
// }
_prevRect = rect256;
}
const int s = TeyvatMap.BigMap256ScaleTo2048; // 相对2048做8倍缩放
var rect2048 = new Rect(rect256.X * s, rect256.Y * s, rect256.Width * s, rect256.Height * s);
UIDispatcherHelper.Invoke(() => { MaskWindow.Instance().PointsCanvasControl.UpdateViewport(rect2048.X, rect2048.Y, rect2048.Width, rect2048.Height); });
}
}
else
{
if ((_config.MiniMapMaskEnabled || _config.PathAutoRecordEnabled) && Bv.IsInMainUi(region))
{
// 主界面上展示小地图
if (_config.MiniMapMaskEnabled)
{
var miniPoint = _navigationInstance.GetPositionStable(region, nameof(MapTypes.Teyvat), TaskContext.Instance().Config.PathingConditionConfig.MapMatchingMethod);
if (miniPoint != default)
{
UIDispatcherHelper.Invoke(() => { MaskWindow.Instance().MiniMapPointsCanvasControl.UpdateViewport(miniPoint.X, miniPoint.Y, 300, 300); });
}
// 自动记录路径
if (_config.PathAutoRecordEnabled)
{
// ...
}
}
}
_prevRect = default;
}
}
catch (Exception e)
{
_logger.LogDebug(e, "实时地图定位时发生异常");
}
}
}