1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 07:42:57 +08:00

Centralise and share bar line generation code between rulesets (#6054)

Centralise and share bar line generation code between rulesets
This commit is contained in:
Dean Herbert 2019-09-10 19:31:29 +09:00 committed by GitHub
commit c27eed0195
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 89 additions and 114 deletions

View File

@ -15,6 +15,7 @@ using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI.Scrolling;
using osu.Game.Tests.Visual;
using osuTK;
@ -114,8 +115,7 @@ namespace osu.Game.Rulesets.Mania.Tests
var obj = new BarLine
{
StartTime = Time.Current + 2000,
ControlPoint = new TimingControlPoint(),
BeatIndex = major ? 0 : 1
Major = major,
};
obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());

View File

@ -1,21 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Beatmaps.ControlPoints;
namespace osu.Game.Rulesets.Mania.Objects
{
public class BarLine : ManiaHitObject
{
/// <summary>
/// The control point which this bar line is part of.
/// </summary>
public TimingControlPoint ControlPoint;
/// <summary>
/// The index of the beat which this bar line represents within the control point.
/// This is a "major" bar line if <see cref="BeatIndex"/> % <see cref="TimingControlPoint.TimeSignature"/> == 0.
/// </summary>
public int BeatIndex;
}
}

View File

@ -4,6 +4,7 @@
using osuTK;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osuTK.Graphics;
@ -13,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
/// Visualises a <see cref="BarLine"/>. Although this derives DrawableManiaHitObject,
/// this does not handle input/sound like a normal hit object.
/// </summary>
public class DrawableBarLine : DrawableManiaHitObject<BarLine>
public class DrawableBarLine : DrawableHitObject<BarLine>
{
/// <summary>
/// Height of major bar line triangles.
@ -40,9 +41,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
Colour = new Color4(255, 204, 33, 255),
});
bool isMajor = barLine.BeatIndex % (int)barLine.ControlPoint.TimeSignature == 0;
if (isMajor)
if (barLine.Major)
{
AddInternal(new EquilateralTriangle
{
@ -65,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
});
}
if (!isMajor && barLine.BeatIndex % 2 == 1)
if (!barLine.Major)
Alpha = 0.2f;
}

View File

@ -2,14 +2,11 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Input;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Input.Handlers;
using osu.Game.Replays;
using osu.Game.Rulesets.Mania.Beatmaps;
@ -19,8 +16,8 @@ using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Mania.Replays;
using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Mods;
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.UI;
using osu.Game.Rulesets.UI.Scrolling;
@ -45,33 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI
public DrawableManiaRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
: base(ruleset, beatmap, mods)
{
// Generate the bar lines
double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue;
var timingPoints = Beatmap.ControlPointInfo.TimingPoints;
var barLines = new List<BarLine>();
for (int i = 0; i < timingPoints.Count; i++)
{
TimingControlPoint point = timingPoints[i];
// Stop on the beat before the next timing point, or if there is no next timing point stop slightly past the last object
double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - point.BeatLength : lastObjectTime + point.BeatLength * (int)point.TimeSignature;
int index = 0;
for (double t = timingPoints[i].Time; Precision.DefinitelyBigger(endTime, t); t += point.BeatLength, index++)
{
barLines.Add(new BarLine
{
StartTime = t,
ControlPoint = point,
BeatIndex = index
});
}
}
BarLines = barLines;
BarLines = new BarLineGenerator(Beatmap).BarLines;
}
[BackgroundDependencyLoader]

View File

@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Linq;
using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.UI.Scrolling;
using osuTK;

View File

@ -12,6 +12,7 @@ using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.UI.Scrolling;

View File

@ -1,9 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Rulesets.Taiko.Objects
{
public class BarLine : TaikoHitObject
{
}
}

View File

@ -3,6 +3,7 @@
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Objects;
using osuTK;
using osu.Game.Rulesets.Objects.Drawables;
@ -11,7 +12,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
/// <summary>
/// A line that scrolls alongside hit objects in the playfield and visualises control points.
/// </summary>
public class DrawableBarLine : DrawableHitObject<TaikoHitObject>
public class DrawableBarLine : DrawableHitObject<HitObject>
{
/// <summary>
/// The width of the line tracker.

View File

@ -5,6 +5,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osuTK;
using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{

View File

@ -5,19 +5,18 @@ using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables;
using osu.Game.Rulesets.Taiko.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.Taiko.Replays;
using System.Linq;
using osu.Framework.Input;
using osu.Game.Configuration;
using osu.Game.Input.Handlers;
using osu.Game.Replays;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI.Scrolling;
namespace osu.Game.Rulesets.Taiko.UI
@ -38,49 +37,7 @@ namespace osu.Game.Rulesets.Taiko.UI
[BackgroundDependencyLoader]
private void load()
{
loadBarLines();
}
private void loadBarLines()
{
TaikoHitObject lastObject = Beatmap.HitObjects[Beatmap.HitObjects.Count - 1];
double lastHitTime = 1 + ((lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime);
var timingPoints = Beatmap.ControlPointInfo.TimingPoints.ToList();
if (timingPoints.Count == 0)
return;
int currentIndex = 0;
int currentBeat = 0;
double time = timingPoints[currentIndex].Time;
while (time <= lastHitTime)
{
int nextIndex = currentIndex + 1;
if (nextIndex < timingPoints.Count && time > timingPoints[nextIndex].Time)
{
currentIndex = nextIndex;
time = timingPoints[currentIndex].Time;
currentBeat = 0;
}
var currentPoint = timingPoints[currentIndex];
var barLine = new BarLine
{
StartTime = time,
};
barLine.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty);
bool isMajor = currentBeat % (int)currentPoint.TimeSignature == 0;
Playfield.Add(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine));
time += currentPoint.BeatLength * (int)currentPoint.TimeSignature;
currentBeat++;
}
new BarLineGenerator(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar.Major ? new DrawableBarLineMajor(bar) : new DrawableBarLine(bar)));
}
public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this);

View File

@ -0,0 +1,16 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Rulesets.Objects
{
/// <summary>
/// A hit object representing the end of a bar.
/// </summary>
public class BarLine : HitObject
{
/// <summary>
/// Whether this barline is a prominent beat (based on time signature of beatmap).
/// </summary>
public bool Major;
}
}

View File

@ -0,0 +1,58 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Linq;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Objects
{
public class BarLineGenerator
{
/// <summary>
/// The generated bar lines.
/// </summary>
public readonly List<BarLine> BarLines = new List<BarLine>();
/// <summary>
/// Constructs and generates bar lines for provided beatmap.
/// </summary>
/// <param name="beatmap">The beatmap to generate bar lines for.</param>
public BarLineGenerator(IBeatmap beatmap)
{
if (beatmap.HitObjects.Count == 0)
return;
HitObject lastObject = beatmap.HitObjects.Last();
double lastHitTime = 1 + ((lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime);
var timingPoints = beatmap.ControlPointInfo.TimingPoints;
if (timingPoints.Count == 0)
return;
for (int i = 0; i < timingPoints.Count; i++)
{
TimingControlPoint currentTimingPoint = timingPoints[i];
int currentBeat = 0;
// Stop on the beat before the next timing point, or if there is no next timing point stop slightly past the last object
double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - currentTimingPoint.BeatLength : lastHitTime + currentTimingPoint.BeatLength * (int)currentTimingPoint.TimeSignature;
double barLength = currentTimingPoint.BeatLength * (int)currentTimingPoint.TimeSignature;
for (double t = currentTimingPoint.Time; Precision.DefinitelyBigger(endTime, t); t += barLength, currentBeat++)
{
BarLines.Add(new BarLine
{
StartTime = t,
Major = currentBeat % (int)currentTimingPoint.TimeSignature == 0
});
}
}
}
}
}