1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 05:32:54 +08:00

Move Shake logic local to hitcircle/slider

This commit is contained in:
Dean Herbert 2022-09-22 14:30:01 +09:00
parent 78625fda7d
commit b844d76311
5 changed files with 53 additions and 37 deletions

View File

@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
if (!objects.Any()) if (!objects.Any())
return false; return false;
return objects.All(o => Precision.AlmostEquals(o.ChildrenOfType<ShakeContainer>().First().Children.OfType<Container>().Single().Scale.X, target)); return objects.All(o => Precision.AlmostEquals(o.ChildrenOfType<Container>().First().Scale.X, target));
} }
private bool checkSomeHit() private bool checkSomeHit()

View File

@ -12,6 +12,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Graphics.Containers;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
@ -47,6 +48,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
} }
private ShakeContainer shakeContainer;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
@ -72,18 +75,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
return true; return true;
}, },
}, },
CirclePiece = new SkinnableDrawable(new OsuSkinComponent(CirclePieceComponent), _ => new MainCirclePiece()) shakeContainer = new ShakeContainer
{ {
Anchor = Anchor.Centre, ShakeDuration = 30,
Origin = Anchor.Centre,
},
ApproachCircle = new ProxyableSkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.ApproachCircle), _ => new DefaultApproachCircle())
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Alpha = 0, Children = new Drawable[]
Scale = new Vector2(4), {
CirclePiece = new SkinnableDrawable(new OsuSkinComponent(CirclePieceComponent), _ => new MainCirclePiece())
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
ApproachCircle = new ProxyableSkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.ApproachCircle), _ => new DefaultApproachCircle())
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Alpha = 0,
Scale = new Vector2(4),
}
}
} }
} }
}, },
@ -123,6 +134,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
} }
} }
public override void Shake() => shakeContainer.Shake();
protected override void CheckForResult(bool userTriggered, double timeOffset) protected override void CheckForResult(bool userTriggered, double timeOffset)
{ {
Debug.Assert(HitObject.HitWindows != null); Debug.Assert(HitObject.HitWindows != null);
@ -139,7 +152,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
if (result == HitResult.None || CheckHittable?.Invoke(this, Time.Current) == false) if (result == HitResult.None || CheckHittable?.Invoke(this, Time.Current) == false)
{ {
Shake(Math.Abs(timeOffset) - HitObject.HitWindows.WindowFor(HitResult.Miss)); Shake();
return; return;
} }

View File

@ -6,12 +6,11 @@
using System; using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Graphics.Containers;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Osu.Objects.Drawables namespace osu.Game.Rulesets.Osu.Objects.Drawables
@ -34,8 +33,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
/// </summary> /// </summary>
public Func<DrawableHitObject, double, bool> CheckHittable; public Func<DrawableHitObject, double, bool> CheckHittable;
private ShakeContainer shakeContainer;
protected DrawableOsuHitObject(OsuHitObject hitObject) protected DrawableOsuHitObject(OsuHitObject hitObject)
: base(hitObject) : base(hitObject)
{ {
@ -45,12 +42,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private void load() private void load()
{ {
Alpha = 0; Alpha = 0;
base.AddInternal(shakeContainer = new ShakeContainer
{
ShakeDuration = 30,
RelativeSizeAxes = Axes.Both
});
} }
protected override void OnApply() protected override void OnApply()
@ -73,18 +64,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
ScaleBindable.UnbindFrom(HitObject.ScaleBindable); ScaleBindable.UnbindFrom(HitObject.ScaleBindable);
} }
// Forward all internal management to shakeContainer.
// This is a bit ugly but we don't have the concept of InternalContent so it'll have to do for now. (https://github.com/ppy/osu-framework/issues/1690)
protected override void AddInternal(Drawable drawable) => shakeContainer.Add(drawable);
protected override void ClearInternal(bool disposeChildren = true) => shakeContainer.Clear(disposeChildren);
protected override bool RemoveInternal(Drawable drawable, bool disposeImmediately) => shakeContainer.Remove(drawable, disposeImmediately);
protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt;
private OsuInputManager osuActionInputManager; private OsuInputManager osuActionInputManager;
internal OsuInputManager OsuActionInputManager => osuActionInputManager ??= GetContainingInputManager() as OsuInputManager; internal OsuInputManager OsuActionInputManager => osuActionInputManager ??= GetContainingInputManager() as OsuInputManager;
public virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength); /// <summary>
/// Shake the hit object in case it was clicked far too early or late (aka "note lock").
/// </summary>
public virtual void Shake() { }
/// <summary> /// <summary>
/// Causes this <see cref="DrawableOsuHitObject"/> to get missed, disregarding all conditions in implementations of <see cref="DrawableHitObject.CheckForResult"/>. /// Causes this <see cref="DrawableOsuHitObject"/> to get missed, disregarding all conditions in implementations of <see cref="DrawableHitObject.CheckForResult"/>.

View File

@ -11,6 +11,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Graphics.Containers;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Skinning; using osu.Game.Rulesets.Osu.Skinning;
@ -34,6 +35,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public SkinnableDrawable Body { get; private set; } public SkinnableDrawable Body { get; private set; }
private ShakeContainer shakeContainer;
/// <summary> /// <summary>
/// A target container which can be used to add top level elements to the slider's display. /// A target container which can be used to add top level elements to the slider's display.
/// Intended to be used for proxy purposes only. /// Intended to be used for proxy purposes only.
@ -76,10 +79,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
Body = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBody), _ => new DefaultSliderBody(), confineMode: ConfineMode.NoScaling), shakeContainer = new ShakeContainer
tailContainer = new Container<DrawableSliderTail> { RelativeSizeAxes = Axes.Both }, {
tickContainer = new Container<DrawableSliderTick> { RelativeSizeAxes = Axes.Both }, ShakeDuration = 30,
repeatContainer = new Container<DrawableSliderRepeat> { RelativeSizeAxes = Axes.Both }, RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
Body = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBody), _ => new DefaultSliderBody(), confineMode: ConfineMode.NoScaling),
tailContainer = new Container<DrawableSliderTail> { RelativeSizeAxes = Axes.Both },
tickContainer = new Container<DrawableSliderTick> { RelativeSizeAxes = Axes.Both },
repeatContainer = new Container<DrawableSliderRepeat> { RelativeSizeAxes = Axes.Both },
}
},
// slider head is not included in shake as it handles hit detection, and handles its own shaking.
headContainer = new Container<DrawableSliderHead> { RelativeSizeAxes = Axes.Both }, headContainer = new Container<DrawableSliderHead> { RelativeSizeAxes = Axes.Both },
OverlayElementContainer = new Container { RelativeSizeAxes = Axes.Both, }, OverlayElementContainer = new Container { RelativeSizeAxes = Axes.Both, },
Ball, Ball,
@ -109,6 +121,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
PathVersion.BindTo(HitObject.Path.Version); PathVersion.BindTo(HitObject.Path.Version);
} }
public override void Shake() => shakeContainer.Shake();
protected override void OnFree() protected override void OnFree()
{ {
base.OnFree(); base.OnFree();

View File

@ -63,7 +63,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
pathVersion.BindTo(DrawableSlider.PathVersion); pathVersion.BindTo(DrawableSlider.PathVersion);
OnShake = DrawableSlider.Shake;
CheckHittable = (d, t) => DrawableSlider.CheckHittable?.Invoke(d, t) ?? true; CheckHittable = (d, t) => DrawableSlider.CheckHittable?.Invoke(d, t) ?? true;
} }
@ -96,9 +95,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
return result.IsHit() ? HitResult.LargeTickHit : HitResult.LargeTickMiss; return result.IsHit() ? HitResult.LargeTickHit : HitResult.LargeTickMiss;
} }
public Action<double> OnShake; public override void Shake()
{
public override void Shake(double maximumLength) => OnShake?.Invoke(maximumLength); base.Shake();
DrawableSlider.Shake();
}
private void updatePosition() private void updatePosition()
{ {