-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Rewrite osu!taiko's time range computation logic to match 1:1 with stable #26781
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
using System; | ||
using osu.Framework.Bindables; | ||
using osu.Framework.Graphics; | ||
using osu.Game.Rulesets.Taiko.Beatmaps; | ||
using osu.Game.Rulesets.UI; | ||
using osuTK; | ||
|
||
|
@@ -14,22 +15,25 @@ public partial class TaikoPlayfieldAdjustmentContainer : PlayfieldAdjustmentCont | |
public const float MAXIMUM_ASPECT = 16f / 9f; | ||
public const float MINIMUM_ASPECT = 5f / 4f; | ||
|
||
private const float stable_gamefield_height = 480f; | ||
|
||
public readonly IBindable<bool> LockPlayfieldAspectRange = new BindableBool(true); | ||
|
||
public TaikoPlayfieldAdjustmentContainer() | ||
{ | ||
RelativeSizeAxes = Axes.X; | ||
RelativePositionAxes = Axes.Y; | ||
Height = TaikoPlayfield.BASE_HEIGHT; | ||
|
||
// Matches stable, see https://github.com/peppy/osu-stable-reference/blob/7519cafd1823f1879c0d9c991ba0e5c7fd3bfa02/osu!/GameModes/Play/Rulesets/Taiko/RulesetTaiko.cs#L514 | ||
Y = 135f / stable_gamefield_height; | ||
} | ||
|
||
protected override void Update() | ||
{ | ||
base.Update(); | ||
|
||
const float base_relative_height = TaikoPlayfield.BASE_HEIGHT / 768; | ||
// Matches stable, see https://github.com/peppy/osu-stable-reference/blob/7519cafd1823f1879c0d9c991ba0e5c7fd3bfa02/osu!/GameModes/Play/Rulesets/Taiko/RulesetTaiko.cs#L514 | ||
const float base_position = 135f / 480f; | ||
|
||
float relativeHeight = base_relative_height; | ||
|
||
|
@@ -51,10 +55,38 @@ protected override void Update() | |
// Limit the maximum relative height of the playfield to one-third of available area to avoid it masking out on extreme resolutions. | ||
relativeHeight = Math.Min(relativeHeight, 1f / 3f); | ||
|
||
Y = base_position; | ||
|
||
Scale = new Vector2(Math.Max((Parent!.ChildSize.Y / 768f) * (relativeHeight / base_relative_height), 1f)); | ||
Width = 1 / Scale.X; | ||
} | ||
|
||
public double ComputeTimeRange() | ||
{ | ||
float currentAspect = Parent!.ChildSize.X / Parent!.ChildSize.Y; | ||
|
||
if (LockPlayfieldAspectRange.Value) | ||
currentAspect = Math.Clamp(currentAspect, MINIMUM_ASPECT, MAXIMUM_ASPECT); | ||
|
||
// in a game resolution of 1024x768, stable's scrolling system consists of objects being placed 600px (widthScaled - 40) away from their hit location. | ||
// however, the point at which the object renders at the end of the screen is exactly x=640, but stable makes the object start moving from beyond the screen instead of the boundary point. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
no reference for this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment needs to be reworded but what I was trying to convey is that stable starts scrolling the object from |
||
// therefore, in lazer we have to adjust the "in length" so that it's in a 640px->160px fashion before passing it down as a "time range". | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what does this mean? what is "a 640px->160px fashion"? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As in, the This is bad for lazer, because 640px in stable is considered the right edge of the playfield, i.e. stable begins scrolling the object from outside of the playfield, while lazer begins scrolling the object from the right edge of the playfield instead (technically scrolls from the right edge of the So to compromise this, the |
||
// see stable's "in length": https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/GameplayElements/HitObjectManagerTaiko.cs#L168 | ||
const float stable_hit_location = 160f; | ||
float widthScaled = currentAspect * stable_gamefield_height; | ||
float inLength = widthScaled - stable_hit_location; | ||
|
||
// also in a game resolution of 1024x768, stable makes hit objects scroll from 760px->160px at a duration of 6000ms, divided by slider velocity (i.e. at a rate of 0.1px/ms) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where does 760px come from here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
// compare: https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/GameplayElements/HitObjectManagerTaiko.cs#L218 | ||
// note: the variable "sv", in the linked reference, is equivalent to MultiplierControlPoint.Multiplier * 100, but since time range is agnostic of velocity, we replace "sv" with 100 below. | ||
float inMsLength = inLength / 100 * 1000; | ||
|
||
// stable multiplies the slider velocity by 1.4x for certain reasons, divide the time range by that factor to achieve similar result. | ||
// for references on how the factor is applied to the time range, see: | ||
// 1. https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/GameplayElements/HitObjectManagerTaiko.cs#L79 (DifficultySliderMultiplier multiplied by 1.4x) | ||
// 2. https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/GameplayElements/HitObjectManager.cs#L468-L470 (DifficultySliderMultiplier used to calculate SliderScoringPointDistance) | ||
// 3. https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/GameplayElements/HitObjectManager.cs#L248-L250 (SliderScoringPointDistance used to calculate slider velocity, i.e. the "sv" variable from above) | ||
inMsLength /= TaikoBeatmapConverter.VELOCITY_MULTIPLIER; | ||
|
||
return inMsLength; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no reference for this (where's the 600px figure in stable?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is connected with the rest of the comment block about the "in length" value, in that it is all sourced from this line in stable code.
In a game resolution of 1024x768, the "scaled" resolution is 640x480 because of the aspect ratio of the game resolution. So "width scaled" is 640px, subtracting 40 from it leads to the final value of 600px, which is the scrolling distance of the object in a 640x480 space (since it's assigned to the
inLength
variable, see scroll code.