mirror of
https://github.com/ppy/osu.git
synced 2025-01-12 17:43:05 +08:00
Fix SPM calculation logic not handling paused clocks (#7253)
Fix SPM calculation logic not handling paused clocks Co-authored-by: Dean Herbert <pe@ppy.sh>
This commit is contained in:
commit
f150d22eaf
@ -70,6 +70,21 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
AddAssert("is rotation absolute almost same", () => Precision.AlmostEquals(drawableSpinner.Disc.RotationAbsolute, estimatedRotation, 100));
|
AddAssert("is rotation absolute almost same", () => Precision.AlmostEquals(drawableSpinner.Disc.RotationAbsolute, estimatedRotation, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSpinPerMinuteOnRewind()
|
||||||
|
{
|
||||||
|
double estimatedSpm = 0;
|
||||||
|
|
||||||
|
addSeekStep(2500);
|
||||||
|
AddStep("retrieve spm", () => estimatedSpm = drawableSpinner.SpmCounter.SpinsPerMinute);
|
||||||
|
|
||||||
|
addSeekStep(5000);
|
||||||
|
AddAssert("spm still valid", () => Precision.AlmostEquals(drawableSpinner.SpmCounter.SpinsPerMinute, estimatedSpm, 1.0));
|
||||||
|
|
||||||
|
addSeekStep(2500);
|
||||||
|
AddAssert("spm still valid", () => Precision.AlmostEquals(drawableSpinner.SpmCounter.SpinsPerMinute, estimatedSpm, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
private void addSeekStep(double time)
|
private void addSeekStep(double time)
|
||||||
{
|
{
|
||||||
AddStep($"seek to {time}", () => track.Seek(time));
|
AddStep($"seek to {time}", () => track.Seek(time));
|
||||||
@ -84,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
new Spinner
|
new Spinner
|
||||||
{
|
{
|
||||||
Position = new Vector2(256, 192),
|
Position = new Vector2(256, 192),
|
||||||
EndTime = 5000,
|
EndTime = 6000,
|
||||||
},
|
},
|
||||||
// placeholder object to avoid hitting the results screen
|
// placeholder object to avoid hitting the results screen
|
||||||
new HitObject
|
new HitObject
|
||||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
public readonly SpinnerDisc Disc;
|
public readonly SpinnerDisc Disc;
|
||||||
public readonly SpinnerTicks Ticks;
|
public readonly SpinnerTicks Ticks;
|
||||||
private readonly SpinnerSpmCounter spmCounter;
|
public readonly SpinnerSpmCounter SpmCounter;
|
||||||
|
|
||||||
private readonly Container mainContainer;
|
private readonly Container mainContainer;
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
spmCounter = new SpinnerSpmCounter
|
SpmCounter = new SpinnerSpmCounter
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
@ -177,8 +177,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
Disc.Tracking = OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false;
|
Disc.Tracking = OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false;
|
||||||
if (!spmCounter.IsPresent && Disc.Tracking)
|
if (!SpmCounter.IsPresent && Disc.Tracking)
|
||||||
spmCounter.FadeIn(HitObject.TimeFadeIn);
|
SpmCounter.FadeIn(HitObject.TimeFadeIn);
|
||||||
|
|
||||||
base.Update();
|
base.Update();
|
||||||
}
|
}
|
||||||
@ -189,7 +189,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
circle.Rotation = Disc.Rotation;
|
circle.Rotation = Disc.Rotation;
|
||||||
Ticks.Rotation = Disc.Rotation;
|
Ticks.Rotation = Disc.Rotation;
|
||||||
spmCounter.SetRotation(Disc.RotationAbsolute);
|
SpmCounter.SetRotation(Disc.RotationAbsolute);
|
||||||
|
|
||||||
float relativeCircleScale = Spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight;
|
float relativeCircleScale = Spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight;
|
||||||
Disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint);
|
Disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint);
|
||||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.MathUtils;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
|
|
||||||
@ -62,6 +63,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
public void SetRotation(float currentRotation)
|
public void SetRotation(float currentRotation)
|
||||||
{
|
{
|
||||||
|
// Never calculate SPM by same time of record to avoid 0 / 0 = NaN or X / 0 = Infinity result.
|
||||||
|
if (Precision.AlmostEquals(0, Time.Elapsed))
|
||||||
|
return;
|
||||||
|
|
||||||
// If we've gone back in time, it's fine to work with a fresh set of records for now
|
// If we've gone back in time, it's fine to work with a fresh set of records for now
|
||||||
if (records.Count > 0 && Time.Current < records.Last().Time)
|
if (records.Count > 0 && Time.Current < records.Last().Time)
|
||||||
records.Clear();
|
records.Clear();
|
||||||
@ -71,6 +76,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
var record = records.Peek();
|
var record = records.Peek();
|
||||||
while (records.Count > 0 && Time.Current - records.Peek().Time > spm_count_duration)
|
while (records.Count > 0 && Time.Current - records.Peek().Time > spm_count_duration)
|
||||||
record = records.Dequeue();
|
record = records.Dequeue();
|
||||||
|
|
||||||
SpinsPerMinute = (currentRotation - record.Rotation) / (Time.Current - record.Time) * 1000 * 60 / 360;
|
SpinsPerMinute = (currentRotation - record.Rotation) / (Time.Current - record.Time) * 1000 * 60 / 360;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user