mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 11:20:04 +08:00
Use the cursor position to test nested object validity
This commit is contained in:
parent
3b8a73bf2c
commit
12210017e4
@ -184,7 +184,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
/// <summary>
|
||||
/// If the head circle is hit late and the mouse is in range of the follow circle,
|
||||
/// then all the repeats that the mouse has passed through should be hit.
|
||||
/// then all the repeats that the follow circle has passed through should be hit.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestHitLateInRangeHitsRepeat()
|
||||
@ -212,8 +212,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
/// <summary>
|
||||
/// If the head circle is hit and the mouse is in range of the follow circle,
|
||||
/// then only the ticks that were in range of the follow circle at the head should be hit.
|
||||
/// If any hitobject was outside the follow range, ALL hitobjects after that point should be missed.
|
||||
/// then only the ticks that are in range of the cursor position should be hit.
|
||||
/// If any hitobject does not meet this criteria, ALL hitobjects after that one should be missed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestHitLateInRangeDoesNotHitAfterAnyOutOfRange()
|
||||
@ -257,7 +257,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
assertTickJudgement(11, HitResult.LargeTickMiss);
|
||||
assertTickJudgement(12, HitResult.LargeTickMiss);
|
||||
|
||||
// And the tail should be hit because of its leniency.
|
||||
// This particular test actually starts tracking the slider just before the end, so the tail should be hit because of its leniency.
|
||||
assertTailJudgement(HitResult.LargeTickHit);
|
||||
|
||||
assertSliderJudgement(HitResult.IgnoreHit);
|
||||
@ -265,10 +265,10 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
/// <summary>
|
||||
/// If the head circle is hit and the mouse is in range of the follow circle,
|
||||
/// then a tick outside the range of the follow circle from the head should not be hit.
|
||||
/// then a tick not within the follow radius from the cursor position should not be hit.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestHitLateInRangeDoesNotHitOutOfRange()
|
||||
public void TestHitLateInRangeDoesNotHitOutOfRangeTick()
|
||||
{
|
||||
performTest(new List<ReplayFrame>
|
||||
{
|
||||
@ -293,6 +293,36 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
assertSliderJudgement(HitResult.IgnoreHit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the head circle is hit and the mouse is in range of the follow circle,
|
||||
/// then a tick not within the follow radius from the cursor position should not be hit.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestHitLateWithEdgeHit()
|
||||
{
|
||||
performTest(new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(time_slider_start + 150, slider_start_position - new Vector2(20), OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 150, slider_start_position - new Vector2(20), OsuAction.LeftButton),
|
||||
}, s =>
|
||||
{
|
||||
s.Path = new SliderPath(PathType.PERFECT_CURVE, new[]
|
||||
{
|
||||
Vector2.Zero,
|
||||
new Vector2(50, 50),
|
||||
new Vector2(20, 0),
|
||||
});
|
||||
|
||||
s.TickDistanceMultiplier = 0.35f;
|
||||
s.SliderVelocityMultiplier = 4;
|
||||
});
|
||||
|
||||
assertHeadJudgement(HitResult.Meh);
|
||||
assertTickJudgement(0, HitResult.LargeTickMiss);
|
||||
assertTailJudgement(HitResult.IgnoreMiss);
|
||||
assertSliderJudgement(HitResult.IgnoreHit);
|
||||
}
|
||||
|
||||
private void assertHeadJudgement(HitResult result)
|
||||
{
|
||||
AddAssert(
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
@ -75,8 +76,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
if (!isMouseInFollowArea(true))
|
||||
return;
|
||||
|
||||
Debug.Assert(screenSpaceMousePosition != null);
|
||||
|
||||
Vector2 mousePositionInSlider = slider.ToLocalSpace(screenSpaceMousePosition.Value) - slider.OriginPosition;
|
||||
|
||||
// When the head is hit and the mouse is in the expanded follow area, force a hit on every nested hitobject
|
||||
// from the start of the slider that is within follow-radius units from the head.
|
||||
// from the start of the slider that is within the follow area.
|
||||
|
||||
bool forceMiss = false;
|
||||
|
||||
@ -94,9 +99,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
double objectProgress = Math.Clamp((nested.HitObject.StartTime - slider.HitObject.StartTime) / slider.HitObject.Duration, 0, 1);
|
||||
Vector2 objectPosition = slider.HitObject.CurvePositionAt(objectProgress);
|
||||
|
||||
// When the first nested object that is further than follow-radius units away from the start of the slider is reached,
|
||||
// forcefully miss all other nested objects that would otherwise be valid to be hit by this process.
|
||||
if (forceMiss || objectPosition.LengthSquared > radius * radius)
|
||||
// When the first nested object that is further outside the follow area is reached,
|
||||
// forcefully miss all other nested objects that would otherwise be valid to be hit.
|
||||
// This covers a case of a slider overlapping itself that requires tracking to a tick on an outer edge.
|
||||
if (forceMiss || (objectPosition - mousePositionInSlider).LengthSquared > radius * radius)
|
||||
{
|
||||
nested.MissForcefully();
|
||||
forceMiss = true;
|
||||
|
Loading…
Reference in New Issue
Block a user