Files
better-genshin-impact/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ThrowRod.cs
FishmanTheMurloc 29a2c0069e bug fix:拉条过程中内存没有及时释放 (#1266)
* bug fix:拉条过程中内存没有及时释放

* 新增LiftAndHold行为用于举竿、检测预抛竿时鼠标左键是否被意外松开、终止任务;抛竿开始后5秒内如从未找到落点,则返回失败,并配有单元测试;添加抛竿时无鱼饵适用鱼的单元测试;调整变量名

* 新增一个钓鱼昼夜设置枚举DontChange及其逻辑(枚举值为3),表示不调整时间直接开钓

* 针对可能是游戏中的雾气/滤镜/小黄鸭之类不明原因干扰了钓鱼拉条框的识别,修改了CV算法,使其不严格按照黄色(255,255,192)找矩形,而是按一定HSV范围寻找,并加强过滤;添加上述不明原因案例的测试用例

* 将MySimpleParallel改造为支持两个以上子行为;将“检查抛竿结果”行为合并到“下杆中”并行节点,以去除检查的等待时间,由此希望能应对鱼过快上钩的情况
2025-03-14 00:17:37 +08:00

200 lines
8.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using BehaviourTree;
using BetterGenshinImpact.GameTask.AutoFishing.Model;
using BetterGenshinImpact.GameTask.AutoFishing;
using BetterGenshinImpact.GameTask.Model.Area.Converter;
using BetterGenshinImpact.GameTask.Model.Area;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using BetterGenshinImpact.Core.Config;
using Compunet.YoloV8;
using Microsoft.Extensions.Time.Testing;
namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
{
public partial class BehavioursTests
{
[Theory]
[InlineData(@"20250225101304534_ThrowRod_Succeeded.png", "false worm bait")]
[InlineData(@"20250226162217468_ThrowRod_Succeeded.png", "fruit paste bait")]
/// <summary>
/// 测试各种抛竿,结果为成功
/// </summary>
public void ThrowRodTest_VariousFish_ShouldSuccess(string screenshot1080p, string selectedBaitName)
{
//
Bitmap bitmap = new Bitmap(@$"..\..\..\Assets\AutoFishing\{screenshot1080p}");
var imageRegion = new GameCaptureRegion(bitmap, 0, 0, new DesktopRegion(new FakeMouseSimulator()), converter: new ScaleConverter(1d), drawContent: new FakeDrawContent());
var predictor = YoloV8Builder.CreateDefaultBuilder().UseOnnxModel(Global.Absolute(@"Assets\Model\Fish\bgi_fish.onnx")).Build();
var blackboard = new Blackboard(predictor, sleep: i => { })
{
selectedBaitName = selectedBaitName
};
FakeTimeProvider fakeTimeProvider = new FakeTimeProvider();
//
ThrowRod sut = new ThrowRod("-", blackboard, new FakeLogger(), false, new FakeInputSimulator(), fakeTimeProvider, drawContent: new FakeDrawContent());
BehaviourStatus actual = sut.Tick(imageRegion);
//
Assert.False(blackboard.throwRodNoBaitFish);
Assert.Equal(BehaviourStatus.Succeeded, actual);
}
[Theory]
[InlineData(@"20250225101304534_ThrowRod_Succeeded.png", "redrot bait")]
[InlineData(@"20250225101304534_ThrowRod_Succeeded.png", "fake fly bait")]
/// <summary>
/// 测试各种抛竿未满足HutaoFisher判定结果为运行中
/// </summary>
public void ThrowRodTest_VariousFish_ShouldFail(string screenshot1080p, string selectedBaitName)
{
//
Bitmap bitmap = new Bitmap(@$"..\..\..\Assets\AutoFishing\{screenshot1080p}");
var imageRegion = new GameCaptureRegion(bitmap, 0, 0, new DesktopRegion(new FakeMouseSimulator()), converter: new ScaleConverter(1d), drawContent: new FakeDrawContent());
var predictor = YoloV8Builder.CreateDefaultBuilder().UseOnnxModel(Global.Absolute(@"Assets\Model\Fish\bgi_fish.onnx")).Build();
var blackboard = new Blackboard(predictor, sleep: i => { })
{
selectedBaitName = selectedBaitName
};
FakeTimeProvider fakeTimeProvider = new FakeTimeProvider();
//
ThrowRod sut = new ThrowRod("-", blackboard, new FakeLogger(), false, new FakeInputSimulator(), fakeTimeProvider, drawContent: new FakeDrawContent());
BehaviourStatus actual = sut.Tick(imageRegion);
//
Assert.False(blackboard.throwRodNoBaitFish);
Assert.Equal(BehaviourStatus.Running, actual);
}
[Theory]
[InlineData(@"20250225101304534_ThrowRod_Succeeded.png", "flashing maintenance mek bait")]
/// <summary>
/// 测试各种抛竿,无鱼饵适用鱼,结果为失败
/// </summary>
public void ThrowRodTest_NoBaitFish_ShouldFail(string screenshot1080p, string selectedBaitName)
{
//
Bitmap bitmap = new Bitmap(@$"..\..\..\Assets\AutoFishing\{screenshot1080p}");
var imageRegion = new GameCaptureRegion(bitmap, 0, 0, new DesktopRegion(new FakeMouseSimulator()), converter: new ScaleConverter(1d), drawContent: new FakeDrawContent());
var predictor = YoloV8Builder.CreateDefaultBuilder().UseOnnxModel(Global.Absolute(@"Assets\Model\Fish\bgi_fish.onnx")).Build();
var blackboard = new Blackboard(predictor, sleep: i => { })
{
selectedBaitName = selectedBaitName
};
FakeTimeProvider fakeTimeProvider = new FakeTimeProvider();
//
ThrowRod sut = new ThrowRod("-", blackboard, new FakeLogger(), false, new FakeInputSimulator(), fakeTimeProvider, drawContent: new FakeDrawContent());
BehaviourStatus actual = sut.Tick(imageRegion);
//
Assert.False(blackboard.throwRodNoBaitFish);
Assert.Equal(BehaviourStatus.Running, actual);
//
// Do nothing
//
for (int i = 0; i < 10; i++)
{
sut.Tick(imageRegion);
}
//
Assert.True(blackboard.throwRodNoBaitFish);
}
/// <summary>
/// 抛竿时,给定三条炮鲀鱼,并且确定算法能将下杆点从鱼的左侧移动到最左侧的炮鲀鱼上,此时希望“当前鱼”能始终锁定在最左侧的鱼上
/// 由于偶尔观测到“摇摆”行为的出现,故设计此测试
/// </summary>
[Fact]
public void ThrowRodTest_Target_ShouldBeTheLeftOne()
{
//
Bitmap bitmap = new Bitmap(@$"..\..\..\Assets\AutoFishing\202503082114541115.png");
var imageRegion = new GameCaptureRegion(bitmap, 0, 0, new DesktopRegion(new FakeMouseSimulator()), converter: new ScaleConverter(1d), drawContent: new FakeDrawContent());
var predictor = YoloV8Builder.CreateDefaultBuilder().UseOnnxModel(Global.Absolute(@"Assets\Model\Fish\bgi_fish.onnx")).Build();
var blackboard = new Blackboard(predictor, sleep: i => { })
{
selectedBaitName = "fake fly bait"
};
//
ThrowRod sut = new ThrowRod("-", blackboard, new FakeLogger(), false, new FakeInputSimulator(), new FakeTimeProvider(), drawContent: new FakeDrawContent());
sut.Tick(imageRegion);
var actual = sut.currentFish;
//
Assert.True(blackboard.fishpond.TargetRect != null && blackboard.fishpond.TargetRect.Value != OpenCvSharp.Rect.Empty);
Assert.Equal(3, blackboard.fishpond.Fishes.Count(f => f.FishType.Name == "pufferfish"));
Assert.Equal(blackboard.fishpond.Fishes.OrderBy(f => f.Rect.X).First(), actual);
//
bitmap = new Bitmap(@$"..\..\..\Assets\AutoFishing\202503082114560489.png");
imageRegion = new GameCaptureRegion(bitmap, 0, 0, new DesktopRegion(new FakeMouseSimulator()), converter: new ScaleConverter(1d), drawContent: new FakeDrawContent());
//
sut.Tick(imageRegion);
actual = sut.currentFish;
//
Assert.Equal(3, blackboard.fishpond.Fishes.Count(f => f.FishType.Name == "pufferfish"));
Assert.Equal(blackboard.fishpond.Fishes.OrderBy(f => f.Rect.X).First(), actual);
}
[Theory]
[InlineData(@"202502252347412417.png")]
[InlineData(@"202503012143011486@900p.png")]
/// <summary>
/// 测试各种抛竿,超时未找到落点,结果为失败
/// </summary>
public void ThrowRodTest_NoTarget_ShouldFail(string screenshot1080p)
{
//
Bitmap bitmap = new Bitmap(@$"..\..\..\Assets\AutoFishing\{screenshot1080p}");
var imageRegion = new GameCaptureRegion(bitmap, 0, 0, new DesktopRegion(new FakeMouseSimulator()), converter: new ScaleConverter(1d), drawContent: new FakeDrawContent());
var predictor = YoloV8Builder.CreateDefaultBuilder().UseOnnxModel(Global.Absolute(@"Assets\Model\Fish\bgi_fish.onnx")).Build();
var blackboard = new Blackboard(predictor, sleep: i => { });
FakeTimeProvider fakeTimeProvider = new FakeTimeProvider();
//
ThrowRod sut = new ThrowRod("-", blackboard, new FakeLogger(), false, new FakeInputSimulator(), fakeTimeProvider, drawContent: new FakeDrawContent());
BehaviourStatus actual = sut.Tick(imageRegion);
//
Assert.False(blackboard.throwRodNoTarget);
Assert.Equal(BehaviourStatus.Running, actual);
//
fakeTimeProvider.Advance(TimeSpan.FromSeconds(5.1));
//
actual = sut.Tick(imageRegion);
//
Assert.True(blackboard.throwRodNoTarget);
Assert.Equal(BehaviourStatus.Failed, actual);
}
}
}