mirror of
https://github.com/ppy/osu
synced 2024-12-15 19:36:34 +00:00
Change KPS Counter implementation base and add better replay integration
The counter implementaiton is now list based, and will not invalidate previous hits by removing them but by testing if they are within the 1 second span, allowing better integration with replays and spectators.
This commit is contained in:
parent
2df24019fd
commit
89855cc1d6
@ -1,17 +1,24 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
@ -19,37 +26,71 @@ namespace osu.Game.Screens.Play.HUD
|
||||
{
|
||||
public class KeysPerSecondCounter : RollingCounter<int>, ISkinnableDrawable
|
||||
{
|
||||
private static Queue<DateTime>? timestamps;
|
||||
private static List<double> timestamps;
|
||||
private static double maxTime = double.NegativeInfinity;
|
||||
|
||||
private static event Action? onNewInput;
|
||||
private readonly TimeSpan refreshSpan = TimeSpan.FromSeconds(1);
|
||||
private static event Action onNewInput;
|
||||
|
||||
private const int invalidation_timeout = 1000;
|
||||
private const float alpha_when_invalid = 0.3f;
|
||||
|
||||
private readonly Bindable<bool> valid = new Bindable<bool>();
|
||||
|
||||
private static GameplayClock gameplayClock;
|
||||
private static IClock referenceClock;
|
||||
|
||||
private static IClock clock => referenceClock ?? gameplayClock;
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private DrawableRuleset drawableRuleset { get; set; }
|
||||
|
||||
[SettingSource("Smoothing time", "How smooth the counter should change\nThe more it is smooth, the less it's accurate.")]
|
||||
public BindableNumber<double> SmoothingTime { get; } = new BindableNumber<double>(350)
|
||||
{
|
||||
MaxValue = 1000,
|
||||
MinValue = 0
|
||||
};
|
||||
|
||||
public static void AddTimestamp()
|
||||
{
|
||||
timestamps?.Enqueue(DateTime.Now);
|
||||
Logger.Log($"Input timestamp attempt C: {clock.CurrentTime}ms | GC: {gameplayClock.CurrentTime} | RC: {referenceClock?.CurrentTime ?? -1} | Max: {maxTime})", level: LogLevel.Debug);
|
||||
|
||||
if (clock.CurrentTime >= maxTime)
|
||||
{
|
||||
Logger.Log("Input timestamp added.", level: LogLevel.Debug);
|
||||
timestamps?.Add(clock.CurrentTime);
|
||||
maxTime = timestamps?.Max() ?? clock.CurrentTime;
|
||||
}
|
||||
|
||||
onNewInput?.Invoke();
|
||||
}
|
||||
|
||||
protected override double RollingDuration => 250;
|
||||
public static void Reset()
|
||||
{
|
||||
timestamps?.Clear();
|
||||
maxTime = int.MinValue;
|
||||
}
|
||||
|
||||
protected override double RollingDuration => SmoothingTime.Value;
|
||||
|
||||
public bool UsesFixedAnchor { get; set; }
|
||||
|
||||
public KeysPerSecondCounter()
|
||||
{
|
||||
timestamps ??= new Queue<DateTime>();
|
||||
timestamps ??= new List<double>();
|
||||
Current.Value = 0;
|
||||
onNewInput += updateCounter;
|
||||
Scheduler.AddOnce(updateCounter);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
private void load(OsuColour colours, GameplayClock clock)
|
||||
{
|
||||
gameplayClock = clock;
|
||||
Colour = colours.BlueLighter;
|
||||
valid.BindValueChanged(e =>
|
||||
DrawableCount.FadeTo(e.NewValue ? 1 : alpha_when_invalid, 1000, Easing.OutQuint));
|
||||
referenceClock = drawableRuleset?.FrameStableClock;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@ -61,21 +102,15 @@ namespace osu.Game.Screens.Play.HUD
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
if (timestamps != null)
|
||||
{
|
||||
if (timestamps.TryPeek(out var earliest) && DateTime.Now - earliest >= refreshSpan)
|
||||
timestamps.Dequeue();
|
||||
}
|
||||
base.Update();
|
||||
|
||||
updateCounter();
|
||||
|
||||
base.Update();
|
||||
}
|
||||
|
||||
private void updateCounter()
|
||||
{
|
||||
valid.Value = timestamps != null;
|
||||
Current.Value = timestamps?.Count ?? 0;
|
||||
valid.Value = timestamps != null && MathHelper.ApproximatelyEquivalent(gameplayClock.CurrentTime, referenceClock.CurrentTime, 500);
|
||||
Current.Value = timestamps?.Count(timestamp => clock.CurrentTime - timestamp is >= 0 and <= invalidation_timeout) ?? 0;
|
||||
}
|
||||
|
||||
protected override IHasText CreateText() => new TextComponent
|
||||
|
@ -11,6 +11,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -65,6 +66,7 @@ namespace osu.Game.Screens.Play
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
{
|
||||
KeysPerSecondCounter.Reset();
|
||||
config.BindWith(OsuSetting.KeyOverlay, configVisibility);
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Scoring.Legacy;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Users;
|
||||
@ -1044,6 +1045,9 @@ namespace osu.Game.Screens.Play
|
||||
musicController.ResetTrackAdjustments();
|
||||
|
||||
fadeOut();
|
||||
|
||||
KeysPerSecondCounter.Reset();
|
||||
|
||||
return base.OnExiting(e);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user