From d51d0e85471722fa95b0e5d458cabfe09ada996f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 1 Aug 2018 21:04:03 +0900 Subject: [PATCH] Initial structure for new hitobject judgement system --- osu.Game/Rulesets/Judgements/Judgement.cs | 12 ++--- .../Objects/Drawables/DrawableHitObject.cs | 50 +++++++++++-------- osu.Game/Rulesets/Objects/HitObject.cs | 10 ++++ 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index 129dd07c3e..63378e57cc 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -28,19 +28,19 @@ namespace osu.Game.Rulesets.Judgements /// public int HighestComboAtJudgement; + /// + /// Whether this has a result. + /// + public bool HasResult => Result > HitResult.None; + /// /// Whether a successful hit occurred. /// public bool IsHit => Result > HitResult.Miss; - /// - /// Whether this judgement is the final judgement for the hit object. - /// - public bool Final = true; - /// /// The offset from a perfect hit at which this judgement occurred. - /// Populated when added via . + /// Populated when added via . /// public double TimeOffset { get; set; } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index a22aaa784f..b767834e5d 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -38,9 +38,6 @@ namespace osu.Game.Rulesets.Objects.Drawables public event Action OnJudgement; public event Action OnJudgementRemoved; - public IReadOnlyList Judgements => judgements; - private readonly List judgements = new List(); - /// /// Whether a visible judgement should be displayed when this representation is hit. /// @@ -49,20 +46,20 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Whether this and all of its nested s have been hit. /// - public bool IsHit => Judgements.Any(j => j.Final && j.IsHit) && NestedHitObjects.All(n => n.IsHit); + public bool IsHit => HitObject.Judgements.All(j => j.IsHit) && NestedHitObjects.All(n => n.IsHit); /// /// Whether this and all of its nested s have been judged. /// - public bool AllJudged => (!ProvidesJudgement || judgementFinalized) && NestedHitObjects.All(h => h.AllJudged); + public bool AllJudged => Judged && NestedHitObjects.All(h => h.AllJudged); /// - /// Whether this can be judged. + /// Whether this has been judged. + /// Note: This does NOT include nested hitobjects. /// - protected virtual bool ProvidesJudgement => true; + public bool Judged => HitObject.Judgements.All(h => h.HasResult); private bool judgementOccurred; - private bool judgementFinalized => judgements.LastOrDefault()?.Final == true; public bool Interactive = true; public override bool HandleKeyboardInput => Interactive; @@ -128,23 +125,31 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public void PlaySamples() => Samples?.Play(); + private double lastUpdateTime; + protected override void Update() { base.Update(); - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - - while (judgements.Count > 0) + if (lastUpdateTime > Time.Current) { - var lastJudgement = judgements[judgements.Count - 1]; - if (lastJudgement.TimeOffset + endTime <= Time.Current) - break; + var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - judgements.RemoveAt(judgements.Count - 1); - State.Value = ArmedState.Idle; + for (int i = HitObject.Judgements.Count - 1; i >= 0; i--) + { + var judgement = HitObject.Judgements[i]; - OnJudgementRemoved?.Invoke(this, lastJudgement); + if (judgement.TimeOffset + endTime <= Time.Current) + break; + + judgement.Result = HitResult.None; + State.Value = ArmedState.Idle; + + OnJudgementRemoved?.Invoke(this, judgement); + } } + + lastUpdateTime = Time.Current; } protected override void UpdateAfterChildren() @@ -167,16 +172,17 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Notifies that a new judgement has occurred for this . /// /// The . - protected void AddJudgement(Judgement judgement) + protected void ApplyJudgement(T judgement, Action application) + where T : Judgement { judgementOccurred = true; + application?.Invoke(judgement); + // Ensure that the judgement is given a valid time offset, because this may not get set by the caller var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; judgement.TimeOffset = Time.Current - endTime; - judgements.Add(judgement); - switch (judgement.Result) { case HitResult.None: @@ -207,7 +213,7 @@ namespace osu.Game.Rulesets.Objects.Drawables foreach (var d in NestedHitObjects) judgementOccurred |= d.UpdateJudgement(userTriggered); - if (!ProvidesJudgement || judgementFinalized || judgementOccurred) + if (judgementOccurred || Judged) return judgementOccurred; var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; @@ -218,7 +224,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Checks if any judgements have occurred for this . This method must construct - /// all s and notify of them through . + /// all s and notify of them through . /// /// Whether the user triggered this check. /// The offset from the end time at which this check occurred. A > 0 diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 15c24e2975..0e029a8657 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -3,12 +3,14 @@ using System; using System.Collections.Generic; +using System.Linq; using Newtonsoft.Json; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Lists; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects @@ -62,6 +64,9 @@ namespace osu.Game.Rulesets.Objects [JsonIgnore] public IReadOnlyList NestedHitObjects => nestedHitObjects.Value; + private readonly List judgements = new List(); + public IReadOnlyList Judgements => judgements; + /// /// Applies default values to this HitObject. /// @@ -71,6 +76,9 @@ namespace osu.Game.Rulesets.Objects { ApplyDefaultsToSelf(controlPointInfo, difficulty); + judgements.Clear(); + judgements.AddRange(CreateJudgements()); + if (nestedHitObjects.IsValueCreated) nestedHitObjects.Value.Clear(); @@ -103,6 +111,8 @@ namespace osu.Game.Rulesets.Objects { } + protected virtual IEnumerable CreateJudgements() => Enumerable.Empty(); + protected void AddNested(HitObject hitObject) => nestedHitObjects.Value.Add(hitObject); ///