mirror of
https://github.com/ppy/osu
synced 2025-01-04 13:22:08 +00:00
Optimise by removing state machine
This commit is contained in:
parent
3daacbc2d2
commit
62f77a05be
@ -1,7 +1,9 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||||
@ -36,11 +38,14 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
{
|
{
|
||||||
DrawableHitObject blockingObject = null;
|
DrawableHitObject blockingObject = null;
|
||||||
|
|
||||||
// Find the last hitobject which blocks future hits.
|
var enumerator = new HitObjectEnumerator(hitObjectContainer, hitObject.HitObject.StartTime);
|
||||||
foreach (var obj in enumerateHitObjectsUpTo(hitObject))
|
|
||||||
|
while (enumerator.MoveNext())
|
||||||
{
|
{
|
||||||
if (hitObjectCanBlockFutureHits(obj))
|
Debug.Assert(enumerator.Current != null);
|
||||||
blockingObject = obj;
|
|
||||||
|
if (hitObjectCanBlockFutureHits(enumerator.Current))
|
||||||
|
blockingObject = enumerator.Current;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is no previous hitobject, allow the hit.
|
// If there is no previous hitobject, allow the hit.
|
||||||
@ -67,13 +72,17 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
if (!hitObjectCanBlockFutureHits(hitObject))
|
if (!hitObjectCanBlockFutureHits(hitObject))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var obj in enumerateHitObjectsUpTo(hitObject))
|
var enumerator = new HitObjectEnumerator(hitObjectContainer, hitObject.HitObject.StartTime);
|
||||||
|
|
||||||
|
while (enumerator.MoveNext())
|
||||||
{
|
{
|
||||||
if (obj.Judged)
|
Debug.Assert(enumerator.Current != null);
|
||||||
|
|
||||||
|
if (enumerator.Current.Judged)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (hitObjectCanBlockFutureHits(obj))
|
if (hitObjectCanBlockFutureHits(enumerator.Current))
|
||||||
((DrawableOsuHitObject)obj).MissForcefully();
|
((DrawableOsuHitObject)enumerator.Current).MissForcefully();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,23 +93,89 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
private static bool hitObjectCanBlockFutureHits(DrawableHitObject hitObject)
|
private static bool hitObjectCanBlockFutureHits(DrawableHitObject hitObject)
|
||||||
=> hitObject is DrawableHitCircle;
|
=> hitObject is DrawableHitCircle;
|
||||||
|
|
||||||
// Todo: Inefficient
|
private struct HitObjectEnumerator : IEnumerator<DrawableHitObject>
|
||||||
private IEnumerable<DrawableHitObject> enumerateHitObjectsUpTo(DrawableHitObject hitObject)
|
|
||||||
{
|
{
|
||||||
return enumerate(hitObjectContainer.AliveObjects);
|
private readonly IEnumerator<DrawableHitObject> hitObjectEnumerator;
|
||||||
|
private readonly double targetTime;
|
||||||
|
|
||||||
IEnumerable<DrawableHitObject> enumerate(IEnumerable<DrawableHitObject> list)
|
private DrawableHitObject currentTopLevel;
|
||||||
|
private int currentNestedIndex;
|
||||||
|
|
||||||
|
public HitObjectEnumerator(HitObjectContainer hitObjectContainer, double targetTime)
|
||||||
{
|
{
|
||||||
foreach (var obj in list)
|
hitObjectEnumerator = hitObjectContainer.AliveObjects.GetEnumerator();
|
||||||
{
|
this.targetTime = targetTime;
|
||||||
if (obj.HitObject.StartTime >= hitObject.HitObject.StartTime)
|
|
||||||
yield break;
|
|
||||||
|
|
||||||
yield return obj;
|
currentTopLevel = null;
|
||||||
|
currentNestedIndex = -1;
|
||||||
|
Current = null;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var nested in enumerate(obj.NestedHitObjects))
|
/// <summary>
|
||||||
yield return nested;
|
/// Attempts to move to the next top-level or nested hitobject.
|
||||||
}
|
/// Stops when no such hitobject is found or until the hitobject start time reaches <see cref="targetTime"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Whether a new hitobject was moved to.</returns>
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
// If we don't already have a top-level hitobject, try to get one.
|
||||||
|
if (currentTopLevel == null)
|
||||||
|
return moveNextTopLevel();
|
||||||
|
|
||||||
|
// If we have a top-level hitobject, try to move to the next nested hitobject or otherwise move to the next top-level hitobject.
|
||||||
|
if (!moveNextNested())
|
||||||
|
return moveNextTopLevel();
|
||||||
|
|
||||||
|
// Guaranteed by moveNextNested() to have a hitobject.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to move to the next top-level hitobject.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Whether a new top-level hitobject was found.</returns>
|
||||||
|
private bool moveNextTopLevel()
|
||||||
|
{
|
||||||
|
currentNestedIndex = -1;
|
||||||
|
|
||||||
|
hitObjectEnumerator.MoveNext();
|
||||||
|
currentTopLevel = hitObjectEnumerator.Current;
|
||||||
|
|
||||||
|
Current = currentTopLevel;
|
||||||
|
|
||||||
|
return Current?.HitObject.StartTime < targetTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to move to the next nested hitobject in the current top-level hitobject.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Whether a new nested hitobject was moved to.</returns>
|
||||||
|
private bool moveNextNested()
|
||||||
|
{
|
||||||
|
currentNestedIndex++;
|
||||||
|
if (currentNestedIndex >= currentTopLevel.NestedHitObjects.Count)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Current = currentTopLevel.NestedHitObjects[currentNestedIndex];
|
||||||
|
Debug.Assert(Current != null);
|
||||||
|
|
||||||
|
return Current?.HitObject.StartTime < targetTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
hitObjectEnumerator.Reset();
|
||||||
|
currentTopLevel = null;
|
||||||
|
currentNestedIndex = -1;
|
||||||
|
Current = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DrawableHitObject Current { get; set; }
|
||||||
|
|
||||||
|
object IEnumerator.Current => Current;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user