mirror of https://github.com/ppy/osu
Merge pull request #25177 from peppy/spinner-max-display
This commit is contained in:
commit
d0599496bd
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue