Skip to content

Commit

Permalink
fixed circle sliders
Browse files Browse the repository at this point in the history
  • Loading branch information
Givikap120 committed Oct 10, 2024
1 parent 550363d commit d05a80e
Showing 1 changed file with 81 additions and 26 deletions.
107 changes: 81 additions & 26 deletions osu.Game.Rulesets.Osu/Difficulty/Evaluators/SliderReadingEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

using System;
using System.Linq;
using HidSharp.Reports.Units;

Check failure on line 6 in osu.Game.Rulesets.Osu/Difficulty/Evaluators/SliderReadingEvaluator.cs

View workflow job for this annotation

GitHub Actions / Code Quality

Using directive is unnecessary. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005)

Check failure on line 6 in osu.Game.Rulesets.Osu/Difficulty/Evaluators/SliderReadingEvaluator.cs

View workflow job for this annotation

GitHub Actions / Code Quality

Using directive is unnecessary. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005)
using osu.Framework.Extensions.ObjectExtensions;

using osu.Game.Rulesets.Osu.Objects;
using osuTK;

Expand Down Expand Up @@ -167,22 +167,15 @@ private static double calculateSliderShapeComplexity(Slider slider)
lineBonus *= slider_shape_reading_multiplier / slider.SpanDuration;
curveBonus *= slider_shape_reading_multiplier / slider.SpanDuration;

// Curve path takes more aim
double curvedLengthBonus = (Vector2.Distance(head.Position, middlePos) + Vector2.Distance(middlePos, tail.Position))
/ Vector2.Distance(head.Position, tail.Position) - 1;

// But start to buff only from 0.2 and more
curveBonus += Math.Max(curvedLengthBonus - 0.2, 0);

return Math.Min(lineBonus, curveBonus);
}

private static double calculateSliderPointUnpredictability(Slider slider)
{
double currAngle = -1, prevAngle = -1;
double currVelocity, prevVelocity = -1;
double prevAngle = double.NaN;
double prevDeltaTime = double.NaN;

OsuHitObject? prevObj0 = null, prevObj1;
OsuHitObject? prevObj0 = null, prevObj1 = null;
Vector2? prevObjPos0 = null, prevObjPos1 = null;

double totalBonus = 0;
Expand All @@ -205,22 +198,47 @@ private static double calculateSliderPointUnpredictability(Slider slider)
double currDistance = Vector2.Distance(currObjPos, (Vector2)prevObjPos0);
double currDeltaTime = currObj.StartTime - prevObj0.StartTime;

currVelocity = currDistance / currDeltaTime;
if (prevVelocity == -1) prevVelocity = currVelocity;
double currVelocity = currDistance / currDeltaTime;

if (prevObj1 == null || prevObjPos1 == null)
{
prevObj1 = prevObj0;
prevObj0 = currObj;

prevObjPos1 = prevObjPos0;
prevObjPos0 = currObjPos;

prevDeltaTime = currDeltaTime;
continue;
}

// Angle change bonus

double currAngle = calculateAngleSigned((Vector2)prevObjPos1, (Vector2)prevObjPos0, currObjPos);

double angleChangeBonus = 0;
if (!double.IsNaN(prevAngle))
{
angleChangeBonus = sinusCurve(Math.Abs(currAngle - prevAngle), 0.2, 0.7);

// Punish wide angles
angleChangeBonus *= 1 - sinusCurve(Math.Abs(currAngle), Math.PI / 2, Math.PI * 5 / 6);
}

// Velocity change bonus

if (prevObjPos1.IsNotNull())
currAngle = calculateAngleBetweenThreePoints(currObjPos, (Vector2)prevObjPos0, (Vector2)prevObjPos1);
if (prevAngle == -1)
prevAngle = currAngle;
double prevDistance = Vector2.Distance((Vector2)prevObjPos0, (Vector2)prevObjPos1);
double prevVelocity = prevDistance / prevDeltaTime;

// Apply bonus
(double prevCircularDistance, double currCircularDistance) = calculateCircularDistance((Vector2)prevObjPos1, (Vector2)prevObjPos0, currObjPos);
double prevCircularVelocity = prevCircularDistance / prevDeltaTime;
double currCircularVelocity = currCircularDistance / currDeltaTime;

double angleChangeBonus = sinusCurve(Math.Abs(currAngle - prevAngle), 0.2, 0.7);
double velocityChangeBonusLinear = sinusCurve(Math.Abs(currVelocity - prevVelocity), 0.2, 0.6);
double velocityChangeBonusCircular = sinusCurve(Math.Abs(currCircularVelocity - prevCircularVelocity), 0.2, 0.6);

// Punish vide angles
angleChangeBonus *= 1 - sinusCurve(Math.Abs(currAngle), Math.PI / 2, Math.PI * 5 / 6);
double velocityChangeBonus = Math.Min(velocityChangeBonusLinear, velocityChangeBonusCircular);

double velocityChangeBonus = sinusCurve(Math.Abs(currVelocity - prevVelocity), 0.2, 0.6);
totalBonus += (angleChangeBonus + velocityChangeBonus) * 2;
objectCount += 1;

Expand All @@ -233,24 +251,61 @@ private static double calculateSliderPointUnpredictability(Slider slider)
prevObjPos0 = currObjPos;

prevVelocity = currVelocity;
prevDeltaTime = currDeltaTime;
prevAngle = currAngle;

if (obj is SliderEndCircle || obj is SliderRepeat) break;
}

if (objectCount == 0)
return 0;

return Math.Min(1, totalBonus / objectCount);
}

// absolute (signed!!!) angle
private static double calculateAngleBetweenThreePoints(Vector2 p1, Vector2 p2, Vector2 p3)
private static (double prev, double curr) calculateCircularDistance(Vector2 p1, Vector2 p2, Vector2 p3)
{
Vector2 v1 = p2 - p1;
Vector2 v2 = p1 - p3;
static double sqr(double x) => x * x;
double currDist = Vector2.Distance(p2, p3);
double prevDist = Vector2.Distance(p1, p2);
double? angle = Math.Abs(calculateAngleSigned(p1, p2, p3));

double triangleArea = currDist * prevDist * Math.Sin(angle ?? 0) / 2;
if (triangleArea == 0)
return (prevDist, currDist);

double thirdSide = Math.Sqrt(sqr(currDist) + sqr(prevDist) - 2 * currDist * prevDist * Math.Cos(angle ?? Math.PI));
double circleRadius = currDist * prevDist * thirdSide / 4 / triangleArea;

double circularAnglePrev = Math.Abs(calculateAngleSigned(p1, p3, p2));
double circularAngleCurr = Math.Abs(calculateAngleSigned(p3, p1, p2));

double flowDistancePrev = circularAnglePrev / Math.PI * circleRadius;
double flowDistanceCurr = circularAngleCurr / Math.PI * circleRadius;

return (flowDistancePrev, flowDistanceCurr);
}

private static double calculateAngleSigned(Vector2 p1, Vector2 p2, Vector2 p3)
{
Vector2 v1 = p3 - p2;
Vector2 v2 = p1 - p2;

float dot = Vector2.Dot(v1, v2);
float det = v1.X * v2.Y - v1.Y * v2.X;

return Math.Atan2(det, dot);
}

private static double calculateAngleAbs(Vector2 p1, Vector2 p2, Vector2 p3)
{
Vector2 v1 = p2 - p1;
Vector2 v2 = p2 - p3;

float dot = v1.X * v2.X + v1.Y * v2.Y;
float modSum = v1.Length * v2.Length;

return Math.Acos(dot / modSum);
}
}
}

0 comments on commit d05a80e

Please sign in to comment.