1
0
mirror of https://github.com/ppy/osu.git synced 2026-06-05 12:03:46 +08:00

Improve SFX playback behaviour of rapid kiai/star fountain activations

This commit is contained in:
Jamie Taylor
2025-03-14 20:47:11 +09:00
Unverified
parent c9b3eeff9b
commit d5074bb30f
3 changed files with 81 additions and 11 deletions
+4 -6
View File
@@ -6,9 +6,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Platform;
using osu.Framework.Utils;
using osu.Game.Audio;
using osu.Game.Graphics.Containers;
using osu.Game.Skinning;
namespace osu.Game.Screens.Menu
{
@@ -20,7 +18,7 @@ namespace osu.Game.Screens.Menu
[Resolved]
private GameHost host { get; set; } = null!;
private SkinnableSound? sample;
private StarFountainSfx sfx = null!;
[BackgroundDependencyLoader]
private void load()
@@ -41,7 +39,7 @@ namespace osu.Game.Screens.Menu
Origin = Anchor.BottomRight,
X = -250,
},
sample = new SkinnableSound(new SampleInfo("Gameplay/fountain-shoot"))
sfx = new StarFountainSfx()
};
}
@@ -83,9 +81,9 @@ namespace osu.Game.Screens.Menu
break;
}
// Don't play SFX when game is in background as it can be a bit noisy.
// Don't play SFX when game is in background, as it can be a bit noisy.
if (host.IsActive.Value)
sample?.Play();
sfx.Trigger();
}
}
}
+74
View File
@@ -0,0 +1,74 @@
// 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.
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Threading;
using osu.Game.Audio;
using osu.Game.Skinning;
namespace osu.Game.Screens.Menu
{
public partial class StarFountainSfx : Container
{
private const int shoot_retrigger_delay = 500;
private const int loop_fade_duration = 500;
private double? lastPlayback;
private SkinnableSound? shootSample;
private PausableSkinnableSound? loopSample;
private ScheduledDelegate? loopFadeDelegate;
private ScheduledDelegate? loopStopDelegate;
public void Trigger()
{
loopFadeDelegate?.Cancel();
loopStopDelegate?.Cancel();
// Only play 'shootSample' if enough time has passed since last `Trigger()` call.
if (lastPlayback == null || Time.Current - lastPlayback > shoot_retrigger_delay)
{
loopSample?.Stop();
shootSample?.Play();
lastPlayback = Time.Current;
return;
}
if (loopSample == null) return;
// Only call `Play()` if `loopSample` is not already playing, to prevent restarting the sample each time.
if (!loopSample.RequestedPlaying)
{
loopSample.Volume.Value = 1f;
loopSample.Play();
}
// Schedule a volume fadeout, followed by a `Stop()`.
loopFadeDelegate = Scheduler.AddDelayed(() =>
{
this.TransformBindableTo(loopSample.Volume, 0, loop_fade_duration);
loopStopDelegate = Scheduler.AddDelayed(() =>
{
loopSample?.Stop();
}, loop_fade_duration);
}, shoot_retrigger_delay);
lastPlayback = Time.Current;
}
[BackgroundDependencyLoader]
private void load()
{
Children = new Drawable[]
{
shootSample = new SkinnableSound(new SampleInfo("Gameplay/fountain-shoot")),
loopSample = new PausableSkinnableSound(new SampleInfo("Gameplay/fountain-loop")) { Looping = true },
};
}
}
}
@@ -6,11 +6,9 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Utils;
using osu.Game.Audio;
using osu.Game.Configuration;
using osu.Game.Graphics.Containers;
using osu.Game.Screens.Menu;
using osu.Game.Skinning;
namespace osu.Game.Screens.Play
{
@@ -21,7 +19,7 @@ namespace osu.Game.Screens.Play
private Bindable<bool> kiaiStarFountains = null!;
private SkinnableSound? sample;
private StarFountainSfx sfx = null!;
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
@@ -44,7 +42,7 @@ namespace osu.Game.Screens.Play
Origin = Anchor.BottomRight,
X = -75,
},
sample = new SkinnableSound(new SampleInfo("Gameplay/fountain-shoot"))
sfx = new StarFountainSfx(),
};
}
@@ -72,7 +70,7 @@ namespace osu.Game.Screens.Play
leftFountain.Shoot(1);
rightFountain.Shoot(-1);
sample?.Play();
sfx.Trigger();
}
public partial class GameplayStarFountain : StarFountain