mirror of
https://github.com/osukey/osukey.git
synced 2025-07-02 08:49:59 +09:00
Handle key counter rewinding in a better way
Use ElapsedFrameTime rather than storing state data
This commit is contained in:
@ -7,7 +7,6 @@ using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK.Input;
|
||||
|
||||
@ -25,14 +24,15 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
public TestSceneKeyCounter()
|
||||
{
|
||||
KeyCounterKeyboard rewindTestKeyCounterKeyboard;
|
||||
KeyCounterKeyboard testCounter;
|
||||
|
||||
KeyCounterDisplay kc = new KeyCounterDisplay
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Children = new KeyCounter[]
|
||||
{
|
||||
rewindTestKeyCounterKeyboard = new KeyCounterKeyboard(Key.X),
|
||||
testCounter = new KeyCounterKeyboard(Key.X),
|
||||
new KeyCounterKeyboard(Key.X),
|
||||
new KeyCounterMouse(MouseButton.Left),
|
||||
new KeyCounterMouse(MouseButton.Right),
|
||||
@ -54,7 +54,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
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", () =>
|
||||
{
|
||||
@ -63,39 +63,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
time1 = Clock.CurrentTime;
|
||||
});
|
||||
|
||||
AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.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);
|
||||
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 2);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -22,9 +20,6 @@ namespace osu.Game.Screens.Play
|
||||
private Container textLayer;
|
||||
private SpriteText countSpriteText;
|
||||
|
||||
private readonly List<KeyCounterState> states = new List<KeyCounterState>();
|
||||
private KeyCounterState currentState;
|
||||
|
||||
public bool IsCounting { get; set; } = true;
|
||||
private int countPresses;
|
||||
|
||||
@ -52,14 +47,24 @@ namespace osu.Game.Screens.Play
|
||||
{
|
||||
isLit = value;
|
||||
updateGlowSprite(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value && IsCounting)
|
||||
public void Increment()
|
||||
{
|
||||
if (!IsCounting)
|
||||
return;
|
||||
|
||||
CountPresses++;
|
||||
saveState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Decrement()
|
||||
{
|
||||
if (!IsCounting)
|
||||
return;
|
||||
|
||||
CountPresses--;
|
||||
}
|
||||
|
||||
//further: change default values here and in KeyCounterCollection if needed, instead of passing them in every constructor
|
||||
@ -143,27 +148,5 @@ namespace osu.Game.Screens.Play
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,9 @@
|
||||
// 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.Framework.Input.Bindings;
|
||||
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
public class KeyCounterAction<T> : KeyCounter, IKeyBindingHandler<T>
|
||||
public class KeyCounterAction<T> : KeyCounter
|
||||
where T : struct
|
||||
{
|
||||
public T Action { get; }
|
||||
@ -16,15 +14,25 @@ namespace osu.Game.Screens.Play
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -102,11 +102,6 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
private Receptor receptor;
|
||||
|
||||
public Receptor GetReceptor()
|
||||
{
|
||||
return receptor ?? (receptor = new Receptor(this));
|
||||
}
|
||||
|
||||
public void SetReceptor(Receptor receptor)
|
||||
{
|
||||
if (this.receptor != null)
|
||||
|
@ -18,7 +18,12 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
protected override bool OnKeyDown(KeyDownEvent e)
|
||||
{
|
||||
if (e.Key == Key) IsLit = true;
|
||||
if (e.Key == Key)
|
||||
{
|
||||
IsLit = true;
|
||||
Increment();
|
||||
}
|
||||
|
||||
return base.OnKeyDown(e);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,12 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
if (e.Button == Button) IsLit = true;
|
||||
if (e.Button == Button)
|
||||
{
|
||||
IsLit = true;
|
||||
Increment();
|
||||
}
|
||||
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user