diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs
index 74f59f3fdb..ecd6fe813e 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs
@@ -73,6 +73,16 @@ namespace osu.Desktop.VisualTests.Tests
});
}
+ private void addSwell()
+ {
+ playfield.Add(new DrawableSwell(new Swell
+ {
+ StartTime = Time.Current + 1000,
+ EndTime = Time.Current + 5000,
+ PreEmpt = 1000
+ }));
+ }
+
private void addDrumRoll(bool strong)
{
var d = new DrumRoll
@@ -85,16 +95,6 @@ namespace osu.Desktop.VisualTests.Tests
playfield.Add(strong ? new DrawableStrongDrumRoll(d) : new DrawableDrumRoll(d));
}
- private void addSwell()
- {
- playfield.Add(new DrawableSwell(new Swell
- {
- StartTime = Time.Current + 1000,
- EndTime = Time.Current + 5000,
- PreEmpt = 1000
- }));
- }
-
private void addCentreHit(bool strong)
{
Hit h = new Hit
diff --git a/osu.Game.Modes.Osu/Objects/Slider.cs b/osu.Game.Modes.Osu/Objects/Slider.cs
index 213a4a7bee..38d1dfda5d 100644
--- a/osu.Game.Modes.Osu/Objects/Slider.cs
+++ b/osu.Game.Modes.Osu/Objects/Slider.cs
@@ -14,6 +14,11 @@ namespace osu.Game.Modes.Osu.Objects
{
public class Slider : OsuHitObject, IHasCurve
{
+ ///
+ /// Scoring distance with a speed-adjusted beat length of 1 second.
+ ///
+ private const float base_scoring_distance = 100;
+
public IHasCurve CurveObject { get; set; }
public SliderCurve Curve => CurveObject.Curve;
@@ -51,13 +56,10 @@ namespace osu.Game.Modes.Osu.Objects
{
base.ApplyDefaults(timing, difficulty);
- ControlPoint overridePoint;
- ControlPoint timingPoint = timing.TimingPointAt(StartTime, out overridePoint);
- var velocityAdjustment = overridePoint?.VelocityAdjustment ?? 1;
- var baseVelocity = 100 * difficulty.SliderMultiplier / velocityAdjustment;
+ double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier / timing.SpeedMultiplierAt(StartTime);
- Velocity = baseVelocity / timingPoint.BeatLength;
- TickDistance = baseVelocity / difficulty.SliderTickRate;
+ Velocity = scoringDistance / timing.BeatLengthAt(StartTime);
+ TickDistance = scoringDistance / difficulty.SliderTickRate;
}
public IEnumerable Ticks
diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs
index cc361628a3..97acdeb3e6 100644
--- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs
+++ b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs
@@ -7,8 +7,10 @@ using osu.Game.Beatmaps.Samples;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Objects.Types;
using osu.Game.Modes.Taiko.Objects;
+using System;
using System.Collections.Generic;
using System.Linq;
+using osu.Game.Database;
namespace osu.Game.Modes.Taiko.Beatmaps
{
@@ -24,74 +26,100 @@ namespace osu.Game.Modes.Taiko.Beatmaps
return new Beatmap(original)
{
- HitObjects = convertHitObjects(original.HitObjects)
+ HitObjects = original.HitObjects.SelectMany(h => convertHitObject(h, original)).ToList()
};
}
- private List convertHitObjects(List hitObjects)
- {
- return hitObjects.Select(convertHitObject).ToList();
- }
-
- private TaikoHitObject convertHitObject(HitObject original)
+ private IEnumerable convertHitObject(HitObject obj, Beatmap beatmap)
{
// Check if this HitObject is already a TaikoHitObject, and return it if so
- TaikoHitObject originalTaiko = original as TaikoHitObject;
+ var originalTaiko = obj as TaikoHitObject;
if (originalTaiko != null)
- return originalTaiko;
+ yield return originalTaiko;
- IHasDistance distanceData = original as IHasDistance;
- IHasRepeats repeatsData = original as IHasRepeats;
- IHasEndTime endTimeData = original as IHasEndTime;
+ var distanceData = obj as IHasDistance;
+ var repeatsData = obj as IHasRepeats;
+ var endTimeData = obj as IHasEndTime;
// Old osu! used hit sounding to determine various hit type information
- SampleType sample = original.Sample?.Type ?? SampleType.None;
+ SampleType sample = obj.Sample?.Type ?? SampleType.None;
bool strong = (sample & SampleType.Finish) > 0;
if (distanceData != null)
{
- return new DrumRoll
+ double sv = beatmap.TimingInfo.SliderVelocityAt(obj.StartTime) * beatmap.BeatmapInfo.Difficulty.SliderMultiplier;
+
+ double l = distanceData.Distance * legacy_velocity_scale;
+ double v = sv * legacy_velocity_scale;
+ double bl = beatmap.TimingInfo.BeatLengthAt(obj.StartTime);
+
+ int repeats = repeatsData?.RepeatCount ?? 1;
+
+ double skipPeriod = Math.Min(bl / beatmap.BeatmapInfo.Difficulty.SliderTickRate, distanceData.Duration / repeats);
+
+ if (skipPeriod > 0 && l / v * 1000 < 2 * bl)
{
- StartTime = original.StartTime,
- Sample = original.Sample,
+ for (double j = obj.StartTime; j <= distanceData.EndTime + skipPeriod / 8; j += skipPeriod)
+ {
+ // Todo: This should generate different type of hits (including strongs)
+ // depending on hitobject sound additions (not implemented fully yet)
+ yield return new CentreHit
+ {
+ StartTime = obj.StartTime,
+ Sample = obj.Sample,
+ IsStrong = strong
+ };
+ }
+ }
+ else
+ {
+ yield return new DrumRoll
+ {
+ StartTime = obj.StartTime,
+ Sample = obj.Sample,
+ IsStrong = strong,
+ Distance = distanceData.Distance * (repeatsData?.RepeatCount ?? 1) * legacy_velocity_scale
+ };
+ }
+ }
+ else if (endTimeData != null)
+ {
+ double hitMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.OverallDifficulty, 3, 5, 7.5) * bash_convert_factor;
+
+ yield return new Swell
+ {
+ StartTime = obj.StartTime,
+ Sample = obj.Sample,
IsStrong = strong,
- Distance = distanceData.Distance * (repeatsData?.RepeatCount ?? 1)
+ EndTime = endTimeData.EndTime,
+ RequiredHits = (int)Math.Max(1, endTimeData.Duration / 1000 * hitMultiplier)
};
}
-
- if (endTimeData != null)
+ else
{
- // We compute the end time manually to add in the Bash convert factor
- return new Swell
+ bool isCentre = (sample & ~(SampleType.Finish | SampleType.Normal)) == 0;
+
+ if (isCentre)
{
- StartTime = original.StartTime,
- Sample = original.Sample,
- IsStrong = strong,
-
- EndTime = original.StartTime + endTimeData.Duration * bash_convert_factor
- };
- }
-
- bool isCentre = (sample & ~(SampleType.Finish | SampleType.Normal)) == 0;
-
- if (isCentre)
- {
- return new CentreHit
+ yield return new CentreHit
+ {
+ StartTime = obj.StartTime,
+ Sample = obj.Sample,
+ IsStrong = strong
+ };
+ }
+ else
{
- StartTime = original.StartTime,
- Sample = original.Sample,
- IsStrong = strong
- };
+ yield return new RimHit
+ {
+ StartTime = obj.StartTime,
+ Sample = obj.Sample,
+ IsStrong = strong,
+ };
+ }
}
-
- return new RimHit
- {
- StartTime = original.StartTime,
- Sample = original.Sample,
- IsStrong = strong,
- };
}
}
}
diff --git a/osu.Game.Modes.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Modes.Taiko/Judgements/TaikoJudgement.cs
index f4745730db..c2c4093b1b 100644
--- a/osu.Game.Modes.Taiko/Judgements/TaikoJudgement.cs
+++ b/osu.Game.Modes.Taiko/Judgements/TaikoJudgement.cs
@@ -43,7 +43,7 @@ namespace osu.Game.Modes.Taiko.Judgements
public override string MaxResultString => MAX_HIT_RESULT.GetDescription();
///
- /// Whether this Judgement has a secondary hit in the case of finishers.
+ /// Whether this Judgement has a secondary hit in the case of strong hits.
///
public virtual bool SecondHit { get; set; }
diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs
index 683d48df10..76eb6bb77d 100644
--- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs
+++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs
@@ -12,24 +12,20 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
{
protected override Key[] HitKeys { get; } = { Key.F, Key.J };
- private readonly CirclePiece circlePiece;
-
public DrawableCentreHit(Hit hit)
: base(hit)
{
- Add(circlePiece = new CirclePiece
- {
- Children = new[]
- {
- new CentreHitSymbolPiece()
- }
- });
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
- circlePiece.AccentColour = colours.PinkDarker;
+ Circle.AccentColour = colours.PinkDarker;
}
+
+ protected override CirclePiece CreateCirclePiece() => new CirclePiece
+ {
+ Children = new[] { new CentreHitSymbolPiece() }
+ };
}
}
diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRoll.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRoll.cs
index 4697625c5e..ea6b0043d7 100644
--- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRoll.cs
+++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRoll.cs
@@ -41,6 +41,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
Width = (float)(drumRoll.Duration / drumRoll.PreEmpt);
Add(circle = CreateCirclePiece());
+ circle.KiaiMode = HitObject.Kiai;
foreach (var tick in drumRoll.Ticks)
{
diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs
index c8a7355e3c..87f0e76f60 100644
--- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs
+++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs
@@ -6,6 +6,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Taiko.Judgements;
+using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
using System;
using System.Linq;
@@ -20,15 +21,17 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
protected override Container Content => bodyContainer;
+ protected readonly CirclePiece Circle;
+
private readonly Hit hit;
+ private readonly Container bodyContainer;
+
///
/// Whether the last key pressed is a valid hit key.
///
private bool validKeyPressed;
- private readonly Container bodyContainer;
-
protected DrawableHit(Hit hit)
: base(hit)
{
@@ -38,7 +41,13 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
+ Children = new[]
+ {
+ Circle = CreateCirclePiece()
+ }
});
+
+ Circle.KiaiMode = HitObject.Kiai;
}
protected override void CheckJudgement(bool userTriggered)
@@ -100,5 +109,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
Expire();
}
+
+ protected abstract CirclePiece CreateCirclePiece();
}
}
diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableRimHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableRimHit.cs
index cab6819300..893a6fbb4d 100644
--- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableRimHit.cs
+++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableRimHit.cs
@@ -12,24 +12,20 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
{
protected override Key[] HitKeys { get; } = { Key.D, Key.K };
- private readonly CirclePiece circlePiece;
-
public DrawableRimHit(Hit hit)
: base(hit)
{
- Add(circlePiece = new CirclePiece
- {
- Children = new[]
- {
- new RimHitSymbolPiece()
- }
- });
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
- circlePiece.AccentColour = colours.BlueDarker;
+ Circle.AccentColour = colours.BlueDarker;
}
+
+ protected override CirclePiece CreateCirclePiece() => new CirclePiece
+ {
+ Children = new[] { new RimHitSymbolPiece() }
+ };
}
}
diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs
index b4ec0b108a..bac44f48fb 100644
--- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs
+++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs
@@ -12,24 +12,20 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
{
protected override Key[] HitKeys { get; } = { Key.F, Key.J };
- private readonly CirclePiece circlePiece;
-
public DrawableStrongCentreHit(Hit hit)
: base(hit)
{
- Add(circlePiece = new StrongCirclePiece
- {
- Children = new []
- {
- new CentreHitSymbolPiece()
- }
- });
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
- circlePiece.AccentColour = colours.PinkDarker;
+ Circle.AccentColour = colours.PinkDarker;
}
+
+ protected override CirclePiece CreateCirclePiece() => new StrongCirclePiece
+ {
+ Children = new[] { new CentreHitSymbolPiece() }
+ };
}
}
diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongRimHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongRimHit.cs
index 1f77ad0409..985ba1c2df 100644
--- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongRimHit.cs
+++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongRimHit.cs
@@ -12,24 +12,20 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
{
protected override Key[] HitKeys { get; } = { Key.D, Key.K };
- private readonly CirclePiece circlePiece;
-
public DrawableStrongRimHit(Hit hit)
: base(hit)
{
- Add(circlePiece = new StrongCirclePiece
- {
- Children = new[]
- {
- new RimHitSymbolPiece()
- }
- });
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
- circlePiece.AccentColour = colours.BlueDarker;
+ Circle.AccentColour = colours.BlueDarker;
}
+
+ protected override CirclePiece CreateCirclePiece() => new StrongCirclePiece
+ {
+ Children = new[] { new RimHitSymbolPiece() }
+ };
}
}
diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs
index ccd6380542..ec1ab42bfc 100644
--- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs
+++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs
@@ -128,6 +128,8 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
}
}
};
+
+ circlePiece.KiaiMode = HitObject.Kiai;
}
[BackgroundDependencyLoader]
diff --git a/osu.Game.Modes.Taiko/Objects/DrumRoll.cs b/osu.Game.Modes.Taiko/Objects/DrumRoll.cs
index df8870ab97..ccf86654b5 100644
--- a/osu.Game.Modes.Taiko/Objects/DrumRoll.cs
+++ b/osu.Game.Modes.Taiko/Objects/DrumRoll.cs
@@ -13,6 +13,11 @@ namespace osu.Game.Modes.Taiko.Objects
{
public class DrumRoll : TaikoHitObject, IHasDistance
{
+ ///
+ /// Drum roll distance that results in a duration of 1 speed-adjusted beat length.
+ ///
+ private const float base_distance = 100;
+
public double EndTime => StartTime + Distance / Velocity;
public double Duration => EndTime - StartTime;
@@ -59,7 +64,7 @@ namespace osu.Game.Modes.Taiko.Objects
{
base.ApplyDefaults(timing, difficulty);
- Velocity = timing.SliderVelocityAt(StartTime) * difficulty.SliderMultiplier / 1000;
+ Velocity = base_distance * difficulty.SliderMultiplier * difficulty.SliderTickRate * timing.BeatLengthAt(StartTime) * timing.SpeedMultiplierAt(StartTime);
TickTimeDistance = timing.BeatLengthAt(StartTime);
//TODO: move this to legacy conversion code to allow for direct division without special case.
diff --git a/osu.Game.Modes.Taiko/Objects/Swell.cs b/osu.Game.Modes.Taiko/Objects/Swell.cs
index 4cbb5904c7..f55416509a 100644
--- a/osu.Game.Modes.Taiko/Objects/Swell.cs
+++ b/osu.Game.Modes.Taiko/Objects/Swell.cs
@@ -1,9 +1,6 @@
// Copyright (c) 2007-2017 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using System;
-using osu.Game.Beatmaps.Timing;
-using osu.Game.Database;
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Taiko.Objects
@@ -17,14 +14,6 @@ namespace osu.Game.Modes.Taiko.Objects
///
/// The number of hits required to complete the swell successfully.
///
- public int RequiredHits { get; protected set; } = 10;
-
- public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty)
- {
- base.ApplyDefaults(timing, difficulty);
-
- double spinnerRotationRatio = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 3, 5, 7.5);
- RequiredHits = (int)Math.Max(1, Duration / 1000f * spinnerRotationRatio);
- }
+ public int RequiredHits = 10;
}
}
\ No newline at end of file
diff --git a/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs
index ac47a3bc88..327c0402ab 100644
--- a/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs
+++ b/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs
@@ -14,6 +14,11 @@ namespace osu.Game.Modes.Taiko.Objects
///
public const float CIRCLE_RADIUS = 42f;
+ ///
+ /// Time (in milliseconds) to scroll in the hit object with a speed-adjusted beat length of 1 second.
+ ///
+ private const double base_scroll_time = 6000;
+
///
/// The time to scroll in the HitObject.
///
@@ -34,7 +39,7 @@ namespace osu.Game.Modes.Taiko.Objects
{
base.ApplyDefaults(timing, difficulty);
- PreEmpt = 600 / (timing.SliderVelocityAt(StartTime) * difficulty.SliderMultiplier) * 1000;
+ PreEmpt = base_scroll_time / difficulty.SliderMultiplier * timing.BeatLengthAt(StartTime) * timing.SpeedMultiplierAt(StartTime) / 1000;
ControlPoint overridePoint;
Kiai = timing.TimingPointAt(StartTime, out overridePoint).KiaiMode;
diff --git a/osu.Game.Modes.Taiko/UI/HitExplosion.cs b/osu.Game.Modes.Taiko/UI/HitExplosion.cs
index 94938a700d..eb43c1a5d0 100644
--- a/osu.Game.Modes.Taiko/UI/HitExplosion.cs
+++ b/osu.Game.Modes.Taiko/UI/HitExplosion.cs
@@ -18,12 +18,21 @@ namespace osu.Game.Modes.Taiko.UI
///
internal class HitExplosion : CircularContainer
{
- private readonly TaikoJudgement judgement;
+ ///
+ /// The size multiplier of a hit explosion if a hit object has been hit with the second key.
+ ///
+ private const float secondhit_size_multiplier = 1.5f;
+
+ ///
+ /// The judgement this hit explosion visualises.
+ ///
+ public readonly TaikoJudgement Judgement;
+
private readonly Box innerFill;
public HitExplosion(TaikoJudgement judgement)
{
- this.judgement = judgement;
+ Judgement = judgement;
Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2);
@@ -50,10 +59,7 @@ namespace osu.Game.Modes.Taiko.UI
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
- if (judgement.SecondHit)
- Size *= 1.5f;
-
- switch (judgement.TaikoResult)
+ switch (Judgement.TaikoResult)
{
case TaikoHitResult.Good:
innerFill.Colour = colours.Green;
@@ -73,5 +79,13 @@ namespace osu.Game.Modes.Taiko.UI
Expire();
}
+
+ ///
+ /// Transforms this hit explosion to visualise a secondary hit.
+ ///
+ public void VisualiseSecondHit()
+ {
+ ResizeTo(Size * secondhit_size_multiplier, 50);
+ }
}
}
diff --git a/osu.Game.Modes.Taiko/UI/HitTarget.cs b/osu.Game.Modes.Taiko/UI/HitTarget.cs
index 32b2877545..27562cd916 100644
--- a/osu.Game.Modes.Taiko/UI/HitTarget.cs
+++ b/osu.Game.Modes.Taiko/UI/HitTarget.cs
@@ -21,9 +21,9 @@ namespace osu.Game.Modes.Taiko.UI
private const float normal_diameter = TaikoHitObject.CIRCLE_RADIUS * 2;
///
- /// Diameter of finisher hit object circles.
+ /// Diameter of strong hit object circles.
///
- private const float finisher_diameter = normal_diameter * 1.5f;
+ private const float strong_hit_diameter = normal_diameter * 1.5f;
///
/// The 1px inner border of the taiko playfield.
@@ -47,15 +47,15 @@ namespace osu.Game.Modes.Taiko.UI
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Y = border_offset,
- Size = new Vector2(border_thickness, (TaikoPlayfield.PLAYFIELD_HEIGHT - finisher_diameter) / 2f - border_offset),
+ Size = new Vector2(border_thickness, (TaikoPlayfield.PLAYFIELD_HEIGHT - strong_hit_diameter) / 2f - border_offset),
Alpha = 0.1f
},
new CircularContainer
{
- Name = "Finisher Ring",
+ Name = "Strong Hit Ring",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
- Size = new Vector2(finisher_diameter),
+ Size = new Vector2(strong_hit_diameter),
Masking = true,
BorderColour = Color4.White,
BorderThickness = border_thickness,
@@ -72,7 +72,7 @@ namespace osu.Game.Modes.Taiko.UI
},
new CircularContainer
{
- Name = "Normal Ring",
+ Name = "Normal Hit Ring",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(normal_diameter),
@@ -96,7 +96,7 @@ namespace osu.Game.Modes.Taiko.UI
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
Y = -border_offset,
- Size = new Vector2(border_thickness, (TaikoPlayfield.PLAYFIELD_HEIGHT - finisher_diameter) / 2f - border_offset),
+ Size = new Vector2(border_thickness, (TaikoPlayfield.PLAYFIELD_HEIGHT - strong_hit_diameter) / 2f - border_offset),
Alpha = 0.1f
},
};
diff --git a/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs b/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs
index e70e2d3811..5640e1df30 100644
--- a/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs
+++ b/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs
@@ -2,15 +2,17 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
+using osu.Framework.Graphics;
using osu.Game.Modes.Objects.Drawables;
-using osu.Game.Modes.Replays;
using osu.Game.Modes.Scoring;
using osu.Game.Modes.Taiko.Beatmaps;
using osu.Game.Modes.Taiko.Judgements;
using osu.Game.Modes.Taiko.Objects;
-using osu.Game.Modes.Taiko.Replays;
+using osu.Game.Modes.Taiko.Objects.Drawable;
using osu.Game.Modes.Taiko.Scoring;
using osu.Game.Modes.UI;
+using osu.Game.Modes.Replays;
+using osu.Game.Modes.Taiko.Replays;
namespace osu.Game.Modes.Taiko.UI
{
@@ -27,9 +29,44 @@ namespace osu.Game.Modes.Taiko.UI
protected override IBeatmapProcessor CreateBeatmapProcessor() => new TaikoBeatmapProcessor();
- protected override Playfield CreatePlayfield() => new TaikoPlayfield();
+ protected override Playfield CreatePlayfield() => new TaikoPlayfield
+ {
+ Anchor = Anchor.CentreLeft,
+ Origin = Anchor.CentreLeft
+ };
- protected override DrawableHitObject GetVisualRepresentation(TaikoHitObject h) => null;
+ protected override DrawableHitObject GetVisualRepresentation(TaikoHitObject h)
+ {
+ var centreHit = h as CentreHit;
+ if (centreHit != null)
+ {
+ if (h.IsStrong)
+ return new DrawableStrongCentreHit(centreHit);
+ return new DrawableCentreHit(centreHit);
+ }
+
+ var rimHit = h as RimHit;
+ if (rimHit != null)
+ {
+ if (h.IsStrong)
+ return new DrawableStrongRimHit(rimHit);
+ return new DrawableRimHit(rimHit);
+ }
+
+ var drumRoll = h as DrumRoll;
+ if (drumRoll != null)
+ {
+ if (h.IsStrong)
+ return new DrawableStrongDrumRoll(drumRoll);
+ return new DrawableDrumRoll(drumRoll);
+ }
+
+ var swell = h as Swell;
+ if (swell != null)
+ return new DrawableSwell(swell);
+
+ return null;
+ }
protected override FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new TaikoFramedReplayInputHandler(replay);
}
diff --git a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs
index b6165b785b..c23d920eda 100644
--- a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs
+++ b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs
@@ -15,6 +15,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics.Primitives;
using osu.Game.Modes.Taiko.Objects.Drawable;
+using System.Linq;
namespace osu.Game.Modes.Taiko.UI
{
@@ -22,7 +23,7 @@ namespace osu.Game.Modes.Taiko.UI
{
///
/// The play field height. This is relative to the size of hit objects
- /// such that the playfield is just a bit larger than finishers.
+ /// such that the playfield is just a bit larger than strong hits.
///
public const float PLAYFIELD_HEIGHT = TaikoHitObject.CIRCLE_RADIUS * 2 * 2;
@@ -176,9 +177,7 @@ namespace osu.Game.Modes.Taiko.UI
public override void OnJudgement(DrawableHitObject judgedObject)
{
bool wasHit = judgedObject.Judgement.Result == HitResult.Hit;
-
- if (wasHit)
- hitExplosionContainer.Add(new HitExplosion(judgedObject.Judgement));
+ bool secondHit = judgedObject.Judgement.SecondHit;
judgementContainer.Add(new DrawableTaikoJudgement(judgedObject.Judgement)
{
@@ -187,6 +186,22 @@ namespace osu.Game.Modes.Taiko.UI
RelativePositionAxes = Axes.X,
X = wasHit ? judgedObject.Position.X : 0,
});
+
+ if (!wasHit)
+ return;
+
+ if (!secondHit)
+ {
+ if (judgedObject.X >= -0.05f && !(judgedObject is DrawableSwell))
+ {
+ // If we're far enough away from the left stage, we should bring outselves in front of it
+ topLevelHitContainer.Add(judgedObject.CreateProxy());
+ }
+
+ hitExplosionContainer.Add(new HitExplosion(judgedObject.Judgement));
+ }
+ else
+ hitExplosionContainer.Children.FirstOrDefault(e => e.Judgement == judgedObject.Judgement)?.VisualiseSecondHit();
}
}
}
\ No newline at end of file
diff --git a/osu.Game/Beatmaps/Timing/TimingInfo.cs b/osu.Game/Beatmaps/Timing/TimingInfo.cs
index 0e47ba983b..076618beea 100644
--- a/osu.Game/Beatmaps/Timing/TimingInfo.cs
+++ b/osu.Game/Beatmaps/Timing/TimingInfo.cs
@@ -20,11 +20,11 @@ namespace osu.Game.Beatmaps.Timing
}
///
- /// Finds the BPM multiplier at a time.
+ /// Finds the speed multiplier at a time.
///
- /// The time to find the BPM multiplier at.
- /// The BPM multiplier.
- public double BPMMultiplierAt(double time)
+ /// The time to find the speed multiplier at.
+ /// The speed multiplier.
+ public double SpeedMultiplierAt(double time)
{
ControlPoint overridePoint;
ControlPoint timingPoint = TimingPointAt(time, out overridePoint);
@@ -33,10 +33,10 @@ namespace osu.Game.Beatmaps.Timing
}
///
- /// Finds the beat length at a time.
+ /// Finds the beat length at a time. This is expressed in milliseconds.
///
/// The time to find the beat length at.
- /// The beat length in milliseconds.
+ /// The beat length.
public double BeatLengthAt(double time)
{
ControlPoint overridePoint;
@@ -45,32 +45,6 @@ namespace osu.Game.Beatmaps.Timing
return timingPoint.BeatLength;
}
- ///
- /// Finds the beat velocity at a time.
- ///
- /// The time to find the velocity at.
- /// The velocity.
- public double BeatVelocityAt(double time)
- {
- ControlPoint overridePoint;
- ControlPoint timingPoint = TimingPointAt(time, out overridePoint);
-
- return overridePoint?.VelocityAdjustment ?? timingPoint?.VelocityAdjustment ?? 1;
- }
-
- ///
- /// Finds the beat length at a time.
- ///
- /// The time to find the beat length at.
- /// The beat length in positional length units.
- public double BeatDistanceAt(double time)
- {
- ControlPoint overridePoint;
- ControlPoint timingPoint = TimingPointAt(time, out overridePoint);
-
- return (timingPoint?.BeatLength ?? 1) * (overridePoint?.VelocityAdjustment ?? timingPoint?.VelocityAdjustment ?? 1);
- }
-
///
/// Finds the timing point at a time.
///
@@ -102,21 +76,5 @@ namespace osu.Game.Beatmaps.Timing
return timingPoint ?? ControlPoint.Default;
}
-
- ///
- /// Finds the slider velocity at a time.
- ///
- /// The time to find the slider velocity at.
- /// The slider velocity in milliseconds.
- public double SliderVelocityAt(double time)
- {
- const double base_scoring_distance = 100;
-
- double beatDistance = BeatDistanceAt(time);
-
- if (beatDistance > 0)
- return base_scoring_distance / beatDistance * 1000;
- return base_scoring_distance;
- }
}
}
\ No newline at end of file
diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs
index 5bdb629393..c678e9bf37 100644
--- a/osu.Game/Screens/Play/Player.cs
+++ b/osu.Game/Screens/Play/Player.cs
@@ -64,7 +64,7 @@ namespace osu.Game.Screens.Play
{
var beatmap = Beatmap.Beatmap;
- if (beatmap.BeatmapInfo?.Mode > PlayMode.Osu)
+ if (beatmap.BeatmapInfo?.Mode > PlayMode.Taiko)
{
//we only support osu! mode for now because the hitobject parsing is crappy and needs a refactor.
Exit();