Merge pull request #13330 from nekodex/results-screen-sfx

Add sound effects to the results screen
This commit is contained in:
Dean Herbert 2021-06-10 18:27:17 +09:00 committed by GitHub
commit 4a4a561ca4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 179 additions and 38 deletions

View File

@ -51,7 +51,7 @@
<Reference Include="Java.Interop" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.525.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.604.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.609.0" />
</ItemGroup>
</Project>

View File

@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual.Ranking
}
}
},
new AccuracyCircle(score)
new AccuracyCircle(score, true)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,

View File

@ -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<RankBadge> 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<double> tickPlaybackRate = new Bindable<double>();
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<IApplicableToScoreProcessor>())
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<IApplicableToScoreProcessor>())
rank = mod.AdjustRank(rank, score.Accuracy);
return rank;
}
private double inverseEasing(Easing easing, double targetValue)
{
double test = 0;

View File

@ -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,

View File

@ -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<GlobalAction>
{
/// <summary>
/// Delay before the default applause sound should be played, in order to match the grade display timing in <see cref="AccuracyCircle"/>.
/// </summary>
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()

View File

@ -35,7 +35,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="ppy.osu.Framework" Version="2021.609.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.525.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.604.0" />
<PackageReference Include="Sentry" Version="3.4.0" />
<PackageReference Include="SharpCompress" Version="0.28.2" />
<PackageReference Include="NUnit" Version="3.13.2" />

View File

@ -71,7 +71,7 @@
</ItemGroup>
<ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.609.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.525.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.604.0" />
</ItemGroup>
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
<PropertyGroup>