示例#1
0
        internal DifficultyHitObjectOsu(HitObject BaseHitObject, float CircleRadius)
        {
            this.BaseHitObject = BaseHitObject;

            if (BaseHitObject.IsType(HitObjectType.Slider))
            {
                SliderOsu Slider = (SliderOsu)BaseHitObject;
                MaxCombo = 1 + Slider.sliderScoreTimingPoints.Count;
            }
            else
            {
                MaxCombo = 1;
            }

            // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps.
            float ScalingFactor = (52.0f / CircleRadius);

            if (CircleRadius < 30)
            {
                float smallCircleBonus = Math.Min(30.0f - CircleRadius, 5.0f) / 50.0f;
                ScalingFactor *= 1.0f + smallCircleBonus;
            }

            NormalizedStartPosition = BaseHitObject.Position * ScalingFactor;

            // Calculate approximation of lazy movement on the slider
            if (BaseHitObject.IsType(HitObjectType.Slider))
            {
                float SliderFollowCircleRadius = CircleRadius * 3;                                       // Not sure if this is correct, but here we do not need 100% exact values. This comes pretty darn close in my tests.

                int SegmentLength  = Math.Min(BaseHitObject.Length / BaseHitObject.SegmentCount, 60000); // We don't want infinite loops if someone decides to make a too long slider. (MillhioreF, I am talking about you! https://osu.ppy.sh/b/326585)
                int SegmentEndTime = BaseHitObject.StartTime + SegmentLength;

                // For simplifying this step we use actual osu! coordinates and simply scale the length, that we obtain by the ScalingFactor later
                Vector2 CursorPos = BaseHitObject.Position; //

                //Debug.Print("" + (BaseHitObject.StartTime + LAZY_SLIDER_STEP_LENGTH) + " " + SegmentEndTime + " " + BaseHitObject.EndTime + " " + BaseHitObject.SegmentCount);

                // Actual computation of the first lazy curve
                for (int Time = BaseHitObject.StartTime + LAZY_SLIDER_STEP_LENGTH; Time < SegmentEndTime; Time += LAZY_SLIDER_STEP_LENGTH)
                {
                    Vector2 Difference = BaseHitObject.PositionAtTime(Time) - CursorPos;
                    float   Distance   = Difference.Length();

                    // Did we move away too far?
                    if (Distance > SliderFollowCircleRadius)
                    {
                        // Yep, we need to move the cursor
                        Difference.Normalize();                         // Obtain the direction of difference. We do no longer need the actual difference
                        Distance              -= SliderFollowCircleRadius;
                        CursorPos             += Difference * Distance; // We move the cursor just as far as needed to stay in the follow circle
                        LazySliderLengthFirst += Distance;
                    }
                }

                LazySliderLengthFirst *= ScalingFactor;
                // If we have an odd amount of repetitions the current position will be the end of the slider. Note that this will -always- be triggered if
                // BaseHitObject.SegmentCount <= 1, because BaseHitObject.SegmentCount can not be smaller than 1. Therefore NormalizedEndPosition will always be initialized
                if (BaseHitObject.SegmentCount % 2 == 1)
                {
                    NormalizedEndPosition = CursorPos * ScalingFactor;
                }

                // If we have more than one segment, then we also need to compute the length ob subsequent lazy curves. They are different from the first one, since the first
                // one starts right at the beginning of the slider.
                if (BaseHitObject.SegmentCount > 1)
                {
                    // Use the next segment
                    SegmentEndTime += SegmentLength;

                    for (int Time = SegmentEndTime - SegmentLength + LAZY_SLIDER_STEP_LENGTH; Time < SegmentEndTime; Time += LAZY_SLIDER_STEP_LENGTH)
                    {
                        Vector2 Difference = BaseHitObject.PositionAtTime(Time) - CursorPos;
                        float   Distance   = Difference.Length();

                        // Did we move away too far?
                        if (Distance > SliderFollowCircleRadius)
                        {
                            // Yep, we need to move the cursor
                            Difference.Normalize();             // Obtain the direction of difference. We do no longer need the actual difference
                            Distance  -= SliderFollowCircleRadius;
                            CursorPos += Difference * Distance; // We move the cursor just as far as needed to stay in the follow circle
                            LazySliderLengthSubsequent += Distance;
                        }
                    }

                    LazySliderLengthSubsequent *= ScalingFactor;
                    // If we have an even amount of repetitions the current position will be the end of the slider
                    if (BaseHitObject.SegmentCount % 2 == 0)
                    {
                        NormalizedEndPosition = CursorPos * ScalingFactor;
                    }
                }
            }
            // We have a normal HitCircle or a spinner
            else
            {
                NormalizedEndPosition = NormalizedStartPosition;
            }
        }