Merge pull request #25177 from peppy/spinner-max-display

This commit is contained in:
Dean Herbert 2023-10-21 11:10:09 +09:00 committed by GitHub
commit d0599496bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 91 additions and 45 deletions

View File

@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Audio;
@ -26,6 +27,15 @@ public partial class TestSceneSpinner : OsuSkinnableTestScene
private TestDrawableSpinner drawableSpinner;
private readonly BindableDouble spinRate = new BindableDouble();
protected override void LoadComplete()
{
base.LoadComplete();
AddSliderStep("Spin rate", 0.5, 5, 1, val => spinRate.Value = val);
}
[TestCase(true)]
[TestCase(false)]
public void TestVariousSpinners(bool autoplay)
@ -86,7 +96,7 @@ public void TestSpinnerSpinRequirements(int od, int normalTicks, int bonusTicks)
spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { OverallDifficulty = od });
return drawableSpinner = new TestDrawableSpinner(spinner, true)
return drawableSpinner = new TestDrawableSpinner(spinner, true, spinRate)
{
Anchor = Anchor.Centre,
Depth = depthIndex++,
@ -114,7 +124,7 @@ private Drawable testSingle(float circleSize, bool auto = false, double length =
spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize });
drawableSpinner = new TestDrawableSpinner(spinner, auto)
drawableSpinner = new TestDrawableSpinner(spinner, auto, spinRate)
{
Anchor = Anchor.Centre,
Depth = depthIndex++,
@ -130,18 +140,20 @@ private Drawable testSingle(float circleSize, bool auto = false, double length =
private partial class TestDrawableSpinner : DrawableSpinner
{
private readonly bool auto;
private readonly BindableDouble spinRate;
public TestDrawableSpinner(Spinner s, bool auto)
public TestDrawableSpinner(Spinner s, bool auto, BindableDouble spinRate)
: base(s)
{
this.auto = auto;
this.spinRate = spinRate;
}
protected override void Update()
{
base.Update();
if (auto)
RotationTracker.AddRotation((float)(Clock.ElapsedFrameTime * 2));
RotationTracker.AddRotation((float)(Clock.ElapsedFrameTime * spinRate.Value));
}
}
}

View File

@ -48,9 +48,16 @@ public partial class DrawableSpinner : DrawableOsuHitObject
/// <summary>
/// The amount of bonus score gained from spinning after the required number of spins, for display purposes.
/// </summary>
public IBindable<double> GainedBonus => gainedBonus;
public double CurrentBonusScore => score_per_tick * Math.Clamp(completedFullSpins.Value - HitObject.SpinsRequiredForBonus, 0, HitObject.MaximumBonusSpins);
private readonly Bindable<double> gainedBonus = new BindableDouble();
/// <summary>
/// The maximum amount of bonus score which can be achieved from extra spins.
/// </summary>
public double MaximumBonusScore => score_per_tick * HitObject.MaximumBonusSpins;
public IBindable<int> CompletedFullSpins => completedFullSpins;
private readonly Bindable<int> completedFullSpins = new Bindable<int>();
/// <summary>
/// The number of spins per minute this spinner is spinning at, for display purposes.
@ -286,8 +293,6 @@ protected override void UpdateAfterChildren()
private static readonly int score_per_tick = new SpinnerBonusTick.OsuSpinnerBonusTickJudgement().MaxNumericResult;
private int completedFullSpins;
private void updateBonusScore()
{
if (ticks.Count == 0)
@ -295,27 +300,21 @@ private void updateBonusScore()
int spins = (int)(Result.TotalRotation / 360);
if (spins < completedFullSpins)
if (spins < completedFullSpins.Value)
{
// rewinding, silently handle
completedFullSpins = spins;
completedFullSpins.Value = spins;
return;
}
while (completedFullSpins != spins)
while (completedFullSpins.Value != spins)
{
var tick = ticks.FirstOrDefault(t => !t.Result.HasResult);
// tick may be null if we've hit the spin limit.
if (tick != null)
{
tick.TriggerResult(true);
tick?.TriggerResult(true);
if (tick is DrawableSpinnerBonusTick)
gainedBonus.Value = score_per_tick * (spins - HitObject.SpinsRequiredForBonus);
}
completedFullSpins++;
completedFullSpins.Value++;
}
}
}

View File

@ -35,14 +35,6 @@ private void load(DrawableHitObject drawableHitObject)
InternalChildren = new Drawable[]
{
bonusCounter = new OsuSpriteText
{
Alpha = 0,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Font = OsuFont.Default.With(size: 24),
Y = -120,
},
new ArgonSpinnerDisc
{
RelativeSizeAxes = Axes.Both,
@ -85,19 +77,33 @@ private void load(DrawableHitObject drawableHitObject)
};
}
private IBindable<double> gainedBonus = null!;
private IBindable<int> completedSpins = null!;
private IBindable<double> spinsPerMinute = null!;
protected override void LoadComplete()
{
base.LoadComplete();
gainedBonus = drawableSpinner.GainedBonus.GetBoundCopy();
gainedBonus.BindValueChanged(bonus =>
completedSpins = drawableSpinner.CompletedFullSpins.GetBoundCopy();
completedSpins.BindValueChanged(_ =>
{
bonusCounter.Text = bonus.NewValue.ToString(NumberFormatInfo.InvariantInfo);
bonusCounter.FadeOutFromOne(1500);
bonusCounter.ScaleTo(1.5f).Then().ScaleTo(1f, 1000, Easing.OutQuint);
if (drawableSpinner.CurrentBonusScore <= 0)
return;
if (drawableSpinner.CurrentBonusScore == drawableSpinner.MaximumBonusScore)
{
bonusCounter.Text = "MAX";
bonusCounter.ScaleTo(1.5f).Then().ScaleTo(2.8f, 1000, Easing.OutQuint);
bonusCounter.FlashColour(Colour4.FromHex("FC618F"), 400);
bonusCounter.FadeOutFromOne(500);
}
else
{
bonusCounter.Text = drawableSpinner.CurrentBonusScore.ToString(NumberFormatInfo.InvariantInfo);
bonusCounter.ScaleTo(1.5f).Then().ScaleTo(1f, 1000, Easing.OutQuint);
bonusCounter.FadeOutFromOne(1500);
}
});
spinsPerMinute = drawableSpinner.SpinsPerMinute.GetBoundCopy();

View File

@ -24,6 +24,9 @@ public partial class DefaultSpinner : CompositeDrawable
private Container spmContainer = null!;
private OsuSpriteText spmCounter = null!;
[Resolved]
private OsuColour colours { get; set; } = null!;
public DefaultSpinner()
{
RelativeSizeAxes = Axes.Both;
@ -80,19 +83,33 @@ private void load(DrawableHitObject drawableHitObject)
});
}
private IBindable<double> gainedBonus = null!;
private IBindable<int> completedSpins = null!;
private IBindable<double> spinsPerMinute = null!;
protected override void LoadComplete()
{
base.LoadComplete();
gainedBonus = drawableSpinner.GainedBonus.GetBoundCopy();
gainedBonus.BindValueChanged(bonus =>
completedSpins = drawableSpinner.CompletedFullSpins.GetBoundCopy();
completedSpins.BindValueChanged(bonus =>
{
bonusCounter.Text = bonus.NewValue.ToString(NumberFormatInfo.InvariantInfo);
bonusCounter.FadeOutFromOne(1500);
bonusCounter.ScaleTo(1.5f).Then().ScaleTo(1f, 1000, Easing.OutQuint);
if (drawableSpinner.CurrentBonusScore <= 0)
return;
if (drawableSpinner.CurrentBonusScore == drawableSpinner.MaximumBonusScore)
{
bonusCounter.Text = "MAX";
bonusCounter.ScaleTo(1.5f).Then().ScaleTo(2.8f, 1000, Easing.OutQuint);
bonusCounter.FlashColour(colours.YellowLight, 400);
bonusCounter.FadeOutFromOne(500);
}
else
{
bonusCounter.Text = drawableSpinner.CurrentBonusScore.ToString(NumberFormatInfo.InvariantInfo);
bonusCounter.FadeOutFromOne(1500);
bonusCounter.ScaleTo(1.5f).Then().ScaleTo(1f, 1000, Easing.OutQuint);
}
});
spinsPerMinute = drawableSpinner.SpinsPerMinute.GetBoundCopy();

View File

@ -107,7 +107,7 @@ private void load(DrawableHitObject drawableHitObject, ISkinSource source)
});
}
private IBindable<double> gainedBonus = null!;
private IBindable<int> completedSpins = null!;
private IBindable<double> spinsPerMinute = null!;
private readonly Bindable<bool> completed = new Bindable<bool>();
@ -116,12 +116,24 @@ protected override void LoadComplete()
{
base.LoadComplete();
gainedBonus = DrawableSpinner.GainedBonus.GetBoundCopy();
gainedBonus.BindValueChanged(bonus =>
completedSpins = DrawableSpinner.CompletedFullSpins.GetBoundCopy();
completedSpins.BindValueChanged(bonus =>
{
bonusCounter.Text = bonus.NewValue.ToString(NumberFormatInfo.InvariantInfo);
bonusCounter.FadeOutFromOne(800, Easing.Out);
bonusCounter.ScaleTo(SPRITE_SCALE * 2f).Then().ScaleTo(SPRITE_SCALE * 1.28f, 800, Easing.Out);
if (DrawableSpinner.CurrentBonusScore <= 0)
return;
bonusCounter.Text = DrawableSpinner.CurrentBonusScore.ToString(NumberFormatInfo.InvariantInfo);
if (DrawableSpinner.CurrentBonusScore == DrawableSpinner.MaximumBonusScore)
{
bonusCounter.ScaleTo(1.4f).Then().ScaleTo(1.8f, 1000, Easing.Out);
bonusCounter.FadeOutFromOne(500, Easing.Out);
}
else
{
bonusCounter.FadeOutFromOne(800, Easing.Out);
bonusCounter.ScaleTo(SPRITE_SCALE * 2f).Then().ScaleTo(SPRITE_SCALE * 1.28f, 800, Easing.Out);
}
});
spinsPerMinute = DrawableSpinner.SpinsPerMinute.GetBoundCopy();