1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-13 16:02:58 +08:00

Avoid overlapping with recent circles

This commit is contained in:
Henry Lin 2021-06-19 10:04:48 +08:00
parent cca26d4651
commit ca8f08ca84

View File

@ -54,12 +54,12 @@ namespace osu.Game.Rulesets.Osu.Mods
/// <summary>
/// Jump distance for circles in the last combo
/// </summary>
private const float max_base_distance = 250f;
private const float max_base_distance = 333f;
/// <summary>
/// The maximum allowed jump distance after multipliers are applied
/// </summary>
private const float distance_cap = 350f;
private const float distance_cap = 380f;
// The distances from the hit objects to the borders of the playfield they start to "turn around" and curve towards the middle.
// The closer the hit objects draw to the border, the sharper the turn
@ -71,6 +71,11 @@ namespace osu.Game.Rulesets.Osu.Mods
/// </summary>
private const float edge_rotation_multiplier = 0.75f;
/// <summary>
/// Number of recent circles to check for overlap
/// </summary>
private const int overlap_check_count = 5;
/// <summary>
/// Duration of the undimming animation
/// </summary>
@ -291,6 +296,14 @@ namespace osu.Game.Rulesets.Osu.Mods
if (obj.Kiai) distance *= 1.2f;
distance = Math.Min(distance_cap, distance);
// Attempt to place the circle at a place that does not overlap with previous ones
var tryCount = 0;
do
{
if (tryCount > 0) direction = MathHelper.TwoPi * nextSingle();
var relativePos = new Vector2(
distance * (float)Math.Cos(direction),
distance * (float)Math.Sin(direction)
@ -313,6 +326,10 @@ namespace osu.Game.Rulesets.Osu.Mods
obj.Position = newPosition;
tryCount++;
if (tryCount % 10 == 0) distance *= 0.9f;
} while (distance >= obj.Radius * 2 && isOverlappingWithRecent(hitObjects, i));
if (obj.LastInCombo)
direction = MathHelper.TwoPi * nextSingle();
else
@ -355,6 +372,13 @@ namespace osu.Game.Rulesets.Osu.Mods
return samples;
}
private bool isOverlappingWithRecent(IReadOnlyList<OsuHitObject> hitObjects, int idx)
{
var target = hitObjects[idx];
return hitObjects.SkipLast(hitObjects.Count - idx).TakeLast(overlap_check_count)
.Any(h => Vector2.Distance(h.Position, target.Position) < target.Radius * 2);
}
/// <summary>
/// Determines the position of the current hit object relative to the previous one.
/// </summary>