1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 15:27:24 +08:00

Rework scroller to support backwards playback

This commit is contained in:
Dean Herbert 2020-05-12 15:23:47 +09:00
parent e9804bf11b
commit 949e17cc0e
3 changed files with 50 additions and 24 deletions

View File

@ -3,6 +3,7 @@
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Skinning;
@ -12,11 +13,28 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
{
public class TestSceneTaikoScroller : TaikoSkinnableTestScene
{
private readonly ManualClock clock = new ManualClock();
private bool reversed;
public TestSceneTaikoScroller()
{
AddStep("Load scroller", () => SetContents(() => new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.TaikoScroller), _ => Empty())));
AddStep("Load scroller", () => SetContents(() =>
new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.TaikoScroller), _ => Empty())
{
Clock = new FramedClock(clock)
}));
AddToggleStep("Toggle passing", passing => this.ChildrenOfType<LegacyTaikoScroller>().ForEach(s => s.LastResult.Value =
new JudgementResult(null, new Judgement()) { Type = passing ? HitResult.Perfect : HitResult.Miss }));
AddToggleStep("toggle playback direction", reversed => this.reversed = reversed);
}
protected override void Update()
{
base.Update();
clock.CurrentTime += (reversed ? -1 : 1) * Clock.ElapsedFrameTime;
}
}
}

View File

@ -17,9 +17,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning
{
public class LegacyTaikoScroller : CompositeDrawable
{
[Resolved(canBeNull: true)]
private GameplayClock gameplayClock { get; set; }
public LegacyTaikoScroller()
{
RelativeSizeAxes = Axes.Both;
@ -59,31 +56,42 @@ namespace osu.Game.Rulesets.Taiko.Skinning
{
base.Update();
while (true)
bool wideEnough() =>
InternalChildren.Any()
&& InternalChildren.First().ScreenSpaceDrawQuad.Width * InternalChildren.Count >= ScreenSpaceDrawQuad.Width * 2;
// store X before checking wide enough so if we perform layout there is no positional discrepancy.
float currentX = (InternalChildren?.FirstOrDefault()?.X ?? 0) - (float)Clock.ElapsedFrameTime * 0.1f;
// ensure we have enough sprites
if (!wideEnough())
{
float? additiveX = null;
ClearInternal();
while (!wideEnough())
AddInternal(new ScrollerSprite { Passing = passing });
}
var first = InternalChildren.First();
var last = InternalChildren.Last();
foreach (var sprite in InternalChildren)
{
// add the x coordinates and perform re-layout on all sprites as spacing may change with gameplay scale.
sprite.X = additiveX ??= sprite.X - (float)(gameplayClock ?? Clock).ElapsedFrameTime * 0.1f;
additiveX += sprite.DrawWidth - 1;
if (sprite.X + sprite.DrawWidth < 0)
sprite.Expire();
sprite.X = currentX;
currentX += sprite.DrawWidth - 1;
}
var last = InternalChildren.LastOrDefault();
// only break from this loop once we have saturated horizontal space completely.
if (last != null && last.ScreenSpaceDrawQuad.TopRight.X >= ScreenSpaceDrawQuad.TopRight.X)
break;
AddInternal(new ScrollerSprite
if (first.ScreenSpaceDrawQuad.TopLeft.X >= ScreenSpaceDrawQuad.TopLeft.X)
{
Passing = passing
});
foreach (var internalChild in InternalChildren)
internalChild.X -= first.DrawWidth;
}
if (last.ScreenSpaceDrawQuad.TopRight.X <= ScreenSpaceDrawQuad.TopRight.X)
{
foreach (var internalChild in InternalChildren)
internalChild.X += first.DrawWidth;
}
}

View File

@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Taiko.UI
{
new BarLineGenerator<BarLine>(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar.Major ? new DrawableBarLineMajor(bar) : new DrawableBarLine(bar)));
AddInternal(scroller = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.TaikoScroller), _ => Empty())
FrameStableComponents.Add(scroller = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.TaikoScroller), _ => Empty())
{
RelativeSizeAxes = Axes.X,
Depth = float.MaxValue