mirror of
https://github.com/ppy/osu.git
synced 2025-02-21 03:02:54 +08:00
Merge remote-tracking branch 'upstream/master' into update-squirrel
This commit is contained in:
commit
39a6bcba17
@ -74,42 +74,42 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
|
|
||||||
private void initialiseHyperDash(List<CatchHitObject> objects)
|
private void initialiseHyperDash(List<CatchHitObject> objects)
|
||||||
{
|
{
|
||||||
// todo: add difficulty adjust.
|
List<CatchHitObject> objectWithDroplets = new List<CatchHitObject>();
|
||||||
double halfCatcherWidth = CatcherArea.CATCHER_SIZE * (objects.FirstOrDefault()?.Scale ?? 1) / CatchPlayfield.BASE_WIDTH / 2;
|
|
||||||
|
|
||||||
|
foreach (var currentObject in objects)
|
||||||
|
{
|
||||||
|
if (currentObject is Fruit)
|
||||||
|
objectWithDroplets.Add(currentObject);
|
||||||
|
if (currentObject is JuiceStream)
|
||||||
|
foreach (var currentJuiceElement in currentObject.NestedHitObjects)
|
||||||
|
if (!(currentJuiceElement is TinyDroplet))
|
||||||
|
objectWithDroplets.Add((CatchHitObject)currentJuiceElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
objectWithDroplets.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime));
|
||||||
|
|
||||||
|
double halfCatcherWidth = CatcherArea.GetCatcherSize(Beatmap.BeatmapInfo.BaseDifficulty) / 2;
|
||||||
int lastDirection = 0;
|
int lastDirection = 0;
|
||||||
double lastExcess = halfCatcherWidth;
|
double lastExcess = halfCatcherWidth;
|
||||||
|
|
||||||
int objCount = objects.Count;
|
for (int i = 0; i < objectWithDroplets.Count - 1; i++)
|
||||||
|
|
||||||
for (int i = 0; i < objCount - 1; i++)
|
|
||||||
{
|
{
|
||||||
CatchHitObject currentObject = objects[i];
|
CatchHitObject currentObject = objectWithDroplets[i];
|
||||||
|
CatchHitObject nextObject = objectWithDroplets[i + 1];
|
||||||
// not needed?
|
|
||||||
// if (currentObject is TinyDroplet) continue;
|
|
||||||
|
|
||||||
CatchHitObject nextObject = objects[i + 1];
|
|
||||||
|
|
||||||
// while (nextObject is TinyDroplet)
|
|
||||||
// {
|
|
||||||
// if (++i == objCount - 1) break;
|
|
||||||
// nextObject = objects[i + 1];
|
|
||||||
// }
|
|
||||||
|
|
||||||
int thisDirection = nextObject.X > currentObject.X ? 1 : -1;
|
int thisDirection = nextObject.X > currentObject.X ? 1 : -1;
|
||||||
double timeToNext = nextObject.StartTime - ((currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime) - 4;
|
double timeToNext = nextObject.StartTime - currentObject.StartTime;
|
||||||
double distanceToNext = Math.Abs(nextObject.X - currentObject.X) - (lastDirection == thisDirection ? lastExcess : halfCatcherWidth);
|
double distanceToNext = Math.Abs(nextObject.X - currentObject.X) - (lastDirection == thisDirection ? lastExcess : halfCatcherWidth);
|
||||||
|
float distanceToHyper = (float)(timeToNext * CatcherArea.Catcher.BASE_SPEED - distanceToNext);
|
||||||
if (timeToNext * CatcherArea.Catcher.BASE_SPEED < distanceToNext)
|
if (distanceToHyper < 0)
|
||||||
{
|
{
|
||||||
currentObject.HyperDashTarget = nextObject;
|
currentObject.HyperDashTarget = nextObject;
|
||||||
lastExcess = halfCatcherWidth;
|
lastExcess = halfCatcherWidth;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//currentObject.DistanceToHyperDash = timeToNext - distanceToNext;
|
currentObject.DistanceToHyperDash = distanceToHyper;
|
||||||
lastExcess = MathHelper.Clamp(timeToNext - distanceToNext, 0, halfCatcherWidth);
|
lastExcess = MathHelper.Clamp(distanceToHyper, 0, halfCatcherWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastDirection = thisDirection;
|
lastDirection = thisDirection;
|
||||||
|
@ -27,7 +27,9 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
public int ComboIndex { get; set; }
|
public int ComboIndex { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The distance for a fruit to to next hyper if it's not a hyper.
|
/// Difference between the distance to the next object
|
||||||
|
/// and the distance that would have triggered a hyper dash.
|
||||||
|
/// A value close to 0 indicates a difficult jump (for difficulty calculation).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float DistanceToHyperDash { get; set; }
|
public float DistanceToHyperDash { get; set; }
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
private readonly CatcherArea catcherArea;
|
private readonly CatcherArea catcherArea;
|
||||||
|
|
||||||
|
protected override bool UserScrollSpeedAdjustment => false;
|
||||||
|
|
||||||
public CatchPlayfield(BeatmapDifficulty difficulty, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> getVisualRepresentation)
|
public CatchPlayfield(BeatmapDifficulty difficulty, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> getVisualRepresentation)
|
||||||
: base(BASE_WIDTH)
|
: base(BASE_WIDTH)
|
||||||
{
|
{
|
||||||
|
@ -107,6 +107,11 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
public bool AttemptCatch(CatchHitObject obj) => MovableCatcher.AttemptCatch(obj);
|
public bool AttemptCatch(CatchHitObject obj) => MovableCatcher.AttemptCatch(obj);
|
||||||
|
|
||||||
|
public static float GetCatcherSize(BeatmapDifficulty difficulty)
|
||||||
|
{
|
||||||
|
return CATCHER_SIZE / CatchPlayfield.BASE_WIDTH * (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5);
|
||||||
|
}
|
||||||
|
|
||||||
public class Catcher : Container, IKeyBindingHandler<CatchAction>
|
public class Catcher : Container, IKeyBindingHandler<CatchAction>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
51
osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs
Normal file
51
osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Mods
|
||||||
|
{
|
||||||
|
internal class OsuModTransform : Mod, IApplicableToDrawableHitObjects
|
||||||
|
{
|
||||||
|
public override string Name => "Transform";
|
||||||
|
public override string ShortenedName => "TR";
|
||||||
|
public override FontAwesome Icon => FontAwesome.fa_arrows;
|
||||||
|
public override ModType Type => ModType.Fun;
|
||||||
|
public override string Description => "Everything rotates. EVERYTHING.";
|
||||||
|
public override double ScoreMultiplier => 1;
|
||||||
|
private float theta;
|
||||||
|
|
||||||
|
public void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables)
|
||||||
|
{
|
||||||
|
foreach (var drawable in drawables)
|
||||||
|
{
|
||||||
|
var hitObject = (OsuHitObject) drawable.HitObject;
|
||||||
|
|
||||||
|
float appearDistance = (float)(hitObject.TimePreempt - hitObject.TimeFadeIn) / 2;
|
||||||
|
|
||||||
|
Vector2 originalPosition = drawable.Position;
|
||||||
|
Vector2 appearOffset = new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance;
|
||||||
|
|
||||||
|
//the - 1 and + 1 prevents the hit objects to appear in the wrong position.
|
||||||
|
double appearTime = hitObject.StartTime - hitObject.TimePreempt - 1;
|
||||||
|
double moveDuration = hitObject.TimePreempt + 1;
|
||||||
|
|
||||||
|
using (drawable.BeginAbsoluteSequence(appearTime, true))
|
||||||
|
{
|
||||||
|
drawable
|
||||||
|
.MoveToOffset(appearOffset)
|
||||||
|
.MoveTo(originalPosition, moveDuration, Easing.InOutSine);
|
||||||
|
}
|
||||||
|
|
||||||
|
theta += (float) hitObject.TimeFadeIn / 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
66
osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs
Normal file
66
osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Mods
|
||||||
|
{
|
||||||
|
internal class OsuModWiggle : Mod, IApplicableToDrawableHitObjects
|
||||||
|
{
|
||||||
|
public override string Name => "Wiggle";
|
||||||
|
public override string ShortenedName => "WG";
|
||||||
|
public override FontAwesome Icon => FontAwesome.fa_certificate;
|
||||||
|
public override ModType Type => ModType.Fun;
|
||||||
|
public override string Description => "They just won't stay still...";
|
||||||
|
public override double ScoreMultiplier => 1;
|
||||||
|
|
||||||
|
private const int wiggle_duration = 90; // (ms) Higher = fewer wiggles
|
||||||
|
private const int wiggle_strength = 10; // Higher = stronger wiggles
|
||||||
|
|
||||||
|
public void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables)
|
||||||
|
{
|
||||||
|
foreach (var drawable in drawables)
|
||||||
|
drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state)
|
||||||
|
{
|
||||||
|
var osuObject = (OsuHitObject)drawable.HitObject;
|
||||||
|
Vector2 origin = drawable.Position;
|
||||||
|
|
||||||
|
Random objRand = new Random((int)osuObject.StartTime);
|
||||||
|
|
||||||
|
// Wiggle all objects during TimePreempt
|
||||||
|
int amountWiggles = (int)osuObject.TimePreempt / wiggle_duration;
|
||||||
|
|
||||||
|
void wiggle()
|
||||||
|
{
|
||||||
|
float nextAngle = (float)(objRand.NextDouble() * 2 * Math.PI);
|
||||||
|
float nextDist = (float)(objRand.NextDouble() * wiggle_strength);
|
||||||
|
drawable.MoveTo(new Vector2((float)(nextDist * Math.Cos(nextAngle) + origin.X), (float)(nextDist * Math.Sin(nextAngle) + origin.Y)), wiggle_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < amountWiggles; i++)
|
||||||
|
using (drawable.BeginAbsoluteSequence(osuObject.StartTime - osuObject.TimePreempt + i * wiggle_duration, true))
|
||||||
|
wiggle();
|
||||||
|
|
||||||
|
// Keep wiggling sliders and spinners for their duration
|
||||||
|
if (!(osuObject is IHasEndTime endTime))
|
||||||
|
return;
|
||||||
|
|
||||||
|
amountWiggles = (int)(endTime.Duration / wiggle_duration);
|
||||||
|
|
||||||
|
for (int i = 0; i < amountWiggles; i++)
|
||||||
|
using (drawable.BeginAbsoluteSequence(osuObject.StartTime + i * wiggle_duration, true))
|
||||||
|
wiggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -117,6 +117,11 @@ namespace osu.Game.Rulesets.Osu
|
|||||||
new OsuModRelax(),
|
new OsuModRelax(),
|
||||||
new OsuModAutopilot(),
|
new OsuModAutopilot(),
|
||||||
};
|
};
|
||||||
|
case ModType.Fun:
|
||||||
|
return new Mod[] {
|
||||||
|
new OsuModTransform(),
|
||||||
|
new OsuModWiggle(),
|
||||||
|
};
|
||||||
default:
|
default:
|
||||||
return new Mod[] { };
|
return new Mod[] { };
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Input.EventArgs;
|
||||||
using osu.Framework.MathUtils;
|
using osu.Framework.MathUtils;
|
||||||
|
using osu.Framework.Timing;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
|
|
||||||
@ -12,21 +17,30 @@ namespace osu.Game.Tests.Visual
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestCaseKeyCounter : OsuTestCase
|
public class TestCaseKeyCounter : OsuTestCase
|
||||||
{
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(KeyCounterKeyboard),
|
||||||
|
typeof(KeyCounterMouse),
|
||||||
|
typeof(KeyCounterCollection)
|
||||||
|
};
|
||||||
|
|
||||||
public TestCaseKeyCounter()
|
public TestCaseKeyCounter()
|
||||||
{
|
{
|
||||||
|
KeyCounterKeyboard rewindTestKeyCounterKeyboard;
|
||||||
KeyCounterCollection kc = new KeyCounterCollection
|
KeyCounterCollection kc = new KeyCounterCollection
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Children = new KeyCounter[]
|
Children = new KeyCounter[]
|
||||||
{
|
{
|
||||||
new KeyCounterKeyboard(Key.Z),
|
rewindTestKeyCounterKeyboard = 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),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
AddStep("Add random", () =>
|
AddStep("Add random", () =>
|
||||||
{
|
{
|
||||||
Key key = (Key)((int)Key.A + RNG.Next(26));
|
Key key = (Key)((int)Key.A + RNG.Next(26));
|
||||||
@ -34,7 +48,57 @@ namespace osu.Game.Tests.Visual
|
|||||||
});
|
});
|
||||||
AddSliderStep("Fade time", 0, 200, 50, v => kc.FadeTime = v);
|
AddSliderStep("Fade time", 0, 200, 50, v => kc.FadeTime = v);
|
||||||
|
|
||||||
|
Key testKey = ((KeyCounterKeyboard)kc.Children.First()).Key;
|
||||||
|
double time1 = 0;
|
||||||
|
|
||||||
|
AddStep($"Press {testKey} key", () =>
|
||||||
|
{
|
||||||
|
rewindTestKeyCounterKeyboard.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = testKey, Repeat = false });
|
||||||
|
rewindTestKeyCounterKeyboard.TriggerOnKeyUp(null, new KeyUpEventArgs { Key = testKey });
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 1);
|
||||||
|
|
||||||
|
AddStep($"Press {testKey} key", () =>
|
||||||
|
{
|
||||||
|
rewindTestKeyCounterKeyboard.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = testKey, Repeat = false });
|
||||||
|
rewindTestKeyCounterKeyboard.TriggerOnKeyUp(null, new KeyUpEventArgs { Key = testKey });
|
||||||
|
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);
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,7 @@ namespace osu.Game.Online.Chat
|
|||||||
Timestamp = DateTimeOffset.Now;
|
Timestamp = DateTimeOffset.Now;
|
||||||
Content = message;
|
Content = message;
|
||||||
|
|
||||||
Sender = new User
|
Sender = User.SYSTEM_USER;
|
||||||
{
|
|
||||||
Username = @"system",
|
|
||||||
Colour = @"0000ff",
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,9 +77,11 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
public void ShowUser(User user, bool fetchOnline = true)
|
public void ShowUser(User user, bool fetchOnline = true)
|
||||||
{
|
{
|
||||||
|
if (user == User.SYSTEM_USER) return;
|
||||||
|
|
||||||
Show();
|
Show();
|
||||||
|
|
||||||
if (user.Id == Header?.User.Id)
|
if (user.Id == Header?.User?.Id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
userReq?.Cancel();
|
userReq?.Cancel();
|
||||||
|
@ -84,11 +84,10 @@ namespace osu.Game.Screens.Menu
|
|||||||
|
|
||||||
private const double early_activation = 60;
|
private const double early_activation = 60;
|
||||||
|
|
||||||
|
public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks;
|
||||||
|
|
||||||
public OsuLogo()
|
public OsuLogo()
|
||||||
{
|
{
|
||||||
// Required to make Schedule calls run in OsuScreen even when we are not visible.
|
|
||||||
AlwaysPresent = true;
|
|
||||||
|
|
||||||
EarlyActivationMilliseconds = early_activation;
|
EarlyActivationMilliseconds = early_activation;
|
||||||
|
|
||||||
Size = new Vector2(default_size);
|
Size = new Vector2(default_size);
|
||||||
|
@ -69,7 +69,7 @@ namespace osu.Game.Screens.Play
|
|||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
KeyCounter = CreateKeyCounter(),
|
KeyCounter = CreateKeyCounter(adjustableClock as IFrameBasedClock),
|
||||||
HoldToQuit = CreateQuitButton(),
|
HoldToQuit = CreateQuitButton(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,12 +194,13 @@ namespace osu.Game.Screens.Play
|
|||||||
Margin = new MarginPadding { Top = 20 }
|
Margin = new MarginPadding { Top = 20 }
|
||||||
};
|
};
|
||||||
|
|
||||||
protected virtual KeyCounterCollection CreateKeyCounter() => new KeyCounterCollection
|
protected virtual KeyCounterCollection CreateKeyCounter(IFrameBasedClock offsetClock) => new KeyCounterCollection
|
||||||
{
|
{
|
||||||
FadeTime = 50,
|
FadeTime = 50,
|
||||||
Anchor = Anchor.BottomRight,
|
Anchor = Anchor.BottomRight,
|
||||||
Origin = Anchor.BottomRight,
|
Origin = Anchor.BottomRight,
|
||||||
Margin = new MarginPadding(10),
|
Margin = new MarginPadding(10),
|
||||||
|
AudioClock = offsetClock
|
||||||
};
|
};
|
||||||
|
|
||||||
protected virtual ScoreCounter CreateScoreCounter() => new ScoreCounter(6)
|
protected virtual ScoreCounter CreateScoreCounter() => new ScoreCounter(6)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
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;
|
||||||
@ -19,6 +21,9 @@ 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;
|
||||||
public int CountPresses
|
public int CountPresses
|
||||||
@ -45,7 +50,10 @@ namespace osu.Game.Screens.Play
|
|||||||
isLit = value;
|
isLit = value;
|
||||||
updateGlowSprite(value);
|
updateGlowSprite(value);
|
||||||
if (value && IsCounting)
|
if (value && IsCounting)
|
||||||
|
{
|
||||||
CountPresses++;
|
CountPresses++;
|
||||||
|
saveState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,6 +136,32 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetCount() => CountPresses = 0;
|
public void ResetCount()
|
||||||
|
{
|
||||||
|
CountPresses = 0;
|
||||||
|
states.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,15 +3,16 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using OpenTK.Graphics;
|
|
||||||
using osu.Framework.Configuration;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Input.EventArgs;
|
using osu.Framework.Input.EventArgs;
|
||||||
using osu.Framework.Input.States;
|
using osu.Framework.Input.States;
|
||||||
|
using osu.Framework.Timing;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Play
|
namespace osu.Game.Screens.Play
|
||||||
{
|
{
|
||||||
@ -37,6 +38,9 @@ namespace osu.Game.Screens.Play
|
|||||||
key.FadeTime = FadeTime;
|
key.FadeTime = FadeTime;
|
||||||
key.KeyDownTextColor = KeyDownTextColor;
|
key.KeyDownTextColor = KeyDownTextColor;
|
||||||
key.KeyUpTextColor = KeyUpTextColor;
|
key.KeyUpTextColor = KeyUpTextColor;
|
||||||
|
// Use the same clock object as SongProgress for saving KeyCounter state
|
||||||
|
if (AudioClock != null)
|
||||||
|
key.Clock = AudioClock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetCount()
|
public void ResetCount()
|
||||||
@ -118,6 +122,8 @@ namespace osu.Game.Screens.Play
|
|||||||
public override bool HandleKeyboardInput => receptor == null;
|
public override bool HandleKeyboardInput => receptor == null;
|
||||||
public override bool HandleMouseInput => receptor == null;
|
public override bool HandleMouseInput => receptor == null;
|
||||||
|
|
||||||
|
public IFrameBasedClock AudioClock { get; set; }
|
||||||
|
|
||||||
private Receptor receptor;
|
private Receptor receptor;
|
||||||
|
|
||||||
public Receptor GetReceptor()
|
public Receptor GetReceptor()
|
||||||
|
17
osu.Game/Screens/Play/KeyCounterState.cs
Normal file
17
osu.Game/Screens/Play/KeyCounterState.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play
|
||||||
|
{
|
||||||
|
public class KeyCounterState
|
||||||
|
{
|
||||||
|
public KeyCounterState(double time, int count)
|
||||||
|
{
|
||||||
|
Time = time;
|
||||||
|
Count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly double Time;
|
||||||
|
public readonly int Count;
|
||||||
|
}
|
||||||
|
}
|
@ -144,5 +144,14 @@ namespace osu.Game.Users
|
|||||||
public Badge[] Badges;
|
public Badge[] Badges;
|
||||||
|
|
||||||
public override string ToString() => Username;
|
public override string ToString() => Username;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A user instance for displaying locally created system messages.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly User SYSTEM_USER = new User
|
||||||
|
{
|
||||||
|
Username = "system",
|
||||||
|
Id = 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user