mirror of
https://github.com/ppy/osu.git
synced 2026-05-21 18:10:40 +08:00
Ranked Play: Add countdown timer to all screens (#36930)
There's been [some feedback](https://discord.com/channels/90072389919997952/1476979671886205060/1477868178775216148) that there's no timer during some screens. Personally I feel like some screens shouldn't require it, but I get it. The results screen is going to be the most controversial one, where I've decided to shift the content down a bit - it would otherwise overlap with the progress bar. Another option is to make the progress bar shorter, but I feel like that makes things inconsistent. <img width="1922" height="1035" alt="image" src="https://github.com/user-attachments/assets/ec4ba01e-bb13-45ff-8a1b-b39d7765c1f4" /> Regarding implementation, I'm not entirely sure on it being added to every subscreen via `RankedPlaySubScreen` instead of just a single component at a top level. I did it this way because the colour scheme seems annoying to change without recreating the entire component (or otherwise all of its children) anyway.
This commit is contained in:
committed by
GitHub
Unverified
parent
ce571e328d
commit
4c0657f4ca
+65
-12
@@ -3,7 +3,6 @@
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
@@ -21,24 +20,20 @@ using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Components
|
||||
{
|
||||
public partial class RankedPlayStageDisplay : CompositeDrawable
|
||||
public partial class RankedPlayStageDisplay : VisibilityContainer
|
||||
{
|
||||
public required LocalisableString Heading { get; init; }
|
||||
|
||||
public required LocalisableString Caption { get; init; }
|
||||
|
||||
public Color4? CaptionColour { get; init; }
|
||||
|
||||
[Resolved]
|
||||
private MultiplayerClient client { get; set; } = null!;
|
||||
|
||||
private readonly RankedPlayColourScheme colourScheme;
|
||||
|
||||
private Drawable headingTextBackground = null!;
|
||||
private OsuSpriteText headingText = null!;
|
||||
private Drawable progressBar = null!;
|
||||
private OsuSpriteText progressText = null!;
|
||||
|
||||
private OsuSpriteText? headingText;
|
||||
private OsuSpriteText? captionText;
|
||||
|
||||
private DateTimeOffset countdownStartTime;
|
||||
private DateTimeOffset countdownEndTime;
|
||||
|
||||
@@ -50,7 +45,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Components
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
private void load()
|
||||
{
|
||||
const float phase_text_background_height = 55;
|
||||
Vector2 progressBarSize = new Vector2(300, 25);
|
||||
@@ -162,7 +157,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Components
|
||||
}
|
||||
]
|
||||
},
|
||||
new OsuSpriteText
|
||||
captionText = new OsuSpriteText
|
||||
{
|
||||
Margin = new MarginPadding
|
||||
{
|
||||
@@ -176,6 +171,54 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Components
|
||||
};
|
||||
}
|
||||
|
||||
private LocalisableString heading;
|
||||
|
||||
/// <summary>
|
||||
/// Heading text to be displayed indicating the purpose of the current stage.
|
||||
/// </summary>
|
||||
public LocalisableString Heading
|
||||
{
|
||||
get => heading;
|
||||
set
|
||||
{
|
||||
heading = value;
|
||||
if (headingText != null)
|
||||
headingText.Text = value;
|
||||
}
|
||||
}
|
||||
|
||||
private LocalisableString caption;
|
||||
|
||||
/// <summary>
|
||||
/// Subtitle text to be displayed indicating the action a user should take in the current stage.
|
||||
/// </summary>
|
||||
public LocalisableString Caption
|
||||
{
|
||||
get => caption;
|
||||
set
|
||||
{
|
||||
caption = value;
|
||||
if (captionText != null)
|
||||
captionText.Text = value;
|
||||
}
|
||||
}
|
||||
|
||||
private Color4? captionColour;
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the default caption colour from the colour scheme with a custom one.
|
||||
/// </summary>
|
||||
public Color4? CaptionColour
|
||||
{
|
||||
get => captionColour;
|
||||
set
|
||||
{
|
||||
captionColour = value;
|
||||
if (captionText != null)
|
||||
captionText.Colour = value ?? colourScheme.Primary;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
@@ -194,7 +237,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Components
|
||||
{
|
||||
base.Update();
|
||||
|
||||
headingTextBackground.Width = headingText.DrawWidth + 80;
|
||||
headingTextBackground.Width = headingText!.DrawWidth + 80;
|
||||
|
||||
TimeSpan duration = countdownEndTime - countdownStartTime;
|
||||
TimeSpan remaining = countdownEndTime - DateTimeOffset.Now;
|
||||
@@ -226,6 +269,16 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Components
|
||||
countdownEndTime = DateTimeOffset.Now;
|
||||
});
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
this.FadeIn();
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
this.FadeOut();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
@@ -11,6 +11,7 @@ using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
@@ -33,6 +34,9 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
|
||||
public CardFlow CenterRow { get; private set; } = null!;
|
||||
|
||||
protected override LocalisableString StageHeading => "Discard Phase";
|
||||
protected override LocalisableString StageCaption => "Replace cards from your hand";
|
||||
|
||||
private PlayerHandOfCards playerHand = null!;
|
||||
private ShearedButton discardButton = null!;
|
||||
private OsuTextFlowContainer explainer = null!;
|
||||
@@ -57,6 +61,11 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
private DateTimeOffset stageEndTime;
|
||||
private TimeSpan stageDuration;
|
||||
|
||||
public DiscardScreen()
|
||||
{
|
||||
StageDisplay.CaptionColour = Color4.White;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
@@ -72,13 +81,6 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
new RankedPlayStageDisplay(RankedPlayColourScheme.Blue)
|
||||
{
|
||||
Heading = "Discard Phase",
|
||||
Caption = "Replace cards from your hand",
|
||||
CaptionColour = Color4.White,
|
||||
Margin = new MarginPadding { Top = 60 },
|
||||
},
|
||||
discardButton = new ShearedButton
|
||||
{
|
||||
Name = "Discard Button",
|
||||
|
||||
@@ -7,6 +7,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
@@ -24,6 +25,9 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
/// </summary>
|
||||
public Action<bool>? ExitRequested { get; init; }
|
||||
|
||||
protected override LocalisableString StageHeading => "Results";
|
||||
protected override LocalisableString StageCaption => string.Empty;
|
||||
|
||||
[Resolved]
|
||||
private RankedPlayMatchInfo matchInfo { get; set; } = null!;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osuTK;
|
||||
@@ -12,6 +13,9 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
{
|
||||
public partial class GameplayScreen : RankedPlaySubScreen
|
||||
{
|
||||
protected override LocalisableString StageHeading => "Gameplay";
|
||||
protected override LocalisableString StageCaption => string.Empty;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics.Containers;
|
||||
@@ -24,6 +25,9 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
{
|
||||
public override bool ShowBeatmapBackground => true;
|
||||
|
||||
protected override LocalisableString StageHeading => "Gameplay";
|
||||
protected override LocalisableString StageCaption => string.Empty;
|
||||
|
||||
[Cached(typeof(IBindable<SongSelect.BeatmapSetLookupResult?>))]
|
||||
private readonly Bindable<SongSelect.BeatmapSetLookupResult?> lastLookupResult = new Bindable<SongSelect.BeatmapSetLookupResult?>();
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
@@ -20,9 +21,13 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Intro
|
||||
{
|
||||
public partial class IntroScreen : RankedPlaySubScreen
|
||||
{
|
||||
protected override LocalisableString StageHeading => string.Empty;
|
||||
protected override LocalisableString StageCaption => string.Empty;
|
||||
|
||||
public IntroScreen()
|
||||
{
|
||||
CornerPieceVisibility.Value = Visibility.Hidden;
|
||||
CountdownVisibility.Value = Visibility.Hidden;
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
|
||||
@@ -8,6 +8,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
|
||||
@@ -22,6 +23,11 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
{
|
||||
public CardFlow CenterRow { get; private set; } = null!;
|
||||
|
||||
protected override LocalisableString StageHeading => "Pick Phase";
|
||||
protected override LocalisableString StageCaption => "Waiting for your opponent...";
|
||||
|
||||
protected override RankedPlayColourScheme ColourScheme => RankedPlayColourScheme.Red;
|
||||
|
||||
private PlayerHandOfCards playerHand = null!;
|
||||
private OpponentHandOfCards opponentHand = null!;
|
||||
|
||||
@@ -46,12 +52,6 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
new RankedPlayStageDisplay(RankedPlayColourScheme.Red)
|
||||
{
|
||||
Heading = "Pick Phase",
|
||||
Caption = "Waiting for your opponent...",
|
||||
Margin = new MarginPadding { Top = 60 },
|
||||
},
|
||||
];
|
||||
|
||||
CenterColumn.Children =
|
||||
|
||||
@@ -8,6 +8,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
@@ -27,6 +28,9 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
|
||||
public CardFlow CenterRow { get; private set; } = null!;
|
||||
|
||||
protected override LocalisableString StageHeading => "Pick Phase";
|
||||
protected override LocalisableString StageCaption => "It's your turn to play a card!";
|
||||
|
||||
private PlayerHandOfCards playerHand = null!;
|
||||
private OpponentHandOfCards opponentHand = null!;
|
||||
|
||||
@@ -65,12 +69,6 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
new RankedPlayStageDisplay(RankedPlayColourScheme.Blue)
|
||||
{
|
||||
Heading = "Pick Phase",
|
||||
Caption = "It's your turn to play a card!",
|
||||
Margin = new MarginPadding { Top = 60 },
|
||||
},
|
||||
];
|
||||
|
||||
CenterColumn.Children =
|
||||
|
||||
@@ -7,6 +7,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Components;
|
||||
using osuTK;
|
||||
@@ -18,19 +19,34 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
public const float CENTERED_CARD_SCALE = 1.2f;
|
||||
|
||||
public readonly Bindable<Visibility> CornerPieceVisibility = new Bindable<Visibility>(Visibility.Visible);
|
||||
protected readonly Bindable<Visibility> CountdownVisibility = new Bindable<Visibility>(Visibility.Visible);
|
||||
|
||||
public virtual bool ShowBeatmapBackground => false;
|
||||
|
||||
/// <summary>
|
||||
/// Heading text to be displayed indicating the purpose of the current stage.
|
||||
/// </summary>
|
||||
protected abstract LocalisableString StageHeading { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Subtitle text to be displayed indicating the action a user should take in the current stage.
|
||||
/// </summary>
|
||||
protected abstract LocalisableString StageCaption { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The colour scheme commonly used for components of this screen.
|
||||
/// </summary>
|
||||
protected virtual RankedPlayColourScheme ColourScheme => RankedPlayColourScheme.Blue;
|
||||
|
||||
[Resolved]
|
||||
private MultiplayerClient client { get; set; } = null!;
|
||||
|
||||
protected MultiplayerClient Client => client;
|
||||
|
||||
protected override Container<Drawable> Content { get; }
|
||||
|
||||
protected readonly Container CenterColumn;
|
||||
|
||||
protected readonly FillFlowContainer ButtonsContainer;
|
||||
protected readonly RankedPlayStageDisplay StageDisplay;
|
||||
|
||||
protected RankedPlaySubScreen()
|
||||
{
|
||||
@@ -62,6 +78,13 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(8)
|
||||
},
|
||||
StageDisplay = new RankedPlayStageDisplay(ColourScheme)
|
||||
{
|
||||
Heading = StageHeading,
|
||||
Caption = StageCaption,
|
||||
Margin = new MarginPadding { Top = 60 },
|
||||
State = { BindTarget = CountdownVisibility }
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
@@ -36,6 +37,9 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
{
|
||||
public partial class ResultsScreen : RankedPlaySubScreen
|
||||
{
|
||||
protected override LocalisableString StageHeading => "Results";
|
||||
protected override LocalisableString StageCaption => string.Empty;
|
||||
|
||||
public override bool ShowBeatmapBackground => true;
|
||||
|
||||
[Resolved]
|
||||
@@ -63,14 +67,11 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
{
|
||||
CornerPieceVisibility.Value = Visibility.Hidden;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
AddInternal(loadingSpinner = new LoadingSpinner
|
||||
{
|
||||
loadingSpinner = new LoadingSpinner
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
},
|
||||
};
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -160,6 +161,9 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
|
||||
AddInternal(new ResultScreenContent
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
// A little bit of room for the countdown timer...
|
||||
Margin = new MarginPadding { Top = 45 },
|
||||
PlayerScore = playerScore,
|
||||
OpponentScore = opponentScore,
|
||||
PlayerDamageInfo = matchInfo.RoomState.Users[playerId].DamageInfo!,
|
||||
@@ -210,8 +214,6 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
|
||||
.OfType<RankedPlayDamageInfo>()
|
||||
.MaxBy(it => it.Damage)!;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
AddInternal(panelScaffold = new PanelScaffold
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
|
||||
Reference in New Issue
Block a user