diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs new file mode 100644 index 0000000000..a6e67ea979 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Osu.Judgements +{ + public class OsuSliderTailJudgement : OsuJudgement + { + public override bool AffectsCombo => false; + protected override int NumericResultFor(HitResult result) => 0; + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 7462478408..7247fe1362 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -18,14 +18,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public class DrawableSlider : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { private readonly Slider slider; - - public readonly DrawableHitCircle HeadCircle; - private readonly List components = new List(); - private readonly Container ticks; - private readonly Container repeatPoints; - + public readonly DrawableHitCircle HeadCircle; public readonly SliderBody Body; public readonly SliderBall Ball; @@ -34,6 +29,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { slider = s; + DrawableSliderTail tail; + Container ticks; + Container repeatPoints; + Children = new Drawable[] { Body = new SliderBody(s) @@ -51,7 +50,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables AlwaysPresent = true, Alpha = 0 }, - HeadCircle = new DrawableHitCircle(s.HeadCircle) + HeadCircle = new DrawableHitCircle(s.HeadCircle), + tail = new DrawableSliderTail(s.TailCircle) }; components.Add(Body); @@ -59,6 +59,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables AddNested(HeadCircle); + AddNested(tail); + components.Add(tail); + foreach (var tick in s.NestedHitObjects.OfType()) { var spanStartTime = s.StartTime + tick.SpanIndex * s.SpanDuration; @@ -73,6 +76,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }; ticks.Add(drawableTick); + components.Add(drawableTick); AddNested(drawableTick); } @@ -112,17 +116,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables foreach (var c in components.OfType()) c.UpdateProgress(progress, span); foreach (var c in components.OfType()) c.UpdateSnakingPosition(slider.Curve.PositionAt(Body.SnakedStart ?? 0), slider.Curve.PositionAt(Body.SnakedEnd ?? 0)); - foreach (var t in ticks.Children) t.Tracking = Ball.Tracking; + foreach (var t in components.OfType()) t.Tracking = Ball.Tracking; } protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (!userTriggered && Time.Current >= slider.EndTime) { - var judgementsCount = ticks.Children.Count + repeatPoints.Children.Count + 1; - var judgementsHit = ticks.Children.Count(t => t.Judgements.Any(j => j.IsHit)) + repeatPoints.Children.Count(t => t.Judgements.Any(j => j.IsHit)); - if (HeadCircle.Judgements.Any(j => j.IsHit)) - judgementsHit++; + var judgementsCount = NestedHitObjects.Count; + var judgementsHit = NestedHitObjects.Count(h => h.IsHit); var hitFraction = (double)judgementsHit / judgementsCount; if (hitFraction == 1 && HeadCircle.Judgements.Any(j => j.Result == HitResult.Great)) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs new file mode 100644 index 0000000000..8835fc2b29 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Osu.Objects.Drawables +{ + public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking + { + /// + /// The judgement text is provided by the . + /// + public override bool DisplayJudgement => false; + + public bool Tracking { get; set; } + + public DrawableSliderTail(HitCircle hitCircle) + : base(hitCircle) + { + AlwaysPresent = true; + RelativeSizeAxes = Axes.Both; + } + + protected override void CheckForJudgements(bool userTriggered, double timeOffset) + { + if (!userTriggered && timeOffset >= 0) + AddJudgement(new OsuSliderTailJudgement { Result = Tracking ? HitResult.Great : HitResult.Miss }); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index 09985752a4..ae76f1e0e1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -12,14 +12,14 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableSliderTick : DrawableOsuHitObject + public class DrawableSliderTick : DrawableOsuHitObject, IRequireTracking { private readonly SliderTick sliderTick; public double FadeInTime; public double FadeOutTime; - public bool Tracking; + public bool Tracking { get; set; } public override bool DisplayJudgement => false; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs new file mode 100644 index 0000000000..98fc686dd3 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Osu.Objects.Drawables +{ + public interface IRequireTracking + { + /// + /// Whether the is currently being tracked by the user. + /// + bool Tracking { get; set; } + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index fba016a55e..0c86c64be7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -81,6 +81,7 @@ namespace osu.Game.Rulesets.Osu.Objects public double TickDistance; public HitCircle HeadCircle; + public HitCircle TailCircle; protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { @@ -104,7 +105,18 @@ namespace osu.Game.Rulesets.Osu.Objects SampleControlPoint = SampleControlPoint }; + TailCircle = new HitCircle + { + StartTime = EndTime, + Position = StackedEndPosition, + IndexInCurrentCombo = IndexInCurrentCombo, + ComboColour = ComboColour, + Samples = Samples, + SampleControlPoint = SampleControlPoint + }; + HeadCircle.ApplyDefaults(controlPointInfo, difficulty); + TailCircle.ApplyDefaults(controlPointInfo, difficulty); } protected override void CreateNestedHitObjects() diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index 74a3883f0a..97a003513f 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -55,6 +55,7 @@ + @@ -75,6 +76,8 @@ + +