1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 07:07:45 +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.Extensions.IEnumerableExtensions;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Skinning; using osu.Game.Rulesets.Taiko.Skinning;
@ -12,11 +13,28 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
{ {
public class TestSceneTaikoScroller : TaikoSkinnableTestScene public class TestSceneTaikoScroller : TaikoSkinnableTestScene
{ {
private readonly ManualClock clock = new ManualClock();
private bool reversed;
public TestSceneTaikoScroller() 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 = AddToggleStep("Toggle passing", passing => this.ChildrenOfType<LegacyTaikoScroller>().ForEach(s => s.LastResult.Value =
new JudgementResult(null, new Judgement()) { Type = passing ? HitResult.Perfect : HitResult.Miss })); 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 public class LegacyTaikoScroller : CompositeDrawable
{ {
[Resolved(canBeNull: true)]
private GameplayClock gameplayClock { get; set; }
public LegacyTaikoScroller() public LegacyTaikoScroller()
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
@ -59,31 +56,42 @@ namespace osu.Game.Rulesets.Taiko.Skinning
{ {
base.Update(); 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();
foreach (var sprite in InternalChildren) while (!wideEnough())
{ AddInternal(new ScrollerSprite { Passing = passing });
// 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; var first = InternalChildren.First();
var last = InternalChildren.Last();
if (sprite.X + sprite.DrawWidth < 0) foreach (var sprite in InternalChildren)
sprite.Expire(); {
} // add the x coordinates and perform re-layout on all sprites as spacing may change with gameplay scale.
sprite.X = currentX;
currentX += sprite.DrawWidth - 1;
}
var last = InternalChildren.LastOrDefault(); if (first.ScreenSpaceDrawQuad.TopLeft.X >= ScreenSpaceDrawQuad.TopLeft.X)
{
foreach (var internalChild in InternalChildren)
internalChild.X -= first.DrawWidth;
}
// only break from this loop once we have saturated horizontal space completely. if (last.ScreenSpaceDrawQuad.TopRight.X <= ScreenSpaceDrawQuad.TopRight.X)
if (last != null && last.ScreenSpaceDrawQuad.TopRight.X >= ScreenSpaceDrawQuad.TopRight.X) {
break; foreach (var internalChild in InternalChildren)
internalChild.X += first.DrawWidth;
AddInternal(new ScrollerSprite
{
Passing = passing
});
} }
} }

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))); 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, RelativeSizeAxes = Axes.X,
Depth = float.MaxValue Depth = float.MaxValue