mirror of
https://github.com/osukey/osukey.git
synced 2025-08-06 16:13:57 +09:00
Rework slider positioning
This commit is contained in:
@ -23,6 +23,8 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
public override string Description => "It never gets boring!";
|
public override string Description => "It never gets boring!";
|
||||||
public override bool Ranked => false;
|
public override bool Ranked => false;
|
||||||
|
|
||||||
|
private const float slider_path_checking_rate = 10;
|
||||||
|
|
||||||
// The relative distance to the edge of the playfield before objects' positions should start to "turn around" and curve towards the middle.
|
// The relative distance to the edge of the playfield before objects' positions should start to "turn around" and curve towards the middle.
|
||||||
// The closer the hit objects draw to the border, the sharper the turn
|
// The closer the hit objects draw to the border, the sharper the turn
|
||||||
private const float playfield_edge_ratio = 0.375f;
|
private const float playfield_edge_ratio = 0.375f;
|
||||||
@ -74,22 +76,8 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
// update end position as it may have changed as a result of the position update.
|
// update end position as it may have changed as a result of the position update.
|
||||||
current.EndPositionRandomised = current.PositionRandomised;
|
current.EndPositionRandomised = current.PositionRandomised;
|
||||||
|
|
||||||
switch (hitObject)
|
if (hitObject is Slider slider)
|
||||||
{
|
moveSliderIntoPlayfield(slider, current);
|
||||||
case Slider slider:
|
|
||||||
// Shift nested objects the same distance as the slider got shifted in the randomisation process
|
|
||||||
// so that moveSliderIntoPlayfield() can determine their relative distances to slider.Position and thus minMargin
|
|
||||||
shiftNestedObjects(slider, Vector2.Subtract(slider.Position, current.PositionOriginal));
|
|
||||||
|
|
||||||
var oldPos = new Vector2(slider.Position.X, slider.Position.Y);
|
|
||||||
|
|
||||||
moveSliderIntoPlayfield(slider, current);
|
|
||||||
|
|
||||||
// Shift them again to move them to their final position after the slider got moved into the playfield
|
|
||||||
shiftNestedObjects(slider, Vector2.Subtract(slider.Position, oldPos));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
previous = current;
|
previous = current;
|
||||||
}
|
}
|
||||||
@ -146,34 +134,53 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void moveSliderIntoPlayfield(Slider slider, RandomObjectInfo currentObjectInfo)
|
private void moveSliderIntoPlayfield(Slider slider, RandomObjectInfo currentObjectInfo)
|
||||||
{
|
{
|
||||||
// Min. distances from the slider's position to the playfield border
|
var minMargin = getMinSliderMargin(slider);
|
||||||
var minMargin = new MarginPadding();
|
|
||||||
|
|
||||||
foreach (var hitObject in slider.NestedHitObjects.Where(o => o is SliderTick || o is SliderEndCircle))
|
slider.Position = new Vector2(
|
||||||
{
|
Math.Clamp(slider.Position.X, minMargin.Left, OsuPlayfield.BASE_SIZE.X - minMargin.Right),
|
||||||
if (!(hitObject is OsuHitObject osuHitObject))
|
Math.Clamp(slider.Position.Y, minMargin.Top, OsuPlayfield.BASE_SIZE.Y - minMargin.Bottom)
|
||||||
continue;
|
);
|
||||||
|
|
||||||
var relativePos = Vector2.Subtract(osuHitObject.Position, slider.Position);
|
|
||||||
|
|
||||||
minMargin.Left = Math.Max(minMargin.Left, -relativePos.X);
|
|
||||||
minMargin.Right = Math.Max(minMargin.Right, relativePos.X);
|
|
||||||
minMargin.Top = Math.Max(minMargin.Top, -relativePos.Y);
|
|
||||||
minMargin.Bottom = Math.Max(minMargin.Bottom, relativePos.Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slider.Position.X < minMargin.Left)
|
|
||||||
slider.Position = new Vector2(minMargin.Left, slider.Position.Y);
|
|
||||||
else if (slider.Position.X + minMargin.Right > OsuPlayfield.BASE_SIZE.X)
|
|
||||||
slider.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - minMargin.Right, slider.Position.Y);
|
|
||||||
|
|
||||||
if (slider.Position.Y < minMargin.Top)
|
|
||||||
slider.Position = new Vector2(slider.Position.X, minMargin.Top);
|
|
||||||
else if (slider.Position.Y + minMargin.Bottom > OsuPlayfield.BASE_SIZE.Y)
|
|
||||||
slider.Position = new Vector2(slider.Position.X, OsuPlayfield.BASE_SIZE.Y - minMargin.Bottom);
|
|
||||||
|
|
||||||
currentObjectInfo.PositionRandomised = slider.Position;
|
currentObjectInfo.PositionRandomised = slider.Position;
|
||||||
currentObjectInfo.EndPositionRandomised = slider.EndPosition;
|
currentObjectInfo.EndPositionRandomised = slider.EndPosition;
|
||||||
|
|
||||||
|
shiftNestedObjects(slider, Vector2.Subtract(currentObjectInfo.PositionRandomised, currentObjectInfo.PositionOriginal));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the min. distances from the <see cref="Slider"/>'s position to the playfield border for the slider to be fully inside of the playfield.
|
||||||
|
/// </summary>
|
||||||
|
private MarginPadding getMinSliderMargin(Slider slider)
|
||||||
|
{
|
||||||
|
var minMargin = new MarginPadding();
|
||||||
|
Vector2 pos;
|
||||||
|
|
||||||
|
for (double j = 0; j <= 1; j += 1 / (slider_path_checking_rate / 1000 * (slider.EndTime - slider.StartTime)))
|
||||||
|
{
|
||||||
|
pos = slider.Path.PositionAt(j);
|
||||||
|
updateMargin();
|
||||||
|
}
|
||||||
|
|
||||||
|
var repeat = (SliderRepeat)slider.NestedHitObjects.FirstOrDefault(o => o is SliderRepeat);
|
||||||
|
|
||||||
|
if (repeat != null)
|
||||||
|
{
|
||||||
|
pos = repeat.Position - slider.Position;
|
||||||
|
updateMargin();
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = slider.Path.PositionAt(1);
|
||||||
|
updateMargin();
|
||||||
|
|
||||||
|
return minMargin;
|
||||||
|
|
||||||
|
void updateMargin()
|
||||||
|
{
|
||||||
|
minMargin.Left = Math.Max(minMargin.Left, -pos.X);
|
||||||
|
minMargin.Right = Math.Max(minMargin.Right, pos.X);
|
||||||
|
minMargin.Top = Math.Max(minMargin.Top, -pos.Y);
|
||||||
|
minMargin.Bottom = Math.Max(minMargin.Bottom, pos.Y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
Reference in New Issue
Block a user