1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-12 21:02:54 +08:00

Interpolate speed change using IUpdatableByPlayfield

This commit is contained in:
Henry Lin 2022-03-03 12:02:39 +08:00
parent 51258dbab4
commit 09254407fe

View File

@ -1,25 +1,24 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Audio; using osu.Framework.Audio;
using osu.Framework.Audio.Track; using osu.Framework.Audio.Track;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Audio;
using osu.Framework.Utils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play; using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Mods namespace osu.Game.Rulesets.Mods
{ {
public class ModAdaptiveSpeed : Mod, IApplicableToRate, IApplicableToDrawableHitObject, IApplicableToBeatmap, IApplicableToHUD public class ModAdaptiveSpeed : Mod, IApplicableToRate, IApplicableToDrawableHitObject, IApplicableToBeatmap, IUpdatableByPlayfield
{ {
// use a wider range so there's still room for adjustment when the initial rate is extreme // use a wider range so there's still room for adjustment when the initial rate is extreme
private const double fastest_rate = 2.5f; private const double fastest_rate = 2.5f;
@ -62,12 +61,11 @@ namespace osu.Game.Rulesets.Mods
public BindableNumber<double> SpeedChange { get; } = new BindableDouble public BindableNumber<double> SpeedChange { get; } = new BindableDouble
{ {
Default = 1, Default = 1,
Value = 1, Value = 1
Precision = 0.01
}; };
private ITrack track; private ITrack track;
private HUDOverlay overlay; private double targetRate = 1d;
private readonly List<double> recentRates = Enumerable.Repeat(1d, average_count).ToList(); private readonly List<double> recentRates = Enumerable.Repeat(1d, average_count).ToList();
@ -81,16 +79,14 @@ namespace osu.Game.Rulesets.Mods
public ModAdaptiveSpeed() public ModAdaptiveSpeed()
{ {
InitialRate.BindValueChanged(val => SpeedChange.Value = val.NewValue); InitialRate.BindValueChanged(val =>
{
SpeedChange.Value = val.NewValue;
targetRate = val.NewValue;
});
AdjustPitch.BindValueChanged(applyPitchAdjustment); AdjustPitch.BindValueChanged(applyPitchAdjustment);
} }
public void ApplyToHUD(HUDOverlay overlay)
{
// this is only used to transform the SpeedChange bindable
this.overlay = overlay;
}
public void ApplyToTrack(ITrack track) public void ApplyToTrack(ITrack track)
{ {
this.track = track; this.track = track;
@ -106,6 +102,11 @@ namespace osu.Game.Rulesets.Mods
sample.AddAdjustment(AdjustableProperty.Frequency, SpeedChange); sample.AddAdjustment(AdjustableProperty.Frequency, SpeedChange);
} }
public void Update(Playfield playfield)
{
SpeedChange.Value = Interpolation.DampContinuously(SpeedChange.Value, targetRate, 50, playfield.Clock.ElapsedFrameTime);
}
public double ApplyToRate(double time, double rate = 1) => rate * InitialRate.Value; public double ApplyToRate(double time, double rate = 1) => rate * InitialRate.Value;
private void applyPitchAdjustment(ValueChangedEvent<bool> adjustPitchSetting) private void applyPitchAdjustment(ValueChangedEvent<bool> adjustPitchSetting)
@ -132,7 +133,7 @@ namespace osu.Game.Rulesets.Mods
dequeuedRates.Add(result.HitObject, recentRates[0]); dequeuedRates.Add(result.HitObject, recentRates[0]);
recentRates.RemoveAt(0); recentRates.RemoveAt(0);
overlay.TransformBindableTo(SpeedChange, recentRates.Average(), 100); targetRate = recentRates.Average();
}; };
drawable.OnRevertResult += (o, result) => drawable.OnRevertResult += (o, result) =>
{ {
@ -143,7 +144,7 @@ namespace osu.Game.Rulesets.Mods
recentRates.RemoveAt(recentRates.Count - 1); recentRates.RemoveAt(recentRates.Count - 1);
dequeuedRates.Remove(result.HitObject); dequeuedRates.Remove(result.HitObject);
overlay.TransformBindableTo(SpeedChange, recentRates.Average(), 100); targetRate = recentRates.Average();
}; };
} }