ensure AccuracyCircle doesn't land in gaps created by RankNotches

This commit is contained in:
Walavouchey 2023-02-07 11:16:36 +01:00
parent 12f6d461b9
commit 6ace6bfee1
3 changed files with 43 additions and 2 deletions

View File

@ -24,11 +24,20 @@ namespace osu.Game.Tests.Visual.Ranking
{
public partial class TestSceneAccuracyCircle : OsuTestScene
{
[TestCase(0, ScoreRank.D)]
[TestCase(0.2, ScoreRank.D)]
[TestCase(0.5, ScoreRank.D)]
[TestCase(0.699, ScoreRank.D)]
[TestCase(0.7, ScoreRank.C)]
[TestCase(0.75, ScoreRank.C)]
[TestCase(0.799, ScoreRank.C)]
[TestCase(0.80, ScoreRank.B)]
[TestCase(0.85, ScoreRank.B)]
[TestCase(0.899, ScoreRank.B)]
[TestCase(0.9, ScoreRank.A)]
[TestCase(0.925, ScoreRank.A)]
[TestCase(0.949, ScoreRank.A)]
[TestCase(0.95, ScoreRank.S)]
[TestCase(0.975, ScoreRank.S)]
[TestCase(0.9999, ScoreRank.S)]
[TestCase(1, ScoreRank.X)]

View File

@ -73,6 +73,11 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
/// </summary>
private const double virtual_ss_percentage = 0.01;
/// <summary>
/// The width of a <see cref="RankNotch"/> in terms of accuracy.
/// </summary>
public const double NOTCH_WIDTH_PERCENTAGE = 0.002;
/// <summary>
/// The easing for the circle filling transforms.
/// </summary>
@ -263,7 +268,34 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
using (BeginDelayedSequence(ACCURACY_TRANSFORM_DELAY))
{
double targetAccuracy = score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH ? 1 : Math.Min(1 - virtual_ss_percentage, score.Accuracy);
double targetAccuracy = score.Accuracy;
// Ensure the gauge overshoots or undershoots a bit so it doesn't land in the gaps of the inner graded circle (caused by `RankNotch`es),
// to prevent ambiguity on what grade it's pointing at.
double[] notchPercentages = { 0.7, 0.8, 0.9, 0.95 };
foreach (double p in notchPercentages)
{
if (targetAccuracy > p - NOTCH_WIDTH_PERCENTAGE / 2 && targetAccuracy < p + NOTCH_WIDTH_PERCENTAGE / 2)
{
int tippingDirection = targetAccuracy - p >= 0 ? 1 : -1; // We "round up" here to match rank criteria
targetAccuracy = p + tippingDirection * (NOTCH_WIDTH_PERCENTAGE / 2);
break;
}
}
// The final gap between 99.999...% (S) and 100% (SS) is exaggerated by `virtual_ss_percentage`. We don't want to land there either.
if (score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH)
targetAccuracy = 1;
else
targetAccuracy = Math.Min(1 - virtual_ss_percentage - NOTCH_WIDTH_PERCENTAGE / 2, targetAccuracy);
// The accuracy circle gauge visually fills up a bit too much.
// This wouldn't normally matter but we want it to align properly with the inner graded circle in the above cases.
const double visual_alignment_offset = 0.001;
if (targetAccuracy < 1 && targetAccuracy >= visual_alignment_offset)
targetAccuracy -= visual_alignment_offset;
accuracyCircle.FillTo(targetAccuracy, ACCURACY_TRANSFORM_DURATION, ACCURACY_TRANSFORM_EASING);

View File

@ -41,7 +41,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.Y,
Height = AccuracyCircle.RANK_CIRCLE_RADIUS,
Width = 1f,
Width = (float)AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 360f,
Colour = OsuColour.Gray(0.3f),
EdgeSmoothness = new Vector2(1f)
}