From ccc5ca5d806b7a798101efba35a5b2de7ff892f6 Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 12 Sep 2025 18:25:08 +0900 Subject: [PATCH] Rework matchmaking cloud SFX --- osu.Game/Configuration/SessionStatics.cs | 8 ---- .../Matchmaking/MatchmakingCloud.cs | 46 ++++++++++--------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/osu.Game/Configuration/SessionStatics.cs b/osu.Game/Configuration/SessionStatics.cs index 0c0b2a989d..59e107a23e 100644 --- a/osu.Game/Configuration/SessionStatics.cs +++ b/osu.Game/Configuration/SessionStatics.cs @@ -8,7 +8,6 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Scoring; -using osu.Game.Screens.OnlinePlay.Matchmaking; using osu.Game.Screens.Play.HUD; using osu.Game.Skinning; using osu.Game.Users; @@ -29,7 +28,6 @@ namespace osu.Game.Configuration SetDefault(Static.LastHoverSoundPlaybackTime, (double?)null); SetDefault(Static.LastModSelectPanelSamplePlaybackTime, (double?)null); SetDefault(Static.LastRankChangeSamplePlaybackTime, (double?)null); - SetDefault(Static.LastMatchmakingCloudSamplePlaybackTime, (double?)null); SetDefault(Static.SeasonalBackgrounds, null); SetDefault(Static.TouchInputActive, RuntimeInfo.IsMobile); SetDefault(Static.LastLocalUserScore, null); @@ -83,12 +81,6 @@ namespace osu.Game.Configuration /// LastRankChangeSamplePlaybackTime, - /// - /// The last playback time in milliseconds for the 'user appear' sample in . - /// Used to debounce sample playback to avoid volume saturation from multiple simultaneous playback. - /// - LastMatchmakingCloudSamplePlaybackTime, - /// /// Whether the last positional input received was a touch input. /// Used in touchscreen detection scenarios (). diff --git a/osu.Game/Screens/OnlinePlay/Matchmaking/MatchmakingCloud.cs b/osu.Game/Screens/OnlinePlay/Matchmaking/MatchmakingCloud.cs index d2b2b72f02..3fab5ab207 100644 --- a/osu.Game/Screens/OnlinePlay/Matchmaking/MatchmakingCloud.cs +++ b/osu.Game/Screens/OnlinePlay/Matchmaking/MatchmakingCloud.cs @@ -10,7 +10,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Utils; -using osu.Game.Configuration; using osu.Game.Online.API.Requests.Responses; using osu.Game.Screens.Ranking; using osuTK; @@ -22,6 +21,8 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking private APIUser[] users = []; private Container usersContainer = null!; + private readonly Bindable lastSamplePlayback = new Bindable(); + public APIUser[] Users { get => users; @@ -32,7 +33,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking foreach (var u in usersContainer) u.Delay(RNG.Next(0, 1000)).FadeOut(500).Expire(); - LoadComponentsAsync(users.Select(u => new MovingAvatar(u)), avatars => + LoadComponentsAsync(users.Select(u => new MovingAvatar(u, lastSamplePlayback)), avatars => { if (usersContainer.Count == 0) { @@ -69,24 +70,25 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking private float targetScale; private float targetAlpha; - private Bindable lastSamplePlaybackTime = null!; + private readonly Bindable lastSamplePlayback = new Bindable(); + private const int num_appear_samples = 6; private Sample? playerAppearSample; - public MovingAvatar(APIUser apiUser) + public MovingAvatar(APIUser apiUser, Bindable lastSamplePlayback) : base(apiUser) { RelativePositionAxes = Axes.Both; Scale = new Vector2(2); Origin = Anchor.Centre; + this.lastSamplePlayback.BindTo(lastSamplePlayback); } [BackgroundDependencyLoader] - private void load(AudioManager audio, SessionStatics statics) + private void load(AudioManager audio) { - playerAppearSample = audio.Samples.Get(@"UI/toolbar-hover"); - lastSamplePlaybackTime = statics.GetBindable(Static.LastMatchmakingCloudSamplePlaybackTime); + playerAppearSample = audio.Samples.Get($@"Multiplayer/Matchmaking/Cloud/appear-{RNG.Next(0, num_appear_samples)}"); } protected override void LoadComplete() @@ -103,20 +105,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking Hide(); int appearDelay = RNG.Next(0, 1000); this.Delay(appearDelay).FadeTo(targetAlpha, 2000, Easing.OutQuint); - Scheduler.AddDelayed(() => - { - bool enoughTimeElapsed = !lastSamplePlaybackTime.Value.HasValue || Time.Current - lastSamplePlaybackTime.Value >= OsuGameBase.SAMPLE_DEBOUNCE_TIME; - if (!enoughTimeElapsed) return; - - var chan = playerAppearSample?.GetChannel(); - - if (chan == null) return; - - chan.Frequency.Value = 1f + RNG.NextDouble(0.25f); - chan.Play(); - - lastSamplePlaybackTime.Value = Time.Current; - }, appearDelay); + Scheduler.AddDelayed(playAppearSample, appearDelay); } private void updateParams() @@ -128,6 +117,21 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking Scheduler.AddDelayed(updateParams, RNG.Next(500, 5000)); } + private void playAppearSample() + { + bool enoughTimeElapsed = !lastSamplePlayback.Value.HasValue || Time.Current - lastSamplePlayback.Value >= OsuGameBase.SAMPLE_DEBOUNCE_TIME; + if (!enoughTimeElapsed) return; + + var chan = playerAppearSample?.GetChannel(); + if (chan == null) return; + + chan.Frequency.Value = 0.5f + RNG.NextDouble(1.5f); + chan.Balance.Value = MathF.Cos(angle) * OsuGameBase.SFX_STEREO_STRENGTH; + chan.Play(); + + lastSamplePlayback.Value = Time.Current; + } + protected override void Update() { base.Update();