diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs index c0ff0e520a..20bb937b76 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -128,9 +128,11 @@ namespace osu.Game.Modes.Osu.Objects.Drawables case ArmedState.Idle: Delay(duration + TIME_PREEMPT); FadeOut(TIME_FADEOUT); + Expire(true); break; case ArmedState.Miss: FadeOut(TIME_FADEOUT / 5); + Expire(); break; case ArmedState.Hit: const double flash_in = 40; @@ -150,6 +152,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables FadeOut(800); ScaleTo(Scale * 1.5f, 400, EasingTypes.OutQuad); + Expire(); break; } } diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs index 5df2e26bc3..a2a52c7d94 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs @@ -168,6 +168,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables ball.FadeOut(160); FadeOut(800); + + Expire(); } public Drawable ProxiedLayer => initialCircle.ApproachCircle; diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs index 97df378f86..77bfb97ad4 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs @@ -146,9 +146,11 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { case ArmedState.Hit: ScaleTo(Scale * 1.2f, 320, EasingTypes.Out); + Expire(); break; case ArmedState.Miss: ScaleTo(Scale * 0.8f, 320, EasingTypes.In); + Expire(); break; } } diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 3230010fda..d78c347f22 100644 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -7,13 +7,13 @@ using System.Collections.Generic; namespace osu.Game.Modes.Taiko.Beatmaps { - internal class TaikoBeatmapConverter : IBeatmapConverter + internal class TaikoBeatmapConverter : IBeatmapConverter { - public Beatmap Convert(Beatmap original) + public Beatmap Convert(Beatmap original) { - return new Beatmap(original) + return new Beatmap(original) { - HitObjects = new List() // Todo: Implement + HitObjects = new List() // Todo: Implement }; } } diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapProcessor.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapProcessor.cs index 9a244cd23e..84bc470e55 100644 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapProcessor.cs +++ b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapProcessor.cs @@ -6,13 +6,13 @@ using osu.Game.Modes.Taiko.Objects; namespace osu.Game.Modes.Taiko.Beatmaps { - internal class TaikoBeatmapProcessor : IBeatmapProcessor + internal class TaikoBeatmapProcessor : IBeatmapProcessor { - public void SetDefaults(TaikoBaseHit hitObject, Beatmap beatmap) + public void SetDefaults(TaikoHitObject hitObject, Beatmap beatmap) { } - public void PostProcess(Beatmap beatmap) + public void PostProcess(Beatmap beatmap) { } } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHit.cs index a54108afda..760977ef5b 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHit.cs @@ -12,9 +12,9 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { internal class DrawableTaikoHit : Sprite { - private TaikoBaseHit h; + private TaikoHitObject h; - public DrawableTaikoHit(TaikoBaseHit h) + public DrawableTaikoHit(TaikoHitObject h) { this.h = h; diff --git a/osu.Game.Modes.Taiko/Objects/TaikoBaseHit.cs b/osu.Game.Modes.Taiko/Objects/TaikoBaseHit.cs deleted file mode 100644 index 4077c1933a..0000000000 --- a/osu.Game.Modes.Taiko/Objects/TaikoBaseHit.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Modes.Objects; - -namespace osu.Game.Modes.Taiko.Objects -{ - public class TaikoBaseHit : HitObject - { - public float Scale = 1; - - public TaikoColour Type; - } - - public enum TaikoColour - { - Red, - Blue - } -} diff --git a/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs new file mode 100644 index 0000000000..61d8ed5f01 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs @@ -0,0 +1,59 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps.Timing; +using osu.Game.Database; +using osu.Game.Modes.Objects; + +namespace osu.Game.Modes.Taiko.Objects +{ + public class TaikoHitObject : HitObject + { + /// + /// HitCircle radius. + /// + public const float CIRCLE_RADIUS = 64; + + /// + /// The hit window that results in a "GREAT" hit. + /// + public double HitWindowGreat = 35; + + /// + /// The hit window that results in a "GOOD" hit. + /// + public double HitWindowGood = 80; + + /// + /// The hit window that results in a "MISS". + /// + public double HitWindowMiss = 95; + + /// + /// The time to scroll in the HitObject. + /// + public double PreEmpt; + + /// + /// Whether this HitObject is in Kiai time. + /// + public bool Kiai; + + public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty) + { + base.ApplyDefaults(timing, difficulty); + + PreEmpt = 600 / (timing.SliderVelocityAt(StartTime) * difficulty.SliderMultiplier) * 1000; + + ControlPoint overridePoint; + Kiai = timing.TimingPointAt(StartTime, out overridePoint).KiaiMode; + + if (overridePoint != null) + Kiai |= overridePoint.KiaiMode; + + HitWindowGreat = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 50, 35, 20); + HitWindowGood = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 120, 80, 50); + HitWindowMiss = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 135, 95, 70); + } + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/Objects/TaikoHitType.cs b/osu.Game.Modes.Taiko/Objects/TaikoHitType.cs new file mode 100644 index 0000000000..adf3a67246 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/TaikoHitType.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; + +namespace osu.Game.Modes.Taiko.Objects +{ + [Flags] + public enum TaikoHitType + { + None = 0, + CentreHit = 1 << 0, + RimHit = 1 << 1, + DrumRoll = 1 << 2, + DrumRollTick = 1 << 3, + Bash = 1 << 4, + Finisher = 1 << 5, + + Hit = CentreHit | RimHit + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/TaikoDifficultyCalculator.cs b/osu.Game.Modes.Taiko/TaikoDifficultyCalculator.cs index 4a133ea896..93dfc3d651 100644 --- a/osu.Game.Modes.Taiko/TaikoDifficultyCalculator.cs +++ b/osu.Game.Modes.Taiko/TaikoDifficultyCalculator.cs @@ -8,7 +8,7 @@ using System.Collections.Generic; namespace osu.Game.Modes.Taiko { - public class TaikoDifficultyCalculator : DifficultyCalculator + public class TaikoDifficultyCalculator : DifficultyCalculator { public TaikoDifficultyCalculator(Beatmap beatmap) : base(beatmap) { @@ -19,6 +19,6 @@ namespace osu.Game.Modes.Taiko return 0; } - protected override IBeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); + protected override IBeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); } } \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/TaikoScoreProcessor.cs b/osu.Game.Modes.Taiko/TaikoScoreProcessor.cs index 1e5c70cd2e..849c0fa894 100644 --- a/osu.Game.Modes.Taiko/TaikoScoreProcessor.cs +++ b/osu.Game.Modes.Taiko/TaikoScoreProcessor.cs @@ -7,13 +7,13 @@ using osu.Game.Modes.UI; namespace osu.Game.Modes.Taiko { - internal class TaikoScoreProcessor : ScoreProcessor + internal class TaikoScoreProcessor : ScoreProcessor { public TaikoScoreProcessor() { } - public TaikoScoreProcessor(HitRenderer hitRenderer) + public TaikoScoreProcessor(HitRenderer hitRenderer) : base(hitRenderer) { } diff --git a/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs b/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs index 385b0915f4..80e42cb976 100644 --- a/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs +++ b/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs @@ -10,7 +10,7 @@ using osu.Game.Modes.UI; namespace osu.Game.Modes.Taiko.UI { - public class TaikoHitRenderer : HitRenderer + public class TaikoHitRenderer : HitRenderer { public TaikoHitRenderer(WorkingBeatmap beatmap) : base(beatmap) @@ -19,12 +19,12 @@ namespace osu.Game.Modes.Taiko.UI public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); - protected override IBeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); + protected override IBeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); - protected override IBeatmapProcessor CreateBeatmapProcessor() => new TaikoBeatmapProcessor(); + protected override IBeatmapProcessor CreateBeatmapProcessor() => new TaikoBeatmapProcessor(); - protected override Playfield CreatePlayfield() => new TaikoPlayfield(); + protected override Playfield CreatePlayfield() => new TaikoPlayfield(); - protected override DrawableHitObject GetVisualRepresentation(TaikoBaseHit h) => null; + protected override DrawableHitObject GetVisualRepresentation(TaikoHitObject h) => null; } } diff --git a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs index d80aa94fa1..f3ae600501 100644 --- a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs @@ -13,7 +13,7 @@ using osu.Game.Modes.Taiko.Judgements; namespace osu.Game.Modes.Taiko.UI { - public class TaikoPlayfield : Playfield + public class TaikoPlayfield : Playfield { public TaikoPlayfield() { diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index bc38781b01..0e9e6a56b4 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -50,9 +50,10 @@ + - + diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index fc8bb751f9..5709bdc8c5 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -43,21 +43,6 @@ namespace osu.Game.Beatmaps TimingInfo = original?.TimingInfo ?? TimingInfo; ComboColors = original?.ComboColors ?? ComboColors; } - - /// - /// Finds the slider velocity at a time. - /// - /// The time to find the slider velocity at. - /// The slider velocity in positional length units. - public double SliderVelocityAt(double time) - { - double scoringDistance = 100 * BeatmapInfo.Difficulty.SliderMultiplier; - double beatDistance = TimingInfo.BeatDistanceAt(time); - - if (beatDistance > 0) - return scoringDistance / beatDistance * 1000; - return scoringDistance; - } } /// @@ -70,5 +55,14 @@ namespace osu.Game.Beatmaps /// /// The star difficulty. public double CalculateStarDifficulty() => Ruleset.GetRuleset(BeatmapInfo.Mode).CreateDifficultyCalculator(this).Calculate(); + + /// + /// Constructs a new beatmap. + /// + /// The original beatmap to use the parameters of. + public Beatmap(Beatmap original = null) + : base(original) + { + } } } diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index efdcea4b41..af90e35da7 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -10,6 +10,7 @@ using osu.Game.Beatmaps.Samples; using osu.Game.Beatmaps.Timing; using osu.Game.Modes; using osu.Game.Modes.Objects; +using osu.Game.Beatmaps.Legacy; namespace osu.Game.Beatmaps.Formats { @@ -244,6 +245,16 @@ namespace osu.Game.Beatmaps.Formats } } + protected override Beatmap ParseFile(TextReader stream) + { + return new LegacyBeatmap(base.ParseFile(stream)); + } + + public override Beatmap Decode(TextReader stream) + { + return new LegacyBeatmap(base.Decode(stream)); + } + protected override void ParseFile(TextReader stream, Beatmap beatmap) { HitObjectParser parser = null; diff --git a/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs b/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs new file mode 100644 index 0000000000..0b8b13f902 --- /dev/null +++ b/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Beatmaps.Legacy +{ + /// + /// A type of Beatmap loaded from a legacy .osu beatmap file (version <=15). + /// + public class LegacyBeatmap : Beatmap + { + /// + /// Constructs a new beatmap. + /// + /// The original beatmap to use the parameters of. + internal LegacyBeatmap(Beatmap original = null) + : base(original) + { + HitObjects = original?.HitObjects; + } + } +} diff --git a/osu.Game/Beatmaps/Timing/TimingInfo.cs b/osu.Game/Beatmaps/Timing/TimingInfo.cs index f245a6b1aa..0e47ba983b 100644 --- a/osu.Game/Beatmaps/Timing/TimingInfo.cs +++ b/osu.Game/Beatmaps/Timing/TimingInfo.cs @@ -102,5 +102,21 @@ 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/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 41c807ba9e..3ff30bd90e 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -34,12 +34,11 @@ namespace osu.Game.Modes.Objects.Drawables set { - if (state == value) return; + if (state == value) + return; state = value; UpdateState(state); - if (IsLoaded) - Expire(); if (State == ArmedState.Hit) PlaySample(); @@ -63,8 +62,6 @@ namespace osu.Game.Modes.Objects.Drawables //force application of the state that was set before we loaded. UpdateState(State); - - Expire(true); } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 658b162bbb..188d929888 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -75,6 +75,7 @@ +