Skip to content

Commit

Permalink
Merge pull request #31968 from frenzibyte/fix-scaling-issues
Browse files Browse the repository at this point in the history
Fix osu!taiko and osu!catch being oversized on mobile platforms
  • Loading branch information
peppy authored Feb 20, 2025
2 parents 95b64bd + b111262 commit 1350256
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 22 deletions.
2 changes: 1 addition & 1 deletion osu.Android/OsuGameAndroid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public partial class OsuGameAndroid : OsuGame
[Cached]
private readonly OsuGameActivity gameActivity;

protected override Vector2 ScalingContainerTargetDrawSize => new Vector2(1024, 1024 * DrawHeight / DrawWidth);
public override Vector2 ScalingContainerTargetDrawSize => new Vector2(1024, 1024 * DrawHeight / DrawWidth);

public OsuGameAndroid(OsuGameActivity activity)
: base(null)
Expand Down
54 changes: 38 additions & 16 deletions osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. 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.Game.Rulesets.UI;
Expand All @@ -15,6 +16,8 @@ public partial class CatchPlayfieldAdjustmentContainer : PlayfieldAdjustmentCont
protected override Container<Drawable> Content => content;
private readonly Container content;

private readonly Container scaleContainer;

public CatchPlayfieldAdjustmentContainer()
{
const float base_game_width = 1024f;
Expand All @@ -26,30 +29,49 @@ public CatchPlayfieldAdjustmentContainer()
Anchor = Anchor.Centre;
Origin = Anchor.Centre;

InternalChild = new Container
InternalChild = scaleContainer = new Container
{
// This container limits vertical visibility of the playfield to ensure fairness between wide and tall resolutions (i.e. tall resolutions should not see more fruits).
// Note that the container still extends across the screen horizontally, so that hit explosions at the sides of the playfield do not get cut off.
Name = "Visible area",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = base_game_height + extra_bottom_space,
Y = extra_bottom_space / 2,
Masking = true,
RelativeSizeAxes = Axes.Both,
Child = new Container
{
Name = "Playable area",
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
// playfields in stable are positioned vertically at three fourths the difference between the playfield height and the window height in stable.
Y = base_game_height * ((1 - playfield_size_adjust) / 4 * 3),
Size = new Vector2(base_game_width, base_game_height) * playfield_size_adjust,
Child = content = new ScalingContainer { RelativeSizeAxes = Axes.Both }
},
// This container limits vertical visibility of the playfield to ensure fairness between wide and tall resolutions (i.e. tall resolutions should not see more fruits).
// Note that the container still extends across the screen horizontally, so that hit explosions at the sides of the playfield do not get cut off.
Name = "Visible area",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = base_game_height + extra_bottom_space,
Y = extra_bottom_space / 2,
Masking = true,
Child = new Container
{
Name = "Playable area",
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
// playfields in stable are positioned vertically at three fourths the difference between the playfield height and the window height in stable.
Y = base_game_height * ((1 - playfield_size_adjust) / 4 * 3),
Size = new Vector2(base_game_width, base_game_height) * playfield_size_adjust,
Child = content = new ScalingContainer { RelativeSizeAxes = Axes.Both }
},
}
};
}

[BackgroundDependencyLoader]
private void load(OsuGame? osuGame)
{
if (osuGame != null)
{
// on mobile platforms where the base aspect ratio is wider, the catch playfield
// needs to be scaled down to remain playable.
const float base_aspect_ratio = 1024f / 768f;
float aspectRatio = osuGame.ScalingContainerTargetDrawSize.X / osuGame.ScalingContainerTargetDrawSize.Y;
scaleContainer.Scale = new Vector2(base_aspect_ratio / aspectRatio);
}
}

/// <summary>
/// A <see cref="Container"/> which scales its content relative to a target width.
/// </summary>
Expand Down
5 changes: 2 additions & 3 deletions osu.Game.Rulesets.Taiko/UI/DrumTouchInputArea.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,10 @@ private void load(TaikoInputManager taikoInputManager, TaikoRulesetConfigManager
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
RelativeSizeAxes = Axes.X,
Height = 350,
RelativeSizeAxes = Axes.Both,
Height = 0.45f,
Y = 20,
Masking = true,
FillMode = FillMode.Fit,
Children = new Drawable[]
{
mainContent = new Container
Expand Down
17 changes: 17 additions & 0 deletions osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// See the LICENCE file in the repository root for full licence text.

using System;
using osu.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Taiko.Beatmaps;
Expand All @@ -19,6 +21,9 @@ public partial class TaikoPlayfieldAdjustmentContainer : PlayfieldAdjustmentCont

public readonly IBindable<bool> LockPlayfieldAspectRange = new BindableBool(true);

[Resolved]
private OsuGame? osuGame { get; set; }

public TaikoPlayfieldAdjustmentContainer()
{
RelativeSizeAxes = Axes.X;
Expand Down Expand Up @@ -56,6 +61,18 @@ protected override void Update()
relativeHeight = Math.Min(relativeHeight, 1f / 3f);

Scale = new Vector2(Math.Max((Parent!.ChildSize.Y / 768f) * (relativeHeight / base_relative_height), 1f));

// on mobile platforms where the base aspect ratio is wider, the taiko playfield
// needs to be scaled down to remain playable.
if (RuntimeInfo.IsMobile && osuGame != null)
{
const float base_aspect_ratio = 1024f / 768f;
float gameAspectRatio = osuGame.ScalingContainerTargetDrawSize.X / osuGame.ScalingContainerTargetDrawSize.Y;
// this magic scale is unexplainable, but required so the playfield doesn't become too zoomed out as the aspect ratio increases.
const float magic_scale = 1.25f;
Scale *= magic_scale * new Vector2(base_aspect_ratio / gameAspectRatio);
}

Width = 1 / Scale.X;
}

Expand Down
2 changes: 1 addition & 1 deletion osu.Game/OsuGame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ public override Task Import(ImportTask[] imports, ImportParameters parameters =
/// Adjust the globally applied <see cref="DrawSizePreservingFillContainer.TargetDrawSize"/> in every <see cref="ScalingContainer"/>.
/// Useful for changing how the game handles different aspect ratios.
/// </summary>
protected internal virtual Vector2 ScalingContainerTargetDrawSize { get; } = new Vector2(1024, 768);
public virtual Vector2 ScalingContainerTargetDrawSize { get; } = new Vector2(1024, 768);

protected override Container CreateScalingContainer() => new ScalingContainer(ScalingMode.Everything);

Expand Down
2 changes: 1 addition & 1 deletion osu.iOS/OsuGameIOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public partial class OsuGameIOS : OsuGame

public override bool HideUnlicensedContent => true;

protected override Vector2 ScalingContainerTargetDrawSize => new Vector2(1024, 1024 * DrawHeight / DrawWidth);
public override Vector2 ScalingContainerTargetDrawSize => new Vector2(1024, 1024 * DrawHeight / DrawWidth);

public OsuGameIOS(AppDelegate appDelegate)
{
Expand Down

0 comments on commit 1350256

Please sign in to comment.