From adebe166d43431671f1ccac4ced5566debdd1b4d Mon Sep 17 00:00:00 2001 From: Shawdooow Date: Tue, 26 Sep 2017 12:13:34 -0400 Subject: [PATCH] slider bouncers --- .../Objects/Drawables/DrawableSlider.cs | 40 +++++---- .../Drawables/DrawableSliderBouncer.cs | 84 +++++++++++++++++++ osu.Game.Rulesets.Osu/Objects/Slider.cs | 31 +++++++ .../Objects/SliderBouncer.cs | 10 +++ .../osu.Game.Rulesets.Osu.csproj | 2 + 5 files changed, 150 insertions(+), 17 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderBouncer.cs create mode 100644 osu.Game.Rulesets.Osu/Objects/SliderBouncer.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index c5155d1e10..61d4ec493c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Classic.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -21,15 +22,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly List components = new List(); private readonly Container ticks; + private readonly Container bouncers; private readonly SliderBody body; private readonly SliderBall ball; - private readonly SliderBouncer bouncer2; - public DrawableSlider(Slider s) : base(s) { - SliderBouncer bouncer1; slider = s; Children = new Drawable[] @@ -41,16 +40,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables PathWidth = s.Scale * 64, }, ticks = new Container(), - bouncer1 = new SliderBouncer(s, false) - { - Position = s.Curve.PositionAt(1), - Scale = new Vector2(s.Scale), - }, - bouncer2 = new SliderBouncer(s, true) - { - Position = s.StackedPosition, - Scale = new Vector2(s.Scale), - }, + bouncers = new Container(), ball = new SliderBall(s) { Scale = new Vector2(s.Scale), @@ -70,8 +60,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables components.Add(body); components.Add(ball); - components.Add(bouncer1); - components.Add(bouncer2); AddNested(initialCircle); @@ -92,14 +80,34 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ticks.Add(drawableTick); AddNested(drawableTick); } + + foreach (var bouncer in s.Bouncers) + { + var repeatStartTime = s.StartTime + bouncer.RepeatIndex * repeatDuration; + var fadeInTime = repeatStartTime + (bouncer.StartTime - repeatStartTime) / 2 - (bouncer.RepeatIndex == 0 ? TIME_FADEIN : TIME_FADEIN / 2); + var fadeOutTime = repeatStartTime + repeatDuration; + + var drawableBouncer = new DrawableSliderBouncer(bouncer, this) + { + FadeInTime = fadeInTime, + FadeOutTime = fadeOutTime, + Position = bouncer.Position, + }; + + bouncers.Add(drawableBouncer); + AddNested(drawableBouncer); + } } private int currentRepeat; + public bool Tracking; protected override void Update() { base.Update(); + Tracking = ball.Tracking; + double progress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); int repeat = slider.RepeatAt(progress); @@ -112,8 +120,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables currentRepeat = repeat; } - bouncer2.Position = slider.Curve.PositionAt(body.SnakedEnd ?? 0); - //todo: we probably want to reconsider this before adding scoring, but it looks and feels nice. if (!initialCircle.Judgements.Any(j => j.IsHit)) initialCircle.Position = slider.Curve.PositionAt(progress); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderBouncer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderBouncer.cs new file mode 100644 index 0000000000..e1f668da86 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderBouncer.cs @@ -0,0 +1,84 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Objects.Drawables; +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Judgements; + +namespace osu.Game.Rulesets.Classic.Objects.Drawables +{ + public class DrawableSliderBouncer : DrawableOsuHitObject + { + private readonly SliderBouncer sliderBouncer; + private readonly DrawableSlider drawableSlider; + + public double FadeInTime; + public double FadeOutTime; + + public override bool RemoveWhenNotAlive => false; + + public DrawableSliderBouncer(SliderBouncer sliderBouncer, DrawableSlider drawableSlider) : base(sliderBouncer) + { + this.sliderBouncer = sliderBouncer; + this.drawableSlider = drawableSlider; + + AutoSizeAxes = Axes.Both; + Blending = BlendingMode.Additive; + Origin = Anchor.Centre; + + Children = new Drawable[] + { + new SpriteIcon + { + Icon = FontAwesome.fa_eercast, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(32), + } + }; + } + + protected override void CheckForJudgements(bool userTriggered, double timeOffset) + { + if (sliderBouncer.StartTime <= Time.Current) + AddJudgement(new OsuJudgement { Result = drawableSlider.Tracking ? HitResult.Great : HitResult.Miss }); + } + + protected override void UpdatePreemptState() + { + var animIn = Math.Min(150, sliderBouncer.StartTime - FadeInTime); + + this.Animate( + d => d.FadeIn(animIn), + d => d.ScaleTo(0.5f).ScaleTo(1.2f, animIn) + ).Then( + d => d.ScaleTo(1, 150, Easing.Out) + ); + } + + protected override void UpdateCurrentState(ArmedState state) + { + switch (state) + { + case ArmedState.Idle: + this.Delay(FadeOutTime - sliderBouncer.StartTime).FadeOut(); + break; + case ArmedState.Miss: + this.FadeOut(160); + break; + case ArmedState.Hit: + this.FadeOut(120, Easing.OutQuint) + .ScaleTo(Scale * 1.5f, 120, Easing.OutQuint); + break; + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 056bde4005..b501e8e86a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -61,6 +61,7 @@ namespace osu.Game.Rulesets.Osu.Objects public double Velocity; public double TickDistance; + public double BouncerDistance; public override void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { @@ -73,6 +74,7 @@ namespace osu.Game.Rulesets.Osu.Objects Velocity = scoringDistance / timingPoint.BeatLength; TickDistance = scoringDistance / difficulty.SliderTickRate; + BouncerDistance = Distance; } public Vector2 PositionAt(double progress) => Curve.PositionAt(ProgressAt(progress)); @@ -131,5 +133,34 @@ namespace osu.Game.Rulesets.Osu.Objects } } } + public IEnumerable Bouncers + { + get + { + var length = Curve.Distance; + var bouncerDistance = Math.Min(BouncerDistance, length); + var repeatDuration = length / Velocity; + + for (var repeat = 0; repeat < RepeatCount; repeat++) + { + if (repeat > 0) + for (var d = bouncerDistance; d <= length; d += bouncerDistance) + { + var repeatStartTime = StartTime + repeat * repeatDuration; + var distanceProgress = d / length; + + yield return new SliderBouncer + { + RepeatIndex = repeat, + StartTime = repeatStartTime, + Position = Curve.PositionAt(distanceProgress), + StackHeight = StackHeight, + Scale = Scale, + ComboColour = ComboColour, + }; + } + } + } + } } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderBouncer.cs b/osu.Game.Rulesets.Osu/Objects/SliderBouncer.cs new file mode 100644 index 0000000000..da98cc8422 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/SliderBouncer.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Osu.Objects +{ + public class SliderBouncer : OsuHitObject + { + public int RepeatIndex { get; set; } + } +} diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index 300000754c..f12d932acb 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -53,6 +53,7 @@ + @@ -72,6 +73,7 @@ +