diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs
index 5874bac7f6..8797f014df 100644
--- a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs
+++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs
@@ -22,22 +22,15 @@ namespace osu.Game.Rulesets.Mania.UI
JudgementText.Font = JudgementText.Font.With(size: 25);
}
- protected override void LoadComplete()
+ protected override double FadeInDuration => 50;
+
+ protected override void ApplyHitAnimations()
{
- base.LoadComplete();
+ JudgementBody.ScaleTo(0.8f);
+ JudgementBody.ScaleTo(1, 250, Easing.OutElastic);
- this.FadeInFromZero(50, Easing.OutQuint);
-
- if (Result.IsHit)
- {
- JudgementBody.ScaleTo(0.8f);
- JudgementBody.ScaleTo(1, 250, Easing.OutElastic);
-
- JudgementBody.Delay(50).ScaleTo(0.75f, 250);
- this.Delay(50).FadeOut(200);
- }
-
- Expire();
+ JudgementBody.Delay(FadeInDuration).ScaleTo(0.75f, 250);
+ this.Delay(FadeInDuration).FadeOut(200);
}
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs
index 2512e74da7..938a2293ba 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs
@@ -5,7 +5,6 @@ using osu.Framework.Graphics;
using osuTK;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables;
-using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
@@ -16,12 +15,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
}
- protected override void LoadComplete()
+ protected override void ApplyHitAnimations()
{
- if (Result.Type != HitResult.Miss)
- JudgementText?.TransformSpacingTo(new Vector2(14, 0), 1800, Easing.OutQuint);
-
- base.LoadComplete();
+ JudgementText?.TransformSpacingTo(new Vector2(14, 0), 1800, Easing.OutQuint);
+ base.ApplyHitAnimations();
}
}
}
diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs
index 90841f11f5..943adaed4b 100644
--- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs
+++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs
@@ -39,12 +39,10 @@ namespace osu.Game.Rulesets.Taiko.UI
}
}
- protected override void LoadComplete()
+ protected override void ApplyHitAnimations()
{
- if (Result.IsHit)
- this.MoveToY(-100, 500);
-
- base.LoadComplete();
+ this.MoveToY(-100, 500);
+ base.ApplyHitAnimations();
}
}
}
diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs
index 0d6e11c649..89db954c36 100644
--- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs
+++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs
@@ -32,6 +32,12 @@ namespace osu.Game.Rulesets.Judgements
protected Container JudgementBody;
protected SpriteText JudgementText;
+ ///
+ /// Duration of initial fade in.
+ /// Default fade out will start immediately after this duration.
+ ///
+ protected virtual double FadeInDuration => 100;
+
///
/// Creates a drawable which visualises a .
///
@@ -65,11 +71,19 @@ namespace osu.Game.Rulesets.Judgements
};
}
+ protected virtual void ApplyHitAnimations()
+ {
+ JudgementBody.ScaleTo(0.9f);
+ JudgementBody.ScaleTo(1, 500, Easing.OutElastic);
+
+ this.Delay(FadeInDuration).FadeOut(400);
+ }
+
protected override void LoadComplete()
{
base.LoadComplete();
- this.FadeInFromZero(100, Easing.OutQuint);
+ this.FadeInFromZero(FadeInDuration, Easing.OutQuint);
switch (Result.Type)
{
@@ -85,10 +99,7 @@ namespace osu.Game.Rulesets.Judgements
this.Delay(600).FadeOut(200);
break;
default:
- JudgementBody.ScaleTo(0.9f);
- JudgementBody.ScaleTo(1, 500, Easing.OutElastic);
-
- this.Delay(100).FadeOut(400);
+ ApplyHitAnimations();
break;
}
diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs
index 2eea6a237c..dded688e80 100644
--- a/osu.Game/Rulesets/Mods/ModDaycore.cs
+++ b/osu.Game/Rulesets/Mods/ModDaycore.cs
@@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mods
public override void ApplyToClock(IAdjustableClock clock)
{
if (clock is IHasPitchAdjust pitchAdjust)
- pitchAdjust.PitchAdjust = 0.75;
+ pitchAdjust.PitchAdjust *= RateAdjust;
else
base.ApplyToClock(clock);
}
diff --git a/osu.Game/Rulesets/Mods/ModDoubleTime.cs b/osu.Game/Rulesets/Mods/ModDoubleTime.cs
index e59654c60d..9ea9eb76bc 100644
--- a/osu.Game/Rulesets/Mods/ModDoubleTime.cs
+++ b/osu.Game/Rulesets/Mods/ModDoubleTime.cs
@@ -2,12 +2,12 @@
// See the LICENCE file in the repository root for full licence text.
using System;
-using osu.Framework.Timing;
+using System.Linq;
using osu.Game.Graphics;
namespace osu.Game.Rulesets.Mods
{
- public abstract class ModDoubleTime : Mod, IApplicableToClock
+ public abstract class ModDoubleTime : ModTimeAdjust, IApplicableToClock
{
public override string Name => "Double Time";
public override string Acronym => "DT";
@@ -15,11 +15,9 @@ namespace osu.Game.Rulesets.Mods
public override ModType Type => ModType.DifficultyIncrease;
public override string Description => "Zoooooooooom...";
public override bool Ranked => true;
- public override Type[] IncompatibleMods => new[] { typeof(ModHalfTime), typeof(ModTimeRamp) };
- public virtual void ApplyToClock(IAdjustableClock clock)
- {
- clock.Rate = 1.5;
- }
+ public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModHalfTime)).ToArray();
+
+ protected override double RateAdjust => 1.5;
}
}
diff --git a/osu.Game/Rulesets/Mods/ModHalfTime.cs b/osu.Game/Rulesets/Mods/ModHalfTime.cs
index 07cceb6f49..fe26c96214 100644
--- a/osu.Game/Rulesets/Mods/ModHalfTime.cs
+++ b/osu.Game/Rulesets/Mods/ModHalfTime.cs
@@ -2,12 +2,12 @@
// See the LICENCE file in the repository root for full licence text.
using System;
-using osu.Framework.Timing;
+using System.Linq;
using osu.Game.Graphics;
namespace osu.Game.Rulesets.Mods
{
- public abstract class ModHalfTime : Mod, IApplicableToClock
+ public abstract class ModHalfTime : ModTimeAdjust, IApplicableToClock
{
public override string Name => "Half Time";
public override string Acronym => "HT";
@@ -15,11 +15,9 @@ namespace osu.Game.Rulesets.Mods
public override ModType Type => ModType.DifficultyReduction;
public override string Description => "Less zoom...";
public override bool Ranked => true;
- public override Type[] IncompatibleMods => new[] { typeof(ModDoubleTime), typeof(ModTimeRamp) };
- public virtual void ApplyToClock(IAdjustableClock clock)
- {
- clock.Rate = 0.75;
- }
+ public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModDoubleTime)).ToArray();
+
+ protected override double RateAdjust => 0.75;
}
}
diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs
index e6bd532f72..a689292ed7 100644
--- a/osu.Game/Rulesets/Mods/ModNightcore.cs
+++ b/osu.Game/Rulesets/Mods/ModNightcore.cs
@@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mods
public override void ApplyToClock(IAdjustableClock clock)
{
if (clock is IHasPitchAdjust pitchAdjust)
- pitchAdjust.PitchAdjust = 1.5;
+ pitchAdjust.PitchAdjust *= RateAdjust;
else
base.ApplyToClock(clock);
}
diff --git a/osu.Game/Rulesets/Mods/ModTimeAdjust.cs b/osu.Game/Rulesets/Mods/ModTimeAdjust.cs
new file mode 100644
index 0000000000..513883f552
--- /dev/null
+++ b/osu.Game/Rulesets/Mods/ModTimeAdjust.cs
@@ -0,0 +1,24 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System;
+using osu.Framework.Audio;
+using osu.Framework.Timing;
+
+namespace osu.Game.Rulesets.Mods
+{
+ public abstract class ModTimeAdjust : Mod
+ {
+ public override Type[] IncompatibleMods => new[] { typeof(ModTimeRamp) };
+
+ protected abstract double RateAdjust { get; }
+
+ public virtual void ApplyToClock(IAdjustableClock clock)
+ {
+ if (clock is IHasTempoAdjust tempo)
+ tempo.TempoAdjust *= RateAdjust;
+ else
+ clock.Rate *= RateAdjust;
+ }
+ }
+}
diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs
index 4a0ed0f9bb..62407907c1 100644
--- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs
+++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs
@@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mods
{
public abstract class ModTimeRamp : Mod
{
- public override Type[] IncompatibleMods => new[] { typeof(ModDoubleTime), typeof(ModHalfTime) };
+ public override Type[] IncompatibleMods => new[] { typeof(ModTimeAdjust) };
protected abstract double FinalRateAdjustment { get; }
}
@@ -29,8 +29,6 @@ namespace osu.Game.Rulesets.Mods
private IAdjustableClock clock;
- private IHasPitchAdjust pitchAdjust;
-
///
/// The point in the beatmap at which the final ramping rate should be reached.
///
@@ -39,10 +37,11 @@ namespace osu.Game.Rulesets.Mods
public virtual void ApplyToClock(IAdjustableClock clock)
{
this.clock = clock;
- pitchAdjust = (IHasPitchAdjust)clock;
- // for preview purposes
- pitchAdjust.PitchAdjust = 1.0 + FinalRateAdjustment;
+ lastAdjust = 1;
+
+ // for preview purposes. during gameplay, Update will overwrite this setting.
+ applyAdjustment(1);
}
public virtual void ApplyToBeatmap(Beatmap beatmap)
@@ -55,10 +54,36 @@ namespace osu.Game.Rulesets.Mods
public virtual void Update(Playfield playfield)
{
- var absRate = Math.Abs(FinalRateAdjustment);
- var adjustment = MathHelper.Clamp(absRate * ((clock.CurrentTime - beginRampTime) / finalRateTime), 0, absRate);
+ applyAdjustment((clock.CurrentTime - beginRampTime) / finalRateTime);
+ }
- pitchAdjust.PitchAdjust = 1 + Math.Sign(FinalRateAdjustment) * adjustment;
+ private double lastAdjust = 1;
+
+ ///
+ /// Adjust the rate along the specified ramp
+ ///
+ /// The amount of adjustment to apply (from 0..1).
+ private void applyAdjustment(double amount)
+ {
+ double adjust = 1 + (Math.Sign(FinalRateAdjustment) * MathHelper.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment));
+
+ switch (clock)
+ {
+ case IHasPitchAdjust pitch:
+ pitch.PitchAdjust /= lastAdjust;
+ pitch.PitchAdjust *= adjust;
+ break;
+ case IHasTempoAdjust tempo:
+ tempo.TempoAdjust /= lastAdjust;
+ tempo.TempoAdjust *= adjust;
+ break;
+ default:
+ clock.Rate /= lastAdjust;
+ clock.Rate *= adjust;
+ break;
+ }
+
+ lastAdjust = adjust;
}
}
}
diff --git a/osu.Game/Rulesets/Mods/ModWindDown.cs b/osu.Game/Rulesets/Mods/ModWindDown.cs
index 646c5c64e4..174070eb85 100644
--- a/osu.Game/Rulesets/Mods/ModWindDown.cs
+++ b/osu.Game/Rulesets/Mods/ModWindDown.cs
@@ -1,6 +1,8 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
+using System.Linq;
using osu.Game.Graphics;
using osu.Game.Rulesets.Objects;
@@ -14,6 +16,9 @@ namespace osu.Game.Rulesets.Mods
public override string Description => "Sloooow doooown...";
public override FontAwesome Icon => FontAwesome.fa_chevron_circle_down;
public override double ScoreMultiplier => 1.0;
+
protected override double FinalRateAdjustment => -0.25;
+
+ public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindUp)).ToArray();
}
}
diff --git a/osu.Game/Rulesets/Mods/ModWindUp.cs b/osu.Game/Rulesets/Mods/ModWindUp.cs
index 9050b5591a..bf9af8a51d 100644
--- a/osu.Game/Rulesets/Mods/ModWindUp.cs
+++ b/osu.Game/Rulesets/Mods/ModWindUp.cs
@@ -1,6 +1,8 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
+using System.Linq;
using osu.Game.Graphics;
using osu.Game.Rulesets.Objects;
@@ -14,6 +16,9 @@ namespace osu.Game.Rulesets.Mods
public override string Description => "Can you keep up?";
public override FontAwesome Icon => FontAwesome.fa_chevron_circle_up;
public override double ScoreMultiplier => 1.0;
+
protected override double FinalRateAdjustment => 0.5;
+
+ public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindDown)).ToArray();
}
-}
\ No newline at end of file
+}
diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs
index 594df63420..3c2cec1d94 100644
--- a/osu.Game/Screens/Play/GameplayClockContainer.cs
+++ b/osu.Game/Screens/Play/GameplayClockContainer.cs
@@ -6,6 +6,7 @@ using System.Linq;
using System.Threading.Tasks;
using osu.Framework;
using osu.Framework.Allocation;
+using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@@ -141,11 +142,15 @@ namespace osu.Game.Screens.Play
{
if (sourceClock == null) return;
- sourceClock.Rate = 1;
+ sourceClock.ResetSpeedAdjustments();
+
+ if (sourceClock is IHasTempoAdjust tempo)
+ tempo.TempoAdjust = UserPlaybackRate.Value;
+ else
+ sourceClock.Rate = UserPlaybackRate.Value;
+
foreach (var mod in beatmap.Mods.Value.OfType())
mod.ApplyToClock(sourceClock);
-
- sourceClock.Rate *= UserPlaybackRate.Value;
}
}
}
diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs
index 14b4af1e7d..3b3adb4d76 100644
--- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs
+++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs
@@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual
base.Update();
// note that this will override any mod rate application
- Beatmap.Value.Track.Rate = Clock.Rate;
+ Beatmap.Value.Track.TempoAdjust = Clock.Rate;
}
}
}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 2e945c212d..e2c96effb6 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index b25e2a8bb2..288630d1ec 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -105,8 +105,8 @@
-
-
+
+