1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-13 15:03:13 +08:00

Rewrite hold note input handling

This commit is contained in:
smoogipoo 2019-12-23 17:48:48 +09:00
parent 42853b5af6
commit 7ac6f68de8
4 changed files with 41 additions and 59 deletions

View File

@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
// Todo: This shouldn't exist, mania should not reference the drawable hitobject directly.
if (DrawableObject.IsLoaded)
{
DrawableNote note = position == HoldNotePosition.Start ? DrawableObject.Head : DrawableObject.Tail;
DrawableNote note = position == HoldNotePosition.Start ? (DrawableNote)DrawableObject.Head : DrawableObject.Tail;
Anchor = note.Anchor;
Origin = note.Origin;

View File

@ -20,8 +20,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
{
public override bool DisplayResult => false;
public DrawableNote Head => headContainer.Child;
public DrawableNote Tail => tailContainer.Child;
public DrawableHoldNoteHead Head => headContainer.Child;
public DrawableHoldNoteTail Tail => tailContainer.Child;
private readonly Container<DrawableHoldNoteHead> headContainer;
private readonly Container<DrawableHoldNoteTail> tailContainer;
@ -124,12 +124,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
bodyPiece.Anchor = bodyPiece.Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft;
}
protected override void CheckForResult(bool userTriggered, double timeOffset)
{
if (Tail.AllJudged)
ApplyResult(r => r.Type = HitResult.Perfect);
}
protected override void Update()
{
base.Update();
@ -145,44 +139,52 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
base.UpdateStateTransforms(state);
}
internal void BeginHold()
protected override void CheckForResult(bool userTriggered, double timeOffset)
{
HoldStartTime = Time.Current;
bodyPiece.Hitting = true;
}
if (Tail.AllJudged)
ApplyResult(r => r.Type = HitResult.Perfect);
protected void EndHold()
{
HoldStartTime = null;
bodyPiece.Hitting = false;
if (Tail.Result.Type == HitResult.Miss)
HasBroken = true;
}
public bool OnPressed(ManiaAction action)
{
// Make sure the action happened within the body of the hold note
if (Time.Current < HitObject.StartTime || Time.Current > HitObject.EndTime)
if (AllJudged)
return false;
if (action != Action.Value)
return false;
// The user has pressed during the body of the hold note, after the head note and its hit windows have passed
// and within the limited range of the above if-statement. This state will be managed by the head note if the
// user has pressed during the hit windows of the head note.
BeginHold();
beginHoldAt(Time.Current - Head.HitObject.StartTime);
Head.UpdateResult();
return true;
}
private void beginHoldAt(double timeOffset)
{
if (timeOffset < -Head.HitObject.HitWindows.WindowFor(HitResult.Miss))
return;
HoldStartTime = Time.Current;
bodyPiece.Hitting = true;
}
public bool OnReleased(ManiaAction action)
{
// Make sure that the user started holding the key during the hold note
if (!HoldStartTime.HasValue)
if (AllJudged)
return false;
if (action != Action.Value)
return false;
EndHold();
// Make sure a hold was started
if (HoldStartTime == null)
return false;
Tail.UpdateResult();
endHold();
// If the key has been released too early, the user should not receive full score for the release
if (!Tail.IsHit)
@ -190,5 +192,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
return true;
}
private void endHold()
{
HoldStartTime = null;
bodyPiece.Hitting = false;
}
}
}

View File

@ -1,8 +1,6 @@
// 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.
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Objects.Drawables
{
/// <summary>
@ -10,28 +8,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
/// </summary>
public class DrawableHoldNoteHead : DrawableNote
{
private readonly DrawableHoldNote holdNote;
public DrawableHoldNoteHead(DrawableHoldNote holdNote)
: base(holdNote.HitObject.Head)
{
this.holdNote = holdNote;
}
public override bool OnPressed(ManiaAction action)
{
if (!base.OnPressed(action))
return false;
public void UpdateResult() => base.UpdateResult(true);
// If the key has been released too early, the user should not receive full score for the release
if (Result.Type == HitResult.Miss)
holdNote.HasBroken = true;
public override bool OnPressed(ManiaAction action) => false; // Handled by the hold note
// The head note also handles early hits before the body, but we want accurate early hits to count as the body being held
// The body doesn't handle these early early hits, so we have to explicitly set the holding state here
holdNote.BeginHold();
return true;
}
public override bool OnReleased(ManiaAction action) => false; // Handled by the hold note
}
}

View File

@ -26,6 +26,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
this.holdNote = holdNote;
}
public void UpdateResult() => base.UpdateResult(true);
protected override void CheckForResult(bool userTriggered, double timeOffset)
{
Debug.Assert(HitObject.HitWindows != null);
@ -54,21 +56,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
});
}
public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down
public override bool OnPressed(ManiaAction action) => false; // Handled by the hold note
public override bool OnReleased(ManiaAction action)
{
// Make sure that the user started holding the key during the hold note
if (!holdNote.HoldStartTime.HasValue)
return false;
if (action != Action.Value)
return false;
UpdateResult(true);
// Handled by the hold note, which will set holding = false
return false;
}
public override bool OnReleased(ManiaAction action) => false; // Handled by the hold note
}
}