1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-14 19:47:24 +08:00

Merge pull request #1095 from smoogipooo/taiko-timingchanges-2

Make taiko use the new ScrollingPlayfield.
This commit is contained in:
Dean Herbert 2017-08-18 22:51:07 +09:00 committed by GitHub
commit 1249cc8eb9
16 changed files with 123 additions and 157 deletions

View File

@ -14,6 +14,9 @@ using osu.Game.Rulesets.Taiko.UI;
using OpenTK; using OpenTK;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Desktop.Tests.Beatmaps;
using System.Collections.Generic;
using osu.Game.Rulesets.Objects;
namespace osu.Desktop.Tests.Visual namespace osu.Desktop.Tests.Visual
{ {
@ -27,7 +30,7 @@ namespace osu.Desktop.Tests.Visual
protected override double TimePerAction => default_duration * 2; protected override double TimePerAction => default_duration * 2;
private readonly Random rng = new Random(1337); private readonly Random rng = new Random(1337);
private readonly TaikoPlayfield playfield; private readonly TaikoRulesetContainer rulesetContainer;
private readonly Container playfieldContainer; private readonly Container playfieldContainer;
public TestCaseTaikoPlayfield() public TestCaseTaikoPlayfield()
@ -51,6 +54,25 @@ namespace osu.Desktop.Tests.Visual
AddStep("Height test 5", () => changePlayfieldSize(5)); AddStep("Height test 5", () => changePlayfieldSize(5));
AddStep("Reset height", () => changePlayfieldSize(6)); AddStep("Reset height", () => changePlayfieldSize(6));
var controlPointInfo = new ControlPointInfo();
controlPointInfo.TimingPoints.Add(new TimingControlPoint());
WorkingBeatmap beatmap = new TestWorkingBeatmap(new Beatmap
{
HitObjects = new List<HitObject> { new CentreHit() },
BeatmapInfo = new BeatmapInfo
{
Difficulty = new BeatmapDifficulty(),
Metadata = new BeatmapMetadata
{
Artist = @"Unknown",
Title = @"Sample Beatmap",
Author = @"peppy",
},
},
ControlPointInfo = controlPointInfo
});
var rateAdjustClock = new StopwatchClock(true) { Rate = 1 }; var rateAdjustClock = new StopwatchClock(true) { Rate = 1 };
Add(playfieldContainer = new Container Add(playfieldContainer = new Container
@ -58,12 +80,9 @@ namespace osu.Desktop.Tests.Visual
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = TaikoPlayfield.DEFAULT_HEIGHT, Height = 768,
Clock = new FramedClock(rateAdjustClock), Clock = new FramedClock(rateAdjustClock),
Children = new[] Children = new[] { rulesetContainer = new TaikoRulesetContainer(null, beatmap, true) }
{
playfield = new TaikoPlayfield()
}
}); });
} }
@ -128,18 +147,18 @@ namespace osu.Desktop.Tests.Visual
} }
}; };
playfield.OnJudgement(h); rulesetContainer.Playfield.OnJudgement(h);
if (RNG.Next(10) == 0) if (RNG.Next(10) == 0)
{ {
h.Judgement.SecondHit = true; h.Judgement.SecondHit = true;
playfield.OnJudgement(h); rulesetContainer.Playfield.OnJudgement(h);
} }
} }
private void addMissJudgement() private void addMissJudgement()
{ {
playfield.OnJudgement(new DrawableTestHit(new Hit()) rulesetContainer.Playfield.OnJudgement(new DrawableTestHit(new Hit())
{ {
Judgement = new TaikoJudgement Judgement = new TaikoJudgement
{ {
@ -151,22 +170,17 @@ namespace osu.Desktop.Tests.Visual
private void addBarLine(bool major, double delay = scroll_time) private void addBarLine(bool major, double delay = scroll_time)
{ {
BarLine bl = new BarLine BarLine bl = new BarLine { StartTime = rulesetContainer.Playfield.Time.Current + delay };
{
StartTime = playfield.Time.Current + delay,
ScrollTime = scroll_time
};
playfield.AddBarLine(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl)); rulesetContainer.Playfield.Add(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl));
} }
private void addSwell(double duration = default_duration) private void addSwell(double duration = default_duration)
{ {
playfield.Add(new DrawableSwell(new Swell rulesetContainer.Playfield.Add(new DrawableSwell(new Swell
{ {
StartTime = playfield.Time.Current + scroll_time, StartTime = rulesetContainer.Playfield.Time.Current + scroll_time,
Duration = duration, Duration = duration,
ScrollTime = scroll_time
})); }));
} }
@ -177,43 +191,40 @@ namespace osu.Desktop.Tests.Visual
var d = new DrumRoll var d = new DrumRoll
{ {
StartTime = playfield.Time.Current + scroll_time, StartTime = rulesetContainer.Playfield.Time.Current + scroll_time,
IsStrong = strong, IsStrong = strong,
Duration = duration, Duration = duration,
ScrollTime = scroll_time,
}; };
playfield.Add(new DrawableDrumRoll(d)); rulesetContainer.Playfield.Add(new DrawableDrumRoll(d));
} }
private void addCentreHit(bool strong) private void addCentreHit(bool strong)
{ {
Hit h = new Hit Hit h = new Hit
{ {
StartTime = playfield.Time.Current + scroll_time, StartTime = rulesetContainer.Playfield.Time.Current + scroll_time,
ScrollTime = scroll_time,
IsStrong = strong IsStrong = strong
}; };
if (strong) if (strong)
playfield.Add(new DrawableCentreHitStrong(h)); rulesetContainer.Playfield.Add(new DrawableCentreHitStrong(h));
else else
playfield.Add(new DrawableCentreHit(h)); rulesetContainer.Playfield.Add(new DrawableCentreHit(h));
} }
private void addRimHit(bool strong) private void addRimHit(bool strong)
{ {
Hit h = new Hit Hit h = new Hit
{ {
StartTime = playfield.Time.Current + scroll_time, StartTime = rulesetContainer.Playfield.Time.Current + scroll_time,
ScrollTime = scroll_time,
IsStrong = strong IsStrong = strong
}; };
if (strong) if (strong)
playfield.Add(new DrawableRimHitStrong(h)); rulesetContainer.Playfield.Add(new DrawableRimHitStrong(h));
else else
playfield.Add(new DrawableRimHit(h)); rulesetContainer.Playfield.Add(new DrawableRimHit(h));
} }
private class DrawableTestHit : DrawableHitObject<TaikoHitObject, TaikoJudgement> private class DrawableTestHit : DrawableHitObject<TaikoHitObject, TaikoJudgement>

View File

@ -2,16 +2,17 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Taiko.Judgements;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {
/// <summary> /// <summary>
/// A line that scrolls alongside hit objects in the playfield and visualises control points. /// A line that scrolls alongside hit objects in the playfield and visualises control points.
/// </summary> /// </summary>
public class DrawableBarLine : Container public class DrawableBarLine : DrawableScrollingHitObject<TaikoHitObject, TaikoJudgement>
{ {
/// <summary> /// <summary>
/// The width of the line tracker. /// The width of the line tracker.
@ -34,15 +35,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
protected readonly BarLine BarLine; protected readonly BarLine BarLine;
public DrawableBarLine(BarLine barLine) public DrawableBarLine(BarLine barLine)
: base(barLine)
{ {
BarLine = barLine; BarLine = barLine;
Anchor = Anchor.CentreLeft; Anchor = Anchor.CentreLeft;
Origin = Anchor.Centre; Origin = Anchor.Centre;
RelativePositionAxes = Axes.X;
RelativeSizeAxes = Axes.Y; RelativeSizeAxes = Axes.Y;
Width = tracker_width; Width = tracker_width;
Children = new[] Children = new[]
@ -56,24 +56,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
Alpha = 0.75f Alpha = 0.75f
} }
}; };
LifetimeStart = BarLine.StartTime - BarLine.ScrollTime * 2;
LifetimeEnd = BarLine.StartTime + BarLine.ScrollTime;
} }
protected override void LoadComplete() protected override TaikoJudgement CreateJudgement() => new TaikoJudgement();
protected override void UpdateState(ArmedState state)
{ {
base.LoadComplete();
this.Delay(BarLine.StartTime - Time.Current).FadeOut(base_fadeout_time * BarLine.ScrollTime / 1000);
}
private void updateScrollPosition(double time) => this.MoveToX((float)((BarLine.StartTime - time) / BarLine.ScrollTime));
protected override void Update()
{
base.Update();
updateScrollPosition(Time.Current);
} }
} }
} }

View File

@ -11,6 +11,7 @@ using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {
@ -31,30 +32,29 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
public DrawableDrumRoll(DrumRoll drumRoll) public DrawableDrumRoll(DrumRoll drumRoll)
: base(drumRoll) : base(drumRoll)
{ {
RelativeSizeAxes = Axes.Y; Width = (float)HitObject.Duration;
AutoSizeAxes = Axes.X;
Container<DrawableDrumRollTick> tickContainer;
MainPiece.Add(tickContainer = new Container<DrawableDrumRollTick>
{
RelativeSizeAxes = Axes.Both,
RelativeChildOffset = new Vector2((float)HitObject.StartTime, 0),
RelativeChildSize = new Vector2((float)HitObject.Duration, 1)
});
foreach (var tick in drumRoll.Ticks) foreach (var tick in drumRoll.Ticks)
{ {
var newTick = new DrawableDrumRollTick(tick) var newTick = new DrawableDrumRollTick(tick);
{
X = (float)((tick.StartTime - HitObject.StartTime) / HitObject.Duration)
};
newTick.OnJudgement += onTickJudgement; newTick.OnJudgement += onTickJudgement;
AddNested(newTick); AddNested(newTick);
MainPiece.Add(newTick); tickContainer.Add(newTick);
} }
} }
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement { SecondHit = HitObject.IsStrong }; protected override TaikoJudgement CreateJudgement() => new TaikoJudgement { SecondHit = HitObject.IsStrong };
protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece();
{
Length = (float)(HitObject.Duration / HitObject.ScrollTime),
PlayfieldLengthReference = () => Parent.DrawSize.X
};
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
@ -63,17 +63,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
accentDarkColour = colours.YellowDarker; accentDarkColour = colours.YellowDarker;
} }
protected override void LoadComplete()
{
base.LoadComplete();
// This is naive, however it's based on the reasoning that the hit target
// is further than mid point of the play field, so the time taken to scroll in should always
// be greater than the time taken to scroll out to the left of the screen.
// Thus, using PreEmpt here is enough for the drum roll to completely scroll out.
LifetimeEnd = HitObject.EndTime + HitObject.ScrollTime;
}
private void onTickJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgement> obj) private void onTickJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgement> obj)
{ {
if (obj.Judgement.Result == HitResult.Hit) if (obj.Judgement.Result == HitResult.Hit)

View File

@ -15,9 +15,21 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
public DrawableDrumRollTick(DrumRollTick tick) public DrawableDrumRollTick(DrumRollTick tick)
: base(tick) : base(tick)
{ {
// Because ticks aren't added by the ScrollingPlayfield, we need to set the following properties ourselves
RelativePositionAxes = Axes.X;
X = (float)tick.StartTime;
FillMode = FillMode.Fit; FillMode = FillMode.Fit;
} }
protected override void LoadComplete()
{
base.LoadComplete();
// We need to set this here because RelativeSizeAxes won't/can't set our size by default with a different RelativeChildSize
Width *= Parent.RelativeChildSize.X;
}
protected override TaikoPiece CreateMainPiece() => new TickPiece protected override TaikoPiece CreateMainPiece() => new TickPiece
{ {
Filled = HitObject.FirstTick Filled = HitObject.FirstTick
@ -47,11 +59,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
} }
} }
protected override void UpdateScrollPosition(double time)
{
// Ticks don't move
}
protected override bool HandleKeyPress(Key key) protected override bool HandleKeyPress(Key key)
{ {
return Judgement.Result == HitResult.None && UpdateJudgement(true); return Judgement.Result == HitResult.None && UpdateJudgement(true);

View File

@ -29,6 +29,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
FillMode = FillMode.Fit; FillMode = FillMode.Fit;
} }
protected override void LoadComplete()
{
base.LoadComplete();
// We need to set this here because RelativeSizeAxes won't/can't set our size by default with a different RelativeChildSize
Width *= Parent.RelativeChildSize.X;
}
protected override void CheckJudgement(bool userTriggered) protected override void CheckJudgement(bool userTriggered)
{ {
if (!userTriggered) if (!userTriggered)

View File

@ -118,7 +118,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
}); });
MainPiece.Add(symbol = new SwellSymbolPiece()); MainPiece.Add(symbol = new SwellSymbolPiece());
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -129,6 +128,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
targetRing.BorderColour = colours.YellowDark.Opacity(0.25f); targetRing.BorderColour = colours.YellowDark.Opacity(0.25f);
} }
protected override void LoadComplete()
{
base.LoadComplete();
// We need to set this here because RelativeSizeAxes won't/can't set our size by default with a different RelativeChildSize
Width *= Parent.RelativeChildSize.X;
}
protected override void CheckJudgement(bool userTriggered) protected override void CheckJudgement(bool userTriggered)
{ {
if (userTriggered) if (userTriggered)
@ -189,20 +196,22 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
Expire(); Expire();
} }
protected override void UpdateScrollPosition(double time) protected override void Update()
{ {
// Make the swell stop at the hit target base.Update();
double t = Math.Min(HitObject.StartTime, time);
// Make the swell stop at the hit target
X = (float)Math.Max(Time.Current, HitObject.StartTime);
double t = Math.Min(HitObject.StartTime, Time.Current);
if (t == HitObject.StartTime && !hasStarted) if (t == HitObject.StartTime && !hasStarted)
{ {
OnStart?.Invoke(); OnStart?.Invoke();
hasStarted = true; hasStarted = true;
} }
base.UpdateScrollPosition(t);
} }
protected override bool HandleKeyPress(Key key) protected override bool HandleKeyPress(Key key)
{ {
if (Judgement.Result != HitResult.None) if (Judgement.Result != HitResult.None)

View File

@ -12,7 +12,7 @@ using OpenTK.Input;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {
public abstract class DrawableTaikoHitObject<TaikoHitType> : DrawableHitObject<TaikoHitObject, TaikoJudgement> public abstract class DrawableTaikoHitObject<TaikoHitType> : DrawableScrollingHitObject<TaikoHitObject, TaikoJudgement>
where TaikoHitType : TaikoHitObject where TaikoHitType : TaikoHitObject
{ {
/// <summary> /// <summary>
@ -38,30 +38,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Size = new Vector2(HitObject.IsStrong ? TaikoHitObject.DEFAULT_STRONG_SIZE : TaikoHitObject.DEFAULT_SIZE); Size = new Vector2(HitObject.IsStrong ? TaikoHitObject.DEFAULT_STRONG_SIZE : TaikoHitObject.DEFAULT_SIZE);
RelativePositionAxes = Axes.X;
Add(MainPiece = CreateMainPiece()); Add(MainPiece = CreateMainPiece());
MainPiece.KiaiMode = HitObject.Kiai; MainPiece.KiaiMode = HitObject.Kiai;
LifetimeStart = HitObject.StartTime - HitObject.ScrollTime * 2;
} }
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement(); protected override TaikoJudgement CreateJudgement() => new TaikoJudgement();
protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(); protected virtual TaikoPiece CreateMainPiece() => new CirclePiece();
/// <summary>
/// Sets the scroll position of the DrawableHitObject relative to the offset between
/// a time value and the HitObject's StartTime.
/// </summary>
/// <param name="time"></param>
protected virtual void UpdateScrollPosition(double time) => X = (float)((HitObject.StartTime - time) / HitObject.ScrollTime);
protected override void Update()
{
UpdateScrollPosition(Time.Current);
}
protected virtual bool HandleKeyPress(Key key) => false; protected virtual bool HandleKeyPress(Key key) => false;
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)

View File

@ -1,23 +1,12 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
{ {
public class ElongatedCirclePiece : CirclePiece public class ElongatedCirclePiece : CirclePiece
{ {
/// <summary>
/// As we are being used to define the absolute size of hits, we need to be given a relative reference of our containing playfield container.
/// </summary>
public Func<float> PlayfieldLengthReference;
/// <summary>
/// The length of this piece as a multiple of the value returned by <see cref="PlayfieldLengthReference"/>
/// </summary>
public float Length;
public ElongatedCirclePiece() public ElongatedCirclePiece()
{ {
RelativeSizeAxes = Axes.Y; RelativeSizeAxes = Axes.Y;
@ -35,7 +24,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
Right = padding, Right = padding,
}; };
Width = (PlayfieldLengthReference?.Invoke() ?? 0) * Length + DrawHeight; Width = Parent.DrawSize.X + DrawHeight;
} }
} }
} }

View File

@ -80,7 +80,6 @@ namespace osu.Game.Rulesets.Taiko.Objects
ret.Add(new DrumRollTick ret.Add(new DrumRollTick
{ {
FirstTick = first, FirstTick = first,
ScrollTime = ScrollTime,
TickSpacing = tickSpacing, TickSpacing = tickSpacing,
StartTime = t, StartTime = t,
IsStrong = IsStrong, IsStrong = IsStrong,

View File

@ -24,16 +24,6 @@ namespace osu.Game.Rulesets.Taiko.Objects
/// </summary> /// </summary>
public const float DEFAULT_STRONG_SIZE = DEFAULT_SIZE * STRONG_SCALE; public const float DEFAULT_STRONG_SIZE = DEFAULT_SIZE * STRONG_SCALE;
/// <summary>
/// The time taken from the initial (off-screen) spawn position to the centre of the hit target for a <see cref="TimingControlPoint.BeatLength"/> of 1000ms.
/// </summary>
private const double scroll_time = 6000;
/// <summary>
/// Our adjusted <see cref="scroll_time"/> taking into consideration local <see cref="TimingControlPoint.BeatLength"/> and other speed multipliers.
/// </summary>
public double ScrollTime;
/// <summary> /// <summary>
/// Whether this HitObject is a "strong" type. /// Whether this HitObject is a "strong" type.
/// Strong hit objects give more points for hitting the hit object with both keys. /// Strong hit objects give more points for hitting the hit object with both keys.
@ -49,12 +39,8 @@ namespace osu.Game.Rulesets.Taiko.Objects
{ {
base.ApplyDefaults(controlPointInfo, difficulty); base.ApplyDefaults(controlPointInfo, difficulty);
TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime);
DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(StartTime);
EffectControlPoint effectPoint = controlPointInfo.EffectPointAt(StartTime); EffectControlPoint effectPoint = controlPointInfo.EffectPointAt(StartTime);
ScrollTime = scroll_time * (timingPoint.BeatLength * difficultyPoint.SpeedMultiplier / 1000) / difficulty.SliderMultiplier;
Kiai |= effectPoint.KiaiMode; Kiai |= effectPoint.KiaiMode;
} }
} }

View File

@ -18,7 +18,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables;
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.UI
{ {
public class TaikoPlayfield : Playfield<TaikoHitObject, TaikoJudgement> public class TaikoPlayfield : ScrollingPlayfield<TaikoHitObject, TaikoJudgement>
{ {
/// <summary> /// <summary>
/// Default height of a <see cref="TaikoPlayfield"/> when inside a <see cref="TaikoRulesetContainer"/>. /// Default height of a <see cref="TaikoPlayfield"/> when inside a <see cref="TaikoRulesetContainer"/>.
@ -35,14 +35,14 @@ namespace osu.Game.Rulesets.Taiko.UI
/// </summary> /// </summary>
private const float left_area_size = 240; private const float left_area_size = 240;
protected override Container<Drawable> Content => hitObjectContainer;
private readonly Container<HitExplosion> hitExplosionContainer; private readonly Container<HitExplosion> hitExplosionContainer;
private readonly Container<KiaiHitExplosion> kiaiExplosionContainer; private readonly Container<KiaiHitExplosion> kiaiExplosionContainer;
private readonly Container<DrawableBarLine> barLineContainer;
private readonly Container<DrawableTaikoJudgement> judgementContainer; private readonly Container<DrawableTaikoJudgement> judgementContainer;
private readonly Container hitObjectContainer; protected override Container<Drawable> Content => content;
private readonly Container content;
private readonly Container topLevelHitContainer; private readonly Container topLevelHitContainer;
private readonly Container overlayBackgroundContainer; private readonly Container overlayBackgroundContainer;
@ -52,6 +52,7 @@ namespace osu.Game.Rulesets.Taiko.UI
private readonly Box background; private readonly Box background;
public TaikoPlayfield() public TaikoPlayfield()
: base(Axes.X)
{ {
AddRangeInternal(new Drawable[] AddRangeInternal(new Drawable[]
{ {
@ -96,10 +97,6 @@ namespace osu.Game.Rulesets.Taiko.UI
FillMode = FillMode.Fit, FillMode = FillMode.Fit,
BlendingMode = BlendingMode.Additive, BlendingMode = BlendingMode.Additive,
}, },
barLineContainer = new Container<DrawableBarLine>
{
RelativeSizeAxes = Axes.Both,
},
new HitTarget new HitTarget
{ {
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
@ -107,7 +104,7 @@ namespace osu.Game.Rulesets.Taiko.UI
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit FillMode = FillMode.Fit
}, },
hitObjectContainer = new Container content = new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
}, },
@ -181,6 +178,8 @@ namespace osu.Game.Rulesets.Taiko.UI
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
} }
}); });
VisibleTimeRange.Value = 6000;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -205,11 +204,6 @@ namespace osu.Game.Rulesets.Taiko.UI
swell.OnStart += () => topLevelHitContainer.Add(swell.CreateProxy()); swell.OnStart += () => topLevelHitContainer.Add(swell.CreateProxy());
} }
public void AddBarLine(DrawableBarLine barLine)
{
barLineContainer.Add(barLine);
}
public override void OnJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgement> judgedObject) public override void OnJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgement> judgedObject)
{ {
bool wasHit = judgedObject.Judgement.Result == HitResult.Hit; bool wasHit = judgedObject.Judgement.Result == HitResult.Hit;
@ -230,7 +224,7 @@ namespace osu.Game.Rulesets.Taiko.UI
if (!secondHit) if (!secondHit)
{ {
if (judgedObject.X >= -0.05f && !(judgedObject is DrawableSwell)) if (judgedObject.X >= -0.05f && judgedObject is DrawableHit)
{ {
// If we're far enough away from the left stage, we should bring outselves in front of it // If we're far enough away from the left stage, we should bring outselves in front of it
topLevelHitContainer.Add(judgedObject.CreateProxy()); topLevelHitContainer.Add(judgedObject.CreateProxy());

View File

@ -21,7 +21,7 @@ using System.Linq;
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.UI
{ {
public class TaikoRulesetContainer : RulesetContainer<TaikoHitObject, TaikoJudgement> public class TaikoRulesetContainer : ScrollingRulesetContainer<TaikoPlayfield, TaikoHitObject, TaikoJudgement>
{ {
public TaikoRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) public TaikoRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset)
: base(ruleset, beatmap, isForCurrentRuleset) : base(ruleset, beatmap, isForCurrentRuleset)
@ -36,11 +36,6 @@ namespace osu.Game.Rulesets.Taiko.UI
private void loadBarLines() private void loadBarLines()
{ {
var taikoPlayfield = Playfield as TaikoPlayfield;
if (taikoPlayfield == null)
return;
TaikoHitObject lastObject = Beatmap.HitObjects[Beatmap.HitObjects.Count - 1]; TaikoHitObject lastObject = Beatmap.HitObjects[Beatmap.HitObjects.Count - 1];
double lastHitTime = 1 + (lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime; double lastHitTime = 1 + (lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime;
@ -72,7 +67,7 @@ namespace osu.Game.Rulesets.Taiko.UI
barLine.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.Difficulty); barLine.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.Difficulty);
bool isMajor = currentBeat % (int)currentPoint.TimeSignature == 0; bool isMajor = currentBeat % (int)currentPoint.TimeSignature == 0;
taikoPlayfield.AddBarLine(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine)); Playfield.Add(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine));
double bl = currentPoint.BeatLength; double bl = currentPoint.BeatLength;
if (bl < 800) if (bl < 800)

View File

@ -32,6 +32,8 @@ namespace osu.Game.Rulesets.Objects.Drawables
} }
} }
public override bool RemoveWhenNotAlive => false;
protected DrawableScrollingHitObject(TObject hitObject) protected DrawableScrollingHitObject(TObject hitObject)
: base(hitObject) : base(hitObject)
{ {

View File

@ -27,6 +27,8 @@ namespace osu.Game.Rulesets.Timing
/// </summary> /// </summary>
internal Axes ScrollingAxes; internal Axes ScrollingAxes;
public override bool RemoveWhenNotAlive => false;
/// <summary> /// <summary>
/// The control point that defines the speed adjustments for this container. This is set by the <see cref="SpeedAdjustmentContainer"/>. /// The control point that defines the speed adjustments for this container. This is set by the <see cref="SpeedAdjustmentContainer"/>.
/// </summary> /// </summary>

View File

@ -34,6 +34,8 @@ namespace osu.Game.Rulesets.Timing
/// </summary> /// </summary>
public Axes ScrollingAxes { get; internal set; } public Axes ScrollingAxes { get; internal set; }
public override bool RemoveWhenNotAlive => false;
/// <summary> /// <summary>
/// The <see cref="MultiplierControlPoint"/> that defines the speed adjustments. /// The <see cref="MultiplierControlPoint"/> that defines the speed adjustments.
/// </summary> /// </summary>

View File

@ -7,6 +7,7 @@ using System.Linq;
using OpenTK.Input; using OpenTK.Input;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Transforms; using osu.Framework.Graphics.Transforms;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
@ -154,7 +155,7 @@ namespace osu.Game.Rulesets.UI
/// Hit objects that are to be re-processed on the next update. /// Hit objects that are to be re-processed on the next update.
/// </summary> /// </summary>
private readonly List<DrawableHitObject> queuedHitObjects = new List<DrawableHitObject>(); private readonly List<DrawableHitObject> queuedHitObjects = new List<DrawableHitObject>();
private readonly List<SpeedAdjustmentContainer> speedAdjustments = new List<SpeedAdjustmentContainer>(); private readonly Container<SpeedAdjustmentContainer> speedAdjustments;
private readonly Axes scrollingAxes; private readonly Axes scrollingAxes;
@ -165,6 +166,8 @@ namespace osu.Game.Rulesets.UI
public ScrollingHitObjectContainer(Axes scrollingAxes) public ScrollingHitObjectContainer(Axes scrollingAxes)
{ {
this.scrollingAxes = scrollingAxes; this.scrollingAxes = scrollingAxes;
AddInternal(speedAdjustments = new Container<SpeedAdjustmentContainer> { RelativeSizeAxes = Axes.Both });
} }
/// <summary> /// <summary>
@ -176,9 +179,7 @@ namespace osu.Game.Rulesets.UI
speedAdjustment.ScrollingAxes = scrollingAxes; speedAdjustment.ScrollingAxes = scrollingAxes;
speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange);
speedAdjustment.Reversed.BindTo(Reversed); speedAdjustment.Reversed.BindTo(Reversed);
speedAdjustments.Add(speedAdjustment); speedAdjustments.Add(speedAdjustment);
AddInternal(speedAdjustment);
} }
public override IEnumerable<DrawableHitObject> Objects => speedAdjustments.SelectMany(s => s.Children); public override IEnumerable<DrawableHitObject> Objects => speedAdjustments.SelectMany(s => s.Children);
@ -210,13 +211,13 @@ namespace osu.Game.Rulesets.UI
var hitObject = queuedHitObjects[i]; var hitObject = queuedHitObjects[i];
var target = adjustmentContainerFor(hitObject); var target = adjustmentContainerFor(hitObject);
if (target != null) if (target == null)
{ continue;
target.Add(hitObject); target.Add(hitObject);
queuedHitObjects.RemoveAt(i); queuedHitObjects.RemoveAt(i);
} }
} }
}
/// <summary> /// <summary>
/// Finds the <see cref="SpeedAdjustmentContainer"/> which provides the speed adjustment active at the start time /// Finds the <see cref="SpeedAdjustmentContainer"/> which provides the speed adjustment active at the start time