Skip to content

Commit

Permalink
Merge pull request #160 from LumpBloom7/BetterSlideAnimation
Browse files Browse the repository at this point in the history
Adjust slide visual and improve their animations
  • Loading branch information
LumpBloom7 authored Dec 24, 2020
2 parents 608638f + 1fbaadf commit c98e7b3
Show file tree
Hide file tree
Showing 12 changed files with 330 additions and 173 deletions.
69 changes: 69 additions & 0 deletions assets/chevron.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
Expand Down Expand Up @@ -38,7 +39,7 @@ public TestSceneSlide()
});
AddSliderStep("Progress", 0.0f, 1.0f, 0.0f, p =>
{
slide.Progress = p;
slide.CompletedSegments = (int)(slide.SegmentCount * p);
});

Add(nodes = new Container()
Expand All @@ -47,9 +48,15 @@ public TestSceneSlide()
Origin = Anchor.Centre,
});
}

protected abstract SentakkiSlidePath CreatePattern();

[SetUpSteps]
protected override void LoadComplete()
{
base.LoadComplete();
RefreshSlide();
}

protected void RefreshSlide()
{
slide.Path = CreatePattern().Path;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ protected override void InitialiseDefaults()
Set(SentakkiRulesetSettings.RingColor, ColorOption.Default);
Set(SentakkiRulesetSettings.RingOpacity, 1f, 0f, 1f, 0.01f);
Set(SentakkiRulesetSettings.LaneInputMode, LaneInputMode.Button);
Set(SentakkiRulesetSettings.SnakingSlideBody, true);
}
}

Expand All @@ -47,6 +48,7 @@ public enum SentakkiRulesetSettings
ShowNoteStartIndicators,
RingColor,
TouchAnimationDuration,
LaneInputMode
LaneInputMode,
SnakingSlideBody
}
}
42 changes: 22 additions & 20 deletions osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableSlideBody.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
using System;
using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Sentakki.Configuration;
using osu.Game.Rulesets.Sentakki.Objects.Drawables.Pieces;
using osuTK;
using osuTK.Graphics;
Expand All @@ -20,35 +23,30 @@ public class DrawableSlideBody : DrawableSentakkiLanedHitObject

public override bool RemoveWhenNotAlive => false;

protected override double InitialLifetimeOffset => base.InitialLifetimeOffset / 2;
protected override double InitialLifetimeOffset => base.InitialLifetimeOffset;

public Container<DrawableSlideNode> SlideNodes;

public SlideVisual Slidepath;
public StarPiece SlideStar;

private float starProg;
private Vector2? previousPosition;
public float StarProgress
{
get => starProg;
set
{
starProg = value;
SlideStar.Position = Slidepath.Path.PositionAt(value);
if (previousPosition == null)
SlideStar.Rotation = SlideStar.Position.GetDegreesFromPosition(Slidepath.Path.PositionAt(value + .001f));
else
SlideStar.Rotation = previousPosition.Value.GetDegreesFromPosition(SlideStar.Position);
previousPosition = SlideStar.Position;
SlideStar.Rotation = Slidepath.Path.PositionAt(value - .01f).GetDegreesFromPosition(Slidepath.Path.PositionAt(value + .01f));
}
}

public DrawableSlideBody() : this(null) { }
public DrawableSlideBody(SlideBody hitObject)
: base(hitObject) { }

[BackgroundDependencyLoader]
[BackgroundDependencyLoader(true)]
private void load()
{
Size = Vector2.Zero;
Expand All @@ -57,10 +55,7 @@ private void load()
Rotation = -22.5f;
AddRangeInternal(new Drawable[]
{
Slidepath = new SlideVisual
{
Alpha = 0,
},
Slidepath = new SlideVisual(),
new Container{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Expand All @@ -72,7 +67,6 @@ private void load()
Origin = Anchor.Centre,
Position = SentakkiExtensions.GetCircularPosition(296.5f,22.5f),
RelativeSizeAxes = Axes.None,
Size = new Vector2(75),
}
},
SlideNodes = new Container<DrawableSlideNode>
Expand All @@ -92,7 +86,7 @@ protected override void OnApply()
base.OnApply();
Slidepath.Path = HitObject.SlideInfo.SlidePath.Path;
updatePathProgress();
previousPosition = null;
StarProgress = 0;

AccentColour.BindTo(ParentHitObject.AccentColour);
}
Expand Down Expand Up @@ -126,20 +120,21 @@ private void updatePathProgress()
{
var target = SlideNodes.LastOrDefault(x => x.Result.IsHit);
if (target == null)
Slidepath.Progress = 0;
else Slidepath.Progress = target.HitObject.Progress;
Slidepath.CompletedSegments = 0;
else
Slidepath.CompletedSegments = target.ThisIndex + 1;

pendingProgressUpdate = false;
}

protected override void UpdateInitialTransforms()
{
base.UpdateInitialTransforms();
Slidepath.FadeInFromZero(AdjustedAnimationDuration / 2);
Slidepath.PerformEntryAnimation(AdjustedAnimationDuration);
using (BeginAbsoluteSequence(HitObject.StartTime - 50, true))
{
SlideStar.FadeInFromZero(100).ScaleTo(1, 100);
this.Delay(100 + HitObject.ShootDelay).TransformTo(nameof(StarProgress), 1f, (HitObject as IHasDuration).Duration - 50 - HitObject.ShootDelay);
SlideStar.FadeInFromZero(HitObject.ShootDelay).ScaleTo(1.25f, HitObject.ShootDelay);
this.Delay(50 + HitObject.ShootDelay).TransformTo(nameof(StarProgress), 1f, (HitObject as IHasDuration).Duration - HitObject.ShootDelay);
}
}

Expand Down Expand Up @@ -180,9 +175,16 @@ protected override void UpdateHitStateTransforms(ArmedState state)
switch (state)
{
case ArmedState.Hit:
SlideStar.FadeOut();
using (BeginAbsoluteSequence(Math.Max(Result.TimeAbsolute, HitObject.GetEndTime() - HitObject.HitWindows.WindowFor(HitResult.Great))))
{
Slidepath.PerformExitAnimation(200);
SlideStar.FadeOut(200);
this.FadeOut(200).Expire();
}

break;
case ArmedState.Miss:
Slidepath.PerformExitAnimation(time_fade_miss);
this.FadeColour(Color4.Red, time_fade_miss, Easing.OutQuint).FadeOut(time_fade_miss).Expire();
break;
}
Expand Down
17 changes: 10 additions & 7 deletions osu.Game.Rulesets.Sentakki/Objects/Drawables/DrawableSlideNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ public class DrawableSlideNode : DrawableSentakkiHitObject
private DrawableSlideBody parentSlide => (DrawableSlideBody)ParentHitObject;

// Used to determine the node order
private int thisIndex;
public int ThisIndex;

// Hits are only possible if this the second node before this one is hit
// If the second node before this one doesn't exist, it is allowed as this is one of the first nodes
// All hits can only be done after the parent StartTime
protected bool IsHittable => Time.Current > parentSlide.HitObject.StartTime && (thisIndex < 2 || parentSlide.SlideNodes[thisIndex - 2].IsHit);
protected bool IsHittable => Time.Current > parentSlide.HitObject.StartTime && (ThisIndex < 2 || parentSlide.SlideNodes[ThisIndex - 2].IsHit);

public DrawableSlideNode() : this(null) { }
public DrawableSlideNode(SlideBody.SlideNode node)
Expand All @@ -32,9 +32,9 @@ public DrawableSlideNode(SlideBody.SlideNode node)
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
RelativeSizeAxes = Axes.None;
Size = new Vector2(240);
Size = new Vector2(200);
CornerExponent = 2f;
CornerRadius = 120;
CornerRadius = 100;
Masking = true;
}

Expand All @@ -45,7 +45,10 @@ protected override void OnApply()

// Nodes are applied before being added to the parent playfield, so this node isn't in SlideNodes yet
// Since we know that the node isn't in the container yet, and that the count is always one higher than the topmost element, we can use that as the predicted index
thisIndex = parentSlide.SlideNodes.Count;
ThisIndex = parentSlide.SlideNodes.Count;

// To ensure it exists as soon as it should
LifetimeStart = parentSlide.HitObject.StartTime;
}

protected override void CheckForResult(bool userTriggered, double timeOffset)
Expand Down Expand Up @@ -75,8 +78,8 @@ protected override void Update()
protected override void ApplyResult(Action<JudgementResult> application)
{
// Judge the previous node, because that isn't guaranteed due to the leniency;
if (thisIndex > 0)
parentSlide.SlideNodes[thisIndex - 1]?.ApplyResult(application);
if (ThisIndex > 0)
parentSlide.SlideNodes[ThisIndex - 1]?.ApplyResult(application);

base.ApplyResult(application);
}
Expand Down
Loading

0 comments on commit c98e7b3

Please sign in to comment.