Handle key counter rewinding in a better way

Use ElapsedFrameTime rather than storing state data
This commit is contained in:
Dean Herbert
2019-09-12 15:41:53 +09:00
parent cb0cf6e2c5
commit 0cdf125c1e
7 changed files with 50 additions and 84 deletions

View File

@ -7,7 +7,6 @@ using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Framework.Timing;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using osuTK.Input; using osuTK.Input;
@ -25,14 +24,15 @@ namespace osu.Game.Tests.Visual.Gameplay
public TestSceneKeyCounter() public TestSceneKeyCounter()
{ {
KeyCounterKeyboard rewindTestKeyCounterKeyboard; KeyCounterKeyboard testCounter;
KeyCounterDisplay kc = new KeyCounterDisplay KeyCounterDisplay kc = new KeyCounterDisplay
{ {
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Children = new KeyCounter[] Children = new KeyCounter[]
{ {
rewindTestKeyCounterKeyboard = new KeyCounterKeyboard(Key.X), testCounter = new KeyCounterKeyboard(Key.X),
new KeyCounterKeyboard(Key.X), new KeyCounterKeyboard(Key.X),
new KeyCounterMouse(MouseButton.Left), new KeyCounterMouse(MouseButton.Left),
new KeyCounterMouse(MouseButton.Right), new KeyCounterMouse(MouseButton.Right),
@ -54,7 +54,7 @@ namespace osu.Game.Tests.Visual.Gameplay
InputManager.ReleaseKey(testKey); InputManager.ReleaseKey(testKey);
}); });
AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 1); AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 1);
AddStep($"Press {testKey} key", () => AddStep($"Press {testKey} key", () =>
{ {
@ -63,39 +63,9 @@ namespace osu.Game.Tests.Visual.Gameplay
time1 = Clock.CurrentTime; time1 = Clock.CurrentTime;
}); });
AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 2); AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 2);
IFrameBasedClock oldClock = null;
AddStep($"Rewind {testKey} counter once", () =>
{
oldClock = rewindTestKeyCounterKeyboard.Clock;
rewindTestKeyCounterKeyboard.Clock = new FramedOffsetClock(new FixedClock(time1 - 10));
});
AddAssert($"Check {testKey} counter after rewind", () => rewindTestKeyCounterKeyboard.CountPresses == 1);
AddStep($"Rewind {testKey} counter to zero", () => rewindTestKeyCounterKeyboard.Clock = new FramedOffsetClock(new FixedClock(0)));
AddAssert($"Check {testKey} counter after rewind", () => rewindTestKeyCounterKeyboard.CountPresses == 0);
AddStep("Restore clock", () => rewindTestKeyCounterKeyboard.Clock = oldClock);
Add(kc); Add(kc);
} }
private class FixedClock : IClock
{
private readonly double time;
public FixedClock(double time)
{
this.time = time;
}
public double CurrentTime => time;
public double Rate => 1;
public bool IsRunning => false;
}
} }
} }

View File

@ -137,9 +137,9 @@ namespace osu.Game.Rulesets.UI
{ {
} }
public bool OnPressed(T action) => Target.Children.OfType<KeyCounterAction<T>>().Any(c => c.OnPressed(action)); public bool OnPressed(T action) => Target.Children.OfType<KeyCounterAction<T>>().Any(c => c.OnPressed(action, Clock.ElapsedFrameTime > 0));
public bool OnReleased(T action) => Target.Children.OfType<KeyCounterAction<T>>().Any(c => c.OnReleased(action)); public bool OnReleased(T action) => Target.Children.OfType<KeyCounterAction<T>>().Any(c => c.OnReleased(action, Clock.ElapsedFrameTime > 0));
} }
#endregion #endregion

View File

@ -1,8 +1,6 @@
// 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.Generic;
using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -22,9 +20,6 @@ namespace osu.Game.Screens.Play
private Container textLayer; private Container textLayer;
private SpriteText countSpriteText; private SpriteText countSpriteText;
private readonly List<KeyCounterState> states = new List<KeyCounterState>();
private KeyCounterState currentState;
public bool IsCounting { get; set; } = true; public bool IsCounting { get; set; } = true;
private int countPresses; private int countPresses;
@ -52,16 +47,26 @@ namespace osu.Game.Screens.Play
{ {
isLit = value; isLit = value;
updateGlowSprite(value); updateGlowSprite(value);
if (value && IsCounting)
{
CountPresses++;
saveState();
}
} }
} }
} }
public void Increment()
{
if (!IsCounting)
return;
CountPresses++;
}
public void Decrement()
{
if (!IsCounting)
return;
CountPresses--;
}
//further: change default values here and in KeyCounterCollection if needed, instead of passing them in every constructor //further: change default values here and in KeyCounterCollection if needed, instead of passing them in every constructor
public Color4 KeyDownTextColor { get; set; } = Color4.DarkGray; public Color4 KeyDownTextColor { get; set; } = Color4.DarkGray;
public Color4 KeyUpTextColor { get; set; } = Color4.White; public Color4 KeyUpTextColor { get; set; } = Color4.White;
@ -143,27 +148,5 @@ namespace osu.Game.Screens.Play
textLayer.FadeColour(KeyUpTextColor, remainingFadeTime, Easing.OutQuint); textLayer.FadeColour(KeyUpTextColor, remainingFadeTime, Easing.OutQuint);
} }
} }
protected override void Update()
{
base.Update();
if (currentState?.Time > Clock.CurrentTime)
restoreStateTo(Clock.CurrentTime);
}
private void saveState()
{
if (currentState == null || currentState.Time < Clock.CurrentTime)
states.Add(currentState = new KeyCounterState(Clock.CurrentTime, CountPresses));
}
private void restoreStateTo(double time)
{
states.RemoveAll(state => state.Time > time);
currentState = states.LastOrDefault();
CountPresses = currentState?.Count ?? 0;
}
} }
} }

View File

@ -1,11 +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 osu.Framework.Input.Bindings;
namespace osu.Game.Screens.Play namespace osu.Game.Screens.Play
{ {
public class KeyCounterAction<T> : KeyCounter, IKeyBindingHandler<T> public class KeyCounterAction<T> : KeyCounter
where T : struct where T : struct
{ {
public T Action { get; } public T Action { get; }
@ -16,15 +14,25 @@ namespace osu.Game.Screens.Play
Action = action; Action = action;
} }
public bool OnPressed(T action) public bool OnPressed(T action, bool forwards)
{ {
if (action.Equals(Action)) IsLit = true; if (!action.Equals(Action))
return false;
IsLit = true;
if (forwards)
Increment();
return false; return false;
} }
public bool OnReleased(T action) public bool OnReleased(T action, bool forwards)
{ {
if (action.Equals(Action)) IsLit = false; if (!action.Equals(Action))
return false;
IsLit = false;
if (!forwards)
Decrement();
return false; return false;
} }
} }

View File

@ -102,11 +102,6 @@ namespace osu.Game.Screens.Play
private Receptor receptor; private Receptor receptor;
public Receptor GetReceptor()
{
return receptor ?? (receptor = new Receptor(this));
}
public void SetReceptor(Receptor receptor) public void SetReceptor(Receptor receptor)
{ {
if (this.receptor != null) if (this.receptor != null)

View File

@ -18,7 +18,12 @@ namespace osu.Game.Screens.Play
protected override bool OnKeyDown(KeyDownEvent e) protected override bool OnKeyDown(KeyDownEvent e)
{ {
if (e.Key == Key) IsLit = true; if (e.Key == Key)
{
IsLit = true;
Increment();
}
return base.OnKeyDown(e); return base.OnKeyDown(e);
} }

View File

@ -36,7 +36,12 @@ namespace osu.Game.Screens.Play
protected override bool OnMouseDown(MouseDownEvent e) protected override bool OnMouseDown(MouseDownEvent e)
{ {
if (e.Button == Button) IsLit = true; if (e.Button == Button)
{
IsLit = true;
Increment();
}
return base.OnMouseDown(e); return base.OnMouseDown(e);
} }