diff --git a/osu.Android.props b/osu.Android.props
index cfa3bc836f..0d3fafd19f 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -51,7 +51,7 @@
-
+
diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
index f305b7255e..a5e2f02f31 100644
--- a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
+++ b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
@@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual.Ranking
}
}
},
- new AccuracyCircle(score)
+ new AccuracyCircle(score, true)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
index c70b4dd35b..635be60549 100644
--- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
+++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
@@ -5,14 +5,18 @@ using System;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Audio;
+using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
+using osu.Framework.Platform;
using osu.Framework.Utils;
+using osu.Game.Audio;
using osu.Game.Graphics;
using osu.Game.Rulesets.Mods;
using osu.Game.Scoring;
+using osu.Game.Skinning;
using osuTK;
namespace osu.Game.Screens.Ranking.Expanded.Accuracy
@@ -79,13 +83,28 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
private Container badges;
private RankText rankText;
- public AccuracyCircle(ScoreInfo score)
+ private PoolableSkinnableSample scoreTickSound;
+ private PoolableSkinnableSample badgeTickSound;
+ private PoolableSkinnableSample badgeMaxSound;
+ private PoolableSkinnableSample swooshUpSound;
+ private PoolableSkinnableSample rankImpactSound;
+ private PoolableSkinnableSample rankApplauseSound;
+
+ private readonly Bindable tickPlaybackRate = new Bindable();
+
+ private double lastTickPlaybackTime;
+ private bool isTicking;
+
+ private readonly bool withFlair;
+
+ public AccuracyCircle(ScoreInfo score, bool withFlair = false)
{
this.score = score;
+ this.withFlair = withFlair;
}
[BackgroundDependencyLoader]
- private void load(AudioManager audio)
+ private void load(GameHost host)
{
InternalChildren = new Drawable[]
{
@@ -204,14 +223,19 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
},
rankText = new RankText(score.Rank)
};
- }
- private ScoreRank getRank(ScoreRank rank)
- {
- foreach (var mod in score.Mods.OfType())
- rank = mod.AdjustRank(rank, score.Accuracy);
-
- return rank;
+ if (withFlair)
+ {
+ AddRangeInternal(new Drawable[]
+ {
+ rankImpactSound = new PoolableSkinnableSample(new SampleInfo(impactSampleName)),
+ rankApplauseSound = new PoolableSkinnableSample(new SampleInfo(@"applause", applauseSampleName)),
+ scoreTickSound = new PoolableSkinnableSample(new SampleInfo(@"Results/score-tick")),
+ badgeTickSound = new PoolableSkinnableSample(new SampleInfo(@"Results/badge-dink")),
+ badgeMaxSound = new PoolableSkinnableSample(new SampleInfo(@"Results/badge-dink-max")),
+ swooshUpSound = new PoolableSkinnableSample(new SampleInfo(@"Results/swoosh-up")),
+ });
+ }
}
protected override void LoadComplete()
@@ -220,33 +244,170 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
this.ScaleTo(0).Then().ScaleTo(1, APPEAR_DURATION, Easing.OutQuint);
- using (BeginDelayedSequence(RANK_CIRCLE_TRANSFORM_DELAY, true))
+ if (withFlair)
+ {
+ const double swoosh_pre_delay = 443f;
+ const double swoosh_volume = 0.4f;
+
+ this.Delay(swoosh_pre_delay).Schedule(() =>
+ {
+ swooshUpSound.VolumeTo(swoosh_volume);
+ swooshUpSound.Play();
+ });
+ }
+
+ using (BeginDelayedSequence(RANK_CIRCLE_TRANSFORM_DELAY))
innerMask.FillTo(1f, RANK_CIRCLE_TRANSFORM_DURATION, ACCURACY_TRANSFORM_EASING);
- using (BeginDelayedSequence(ACCURACY_TRANSFORM_DELAY, true))
+ using (BeginDelayedSequence(ACCURACY_TRANSFORM_DELAY))
{
double targetAccuracy = score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH ? 1 : Math.Min(1 - virtual_ss_percentage, score.Accuracy);
accuracyCircle.FillTo(targetAccuracy, ACCURACY_TRANSFORM_DURATION, ACCURACY_TRANSFORM_EASING);
+ if (withFlair)
+ {
+ Schedule(() =>
+ {
+ const double score_tick_debounce_rate_start = 18f;
+ const double score_tick_debounce_rate_end = 300f;
+ const double score_tick_volume_start = 0.6f;
+ const double score_tick_volume_end = 1.0f;
+
+ this.TransformBindableTo(tickPlaybackRate, score_tick_debounce_rate_start);
+ this.TransformBindableTo(tickPlaybackRate, score_tick_debounce_rate_end, ACCURACY_TRANSFORM_DURATION, Easing.OutSine);
+
+ scoreTickSound.FrequencyTo(1 + targetAccuracy, ACCURACY_TRANSFORM_DURATION, Easing.OutSine);
+ scoreTickSound.VolumeTo(score_tick_volume_start).Then().VolumeTo(score_tick_volume_end, ACCURACY_TRANSFORM_DURATION, Easing.OutSine);
+
+ isTicking = true;
+ });
+ }
+
+ int badgeNum = 0;
+
foreach (var badge in badges)
{
if (badge.Accuracy > score.Accuracy)
continue;
- using (BeginDelayedSequence(inverseEasing(ACCURACY_TRANSFORM_EASING, Math.Min(1 - virtual_ss_percentage, badge.Accuracy) / targetAccuracy) * ACCURACY_TRANSFORM_DURATION, true))
+ using (BeginDelayedSequence(inverseEasing(ACCURACY_TRANSFORM_EASING, Math.Min(1 - virtual_ss_percentage, badge.Accuracy) / targetAccuracy) * ACCURACY_TRANSFORM_DURATION))
{
badge.Appear();
+
+ if (withFlair)
+ {
+ Schedule(() =>
+ {
+ var dink = badgeNum < badges.Count - 1 ? badgeTickSound : badgeMaxSound;
+
+ dink.FrequencyTo(1 + badgeNum++ * 0.05);
+ dink.Play();
+ });
+ }
}
}
- using (BeginDelayedSequence(TEXT_APPEAR_DELAY, true))
+ using (BeginDelayedSequence(TEXT_APPEAR_DELAY))
{
rankText.Appear();
+
+ if (!withFlair) return;
+
+ Schedule(() =>
+ {
+ isTicking = false;
+ rankImpactSound.Play();
+ });
+
+ const double applause_pre_delay = 545f;
+ const double applause_volume = 0.8f;
+
+ using (BeginDelayedSequence(applause_pre_delay))
+ {
+ Schedule(() =>
+ {
+ rankApplauseSound.VolumeTo(applause_volume);
+ rankApplauseSound.Play();
+ });
+ }
}
}
}
+ protected override void Update()
+ {
+ base.Update();
+
+ if (isTicking && Clock.CurrentTime - lastTickPlaybackTime >= tickPlaybackRate.Value)
+ {
+ scoreTickSound?.Play();
+ lastTickPlaybackTime = Clock.CurrentTime;
+ }
+ }
+
+ private string applauseSampleName
+ {
+ get
+ {
+ switch (score.Rank)
+ {
+ default:
+ case ScoreRank.D:
+ return @"Results/applause-d";
+
+ case ScoreRank.C:
+ return @"Results/applause-c";
+
+ case ScoreRank.B:
+ return @"Results/applause-b";
+
+ case ScoreRank.A:
+ return @"Results/applause-a";
+
+ case ScoreRank.S:
+ case ScoreRank.SH:
+ case ScoreRank.X:
+ case ScoreRank.XH:
+ return @"Results/applause-s";
+ }
+ }
+ }
+
+ private string impactSampleName
+ {
+ get
+ {
+ switch (score.Rank)
+ {
+ default:
+ case ScoreRank.D:
+ return @"Results/rank-impact-fail-d";
+
+ case ScoreRank.C:
+ case ScoreRank.B:
+ return @"Results/rank-impact-fail";
+
+ case ScoreRank.A:
+ case ScoreRank.S:
+ case ScoreRank.SH:
+ return @"Results/rank-impact-pass";
+
+ case ScoreRank.X:
+ case ScoreRank.XH:
+ return @"Results/rank-impact-pass-ss";
+ }
+ }
+ }
+
+ private ScoreRank getRank(ScoreRank rank)
+ {
+ foreach (var mod in score.Mods.OfType())
+ rank = mod.AdjustRank(rank, score.Accuracy);
+
+ return rank;
+ }
+
private double inverseEasing(Easing easing, double targetValue)
{
double test = 0;
diff --git a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs
index f65aed3037..0a10eee644 100644
--- a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs
+++ b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs
@@ -122,7 +122,7 @@ namespace osu.Game.Screens.Ranking.Expanded
Margin = new MarginPadding { Top = 40 },
RelativeSizeAxes = Axes.X,
Height = 230,
- Child = new AccuracyCircle(score)
+ Child = new AccuracyCircle(score, withFlair)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs
index dd1ca379fb..b458d7c17f 100644
--- a/osu.Game/Screens/Ranking/ResultsScreen.cs
+++ b/osu.Game/Screens/Ranking/ResultsScreen.cs
@@ -12,7 +12,6 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Bindings;
using osu.Framework.Screens;
-using osu.Game.Audio;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
@@ -20,20 +19,13 @@ using osu.Game.Input.Bindings;
using osu.Game.Online.API;
using osu.Game.Scoring;
using osu.Game.Screens.Play;
-using osu.Game.Screens.Ranking.Expanded.Accuracy;
using osu.Game.Screens.Ranking.Statistics;
-using osu.Game.Skinning;
using osuTK;
namespace osu.Game.Screens.Ranking
{
public abstract class ResultsScreen : ScreenWithBeatmapBackground, IKeyBindingHandler
{
- ///
- /// Delay before the default applause sound should be played, in order to match the grade display timing in .
- ///
- public const double APPLAUSE_DELAY = AccuracyCircle.ACCURACY_TRANSFORM_DELAY + AccuracyCircle.TEXT_APPEAR_DELAY + ScorePanel.RESIZE_DURATION + ScorePanel.TOP_LAYER_EXPAND_DELAY - 1440;
-
protected const float BACKGROUND_BLUR = 20;
private static readonly float screen_height = 768 - TwoLayerButton.SIZE_EXTENDED.Y;
@@ -64,8 +56,6 @@ namespace osu.Game.Screens.Ranking
private readonly bool allowRetry;
private readonly bool allowWatchingReplay;
- private SkinnableSound applauseSound;
-
protected ResultsScreen(ScoreInfo score, bool allowRetry, bool allowWatchingReplay = true)
{
Score = score;
@@ -156,13 +146,6 @@ namespace osu.Game.Screens.Ranking
bool shouldFlair = player != null && Score.Mods.All(m => m.UserPlayable);
ScorePanelList.AddScore(Score, shouldFlair);
-
- if (shouldFlair)
- {
- AddInternal(applauseSound = Score.Rank >= ScoreRank.A
- ? new SkinnableSound(new SampleInfo("Results/rankpass", "applause"))
- : new SkinnableSound(new SampleInfo("Results/rankfail")));
- }
}
if (allowWatchingReplay)
@@ -200,9 +183,6 @@ namespace osu.Game.Screens.Ranking
api.Queue(req);
statisticsPanel.State.BindValueChanged(onStatisticsStateChanged, true);
-
- using (BeginDelayedSequence(APPLAUSE_DELAY))
- Schedule(() => applauseSound?.Play());
}
protected override void Update()
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index be10764c6a..2ee8ed527f 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -35,7 +35,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index 751f60912a..7832aaaf2d 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -71,7 +71,7 @@
-
+