Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow judging at most one swell tick per frame #25010

Merged
merged 4 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,48 @@ public void TestHitNoneSwell()
AddAssert("all tick offsets are 0", () => JudgementResults.Where(r => r.HitObject is SwellTick).All(r => r.TimeOffset == 0));
}

[Test]
public void TestAtMostOneSwellTickJudgedPerFrame()
{
const double swell_time = 1000;

Swell swell = new Swell
{
StartTime = swell_time,
Duration = 1000,
RequiredHits = 10
};

List<ReplayFrame> frames = new List<ReplayFrame>
{
new TaikoReplayFrame(1000),
new TaikoReplayFrame(1250, TaikoAction.LeftCentre, TaikoAction.LeftRim),
new TaikoReplayFrame(1251),
new TaikoReplayFrame(1500, TaikoAction.LeftCentre, TaikoAction.LeftRim, TaikoAction.RightCentre, TaikoAction.RightRim),
new TaikoReplayFrame(1501),
new TaikoReplayFrame(2000),
};

PerformTest(frames, CreateBeatmap(swell));

AssertJudgementCount(11);

// this is a charitable interpretation of the inputs.
//
// for the frame at time 1250, we only count either one of the input actions - simple.
//
// for the frame at time 1500, we give the user the benefit of the doubt,
// and we ignore actions that wouldn't otherwise cause a hit due to not alternating,
// but we still count one (just one) of the actions that _would_ normally cause a hit.
// this is done as a courtesy to avoid stuff like key chattering after press blocking legitimate inputs.
for (int i = 0; i < 2; i++)
AssertResult<SwellTick>(i, HitResult.IgnoreHit);
for (int i = 2; i < swell.RequiredHits; i++)
AssertResult<SwellTick>(i, HitResult.IgnoreMiss);

AssertResult<Swell>(0, HitResult.IgnoreMiss);
}

/// <summary>
/// Ensure input is correctly sent to subsequent hits if a swell is fully completed.
/// </summary>
Expand Down
14 changes: 14 additions & 0 deletions osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using osu.Framework.Input.Events;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Taiko.Skinning.Default;
using osu.Game.Screens.Play;
using osu.Game.Skinning;

namespace osu.Game.Rulesets.Taiko.Objects.Drawables
Expand All @@ -38,6 +39,8 @@ public partial class DrawableSwell : DrawableTaikoHitObject<Swell>
private readonly CircularContainer targetRing;
private readonly CircularContainer expandingRing;

private double? lastPressHandleTime;

public override bool DisplayResult => false;

public DrawableSwell()
Expand Down Expand Up @@ -140,6 +143,7 @@ protected override void OnFree()
UnproxyContent();

lastWasCentre = null;
lastPressHandleTime = null;
}

protected override void AddNestedHitObject(DrawableHitObject hitObject)
Expand Down Expand Up @@ -266,6 +270,9 @@ protected override void Update()
ProxyContent();
else
UnproxyContent();

if ((Clock as IGameplayClock)?.IsRewinding == true)
lastPressHandleTime = null;
}

private bool? lastWasCentre;
Expand All @@ -285,7 +292,14 @@ public override bool OnPressed(KeyBindingPressEvent<TaikoAction> e)
if (lastWasCentre == isCentre)
return false;

// If we've already successfully judged a tick this frame, do not judge more.
// Note that the ordering is important here - this is intentionally placed after the alternating check.
// That is done to prevent accidental double inputs blocking simultaneous but legitimate hits from registering.
if (lastPressHandleTime == Time.Current)
peppy marked this conversation as resolved.
Show resolved Hide resolved
return true;

lastWasCentre = isCentre;
lastPressHandleTime = Time.Current;

UpdateResult(true);

Expand Down