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:
parent
e9804bf11b
commit
949e17cc0e
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user