mirror of
https://github.com/osukey/osukey.git
synced 2025-07-02 00:40:09 +09:00
Move catcher trail generation logic to Catcher
It resolves mutual dependency of `Catcher` and `CatcherTrailDisplay`. Trail generation logic is moved to `Catcher`. The generation logic no longer uses delayed scheduling because the hidden state is hard to manage. Instead, the last time a trail is generated is calculated and used. The new logic has a different behavior when the dash key is pressed in succession under 50ms, but it is not noticeable for normal plays.
This commit is contained in:
@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
var skin = new TestSkin { FlipCatcherPlate = flip };
|
var skin = new TestSkin { FlipCatcherPlate = flip };
|
||||||
container.Child = new SkinProvidingContainer(skin)
|
container.Child = new SkinProvidingContainer(skin)
|
||||||
{
|
{
|
||||||
Child = catcher = new Catcher(new Container(), new DroppedObjectContainer())
|
Child = catcher = new Catcher(new CatcherTrailDisplay(), new DroppedObjectContainer())
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre
|
Anchor = Anchor.Centre
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuConfigManager config { get; set; }
|
private OsuConfigManager config { get; set; }
|
||||||
|
|
||||||
private Container trailContainer;
|
private CatcherTrailDisplay trailDisplay;
|
||||||
|
|
||||||
private DroppedObjectContainer droppedObjectContainer;
|
private DroppedObjectContainer droppedObjectContainer;
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
CircleSize = 0,
|
CircleSize = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
trailContainer = new Container();
|
trailDisplay = new CatcherTrailDisplay();
|
||||||
droppedObjectContainer = new DroppedObjectContainer();
|
droppedObjectContainer = new DroppedObjectContainer();
|
||||||
|
|
||||||
Child = new Container
|
Child = new Container
|
||||||
@ -54,8 +54,8 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
droppedObjectContainer,
|
droppedObjectContainer,
|
||||||
catcher = new TestCatcher(trailContainer, droppedObjectContainer, difficulty),
|
catcher = new TestCatcher(trailDisplay, droppedObjectContainer, difficulty),
|
||||||
trailContainer,
|
trailDisplay,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -294,8 +294,8 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
{
|
{
|
||||||
public IEnumerable<CaughtObject> CaughtObjects => this.ChildrenOfType<CaughtObject>();
|
public IEnumerable<CaughtObject> CaughtObjects => this.ChildrenOfType<CaughtObject>();
|
||||||
|
|
||||||
public TestCatcher(Container trailsTarget, DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty)
|
public TestCatcher(CatcherTrailDisplay trails, DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty)
|
||||||
: base(trailsTarget, droppedObjectTarget, difficulty)
|
: base(trails, droppedObjectTarget, difficulty)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,11 +121,13 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
{
|
{
|
||||||
public TestCatcherArea(BeatmapDifficulty beatmapDifficulty)
|
public TestCatcherArea(BeatmapDifficulty beatmapDifficulty)
|
||||||
{
|
{
|
||||||
var droppedObjectContainer = new DroppedObjectContainer();
|
var trailDisplay = new CatcherTrailDisplay { Depth = -1 };
|
||||||
|
Add(trailDisplay);
|
||||||
|
|
||||||
|
var droppedObjectContainer = new DroppedObjectContainer();
|
||||||
Add(droppedObjectContainer);
|
Add(droppedObjectContainer);
|
||||||
|
|
||||||
Catcher = new Catcher(this, droppedObjectContainer, beatmapDifficulty)
|
Catcher = new Catcher(trailDisplay, droppedObjectContainer, beatmapDifficulty)
|
||||||
{
|
{
|
||||||
X = CatchPlayfield.CENTER_X
|
X = CatchPlayfield.CENTER_X
|
||||||
};
|
};
|
||||||
|
@ -113,30 +113,28 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
private void checkHyperDashCatcherColour(ISkin skin, Color4 expectedCatcherColour, Color4? expectedEndGlowColour = null)
|
private void checkHyperDashCatcherColour(ISkin skin, Color4 expectedCatcherColour, Color4? expectedEndGlowColour = null)
|
||||||
{
|
{
|
||||||
Container trailsContainer = null;
|
|
||||||
Catcher catcher = null;
|
|
||||||
CatcherTrailDisplay trails = null;
|
CatcherTrailDisplay trails = null;
|
||||||
|
Catcher catcher = null;
|
||||||
|
|
||||||
AddStep("create hyper-dashing catcher", () =>
|
AddStep("create hyper-dashing catcher", () =>
|
||||||
{
|
{
|
||||||
trailsContainer = new Container();
|
trails = new CatcherTrailDisplay();
|
||||||
Child = setupSkinHierarchy(new Container
|
Child = setupSkinHierarchy(new Container
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
catcher = new Catcher(trailsContainer, new DroppedObjectContainer())
|
catcher = new Catcher(trails, new DroppedObjectContainer())
|
||||||
{
|
{
|
||||||
Scale = new Vector2(4)
|
Scale = new Vector2(4)
|
||||||
},
|
},
|
||||||
trailsContainer
|
trails
|
||||||
}
|
}
|
||||||
}, skin);
|
}, skin);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("get trails container", () =>
|
AddStep("start hyper-dash", () =>
|
||||||
{
|
{
|
||||||
trails = trailsContainer.OfType<CatcherTrailDisplay>().Single();
|
|
||||||
catcher.SetHyperDashState(2);
|
catcher.SetHyperDashState(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
@ -45,14 +44,14 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
var trailContainer = new Container
|
var trailDisplay = new CatcherTrailDisplay
|
||||||
{
|
{
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
Origin = Anchor.TopLeft
|
Origin = Anchor.TopLeft
|
||||||
};
|
};
|
||||||
var droppedObjectContainer = new DroppedObjectContainer();
|
var droppedObjectContainer = new DroppedObjectContainer();
|
||||||
|
|
||||||
Catcher = new Catcher(trailContainer, droppedObjectContainer, difficulty)
|
Catcher = new Catcher(trailDisplay, droppedObjectContainer, difficulty)
|
||||||
{
|
{
|
||||||
X = CENTER_X
|
X = CENTER_X
|
||||||
};
|
};
|
||||||
@ -70,7 +69,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
Origin = Anchor.TopLeft,
|
Origin = Anchor.TopLeft,
|
||||||
Catcher = Catcher,
|
Catcher = Catcher,
|
||||||
},
|
},
|
||||||
trailContainer,
|
trailDisplay,
|
||||||
HitObjectContainer,
|
HitObjectContainer,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -71,10 +71,10 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private const float caught_fruit_scale_adjust = 0.5f;
|
private const float caught_fruit_scale_adjust = 0.5f;
|
||||||
|
|
||||||
[NotNull]
|
/// <summary>
|
||||||
private readonly Container trailsTarget;
|
/// Contains trails and afterimages (also called "end glow" in code) of the catcher.
|
||||||
|
/// </summary>
|
||||||
private CatcherTrailDisplay trails;
|
private readonly CatcherTrailDisplay trails;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains caught objects on the plate.
|
/// Contains caught objects on the plate.
|
||||||
@ -92,20 +92,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
private set => Body.AnimationState.Value = value;
|
private set => Body.AnimationState.Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool dashing;
|
public bool Dashing { get; set; }
|
||||||
|
|
||||||
public bool Dashing
|
|
||||||
{
|
|
||||||
get => dashing;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == dashing) return;
|
|
||||||
|
|
||||||
dashing = value;
|
|
||||||
|
|
||||||
updateTrailVisibility();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The currently facing direction.
|
/// The currently facing direction.
|
||||||
@ -138,9 +125,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
private readonly DrawablePool<CaughtBanana> caughtBananaPool;
|
private readonly DrawablePool<CaughtBanana> caughtBananaPool;
|
||||||
private readonly DrawablePool<CaughtDroplet> caughtDropletPool;
|
private readonly DrawablePool<CaughtDroplet> caughtDropletPool;
|
||||||
|
|
||||||
public Catcher([NotNull] Container trailsTarget, [NotNull] DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty = null)
|
public Catcher([NotNull] CatcherTrailDisplay trails, [NotNull] DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty = null)
|
||||||
{
|
{
|
||||||
this.trailsTarget = trailsTarget;
|
this.trails = trails;
|
||||||
this.droppedObjectTarget = droppedObjectTarget;
|
this.droppedObjectTarget = droppedObjectTarget;
|
||||||
|
|
||||||
Origin = Anchor.TopCentre;
|
Origin = Anchor.TopCentre;
|
||||||
@ -177,15 +164,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
private void load(OsuConfigManager config)
|
private void load(OsuConfigManager config)
|
||||||
{
|
{
|
||||||
hitLighting = config.GetBindable<bool>(OsuSetting.HitLighting);
|
hitLighting = config.GetBindable<bool>(OsuSetting.HitLighting);
|
||||||
trails = new CatcherTrailDisplay(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
// don't add in above load as we may potentially modify a parent in an unsafe manner.
|
|
||||||
trailsTarget.Add(trails);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -313,7 +291,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
if (!wasHyperDashing)
|
if (!wasHyperDashing)
|
||||||
{
|
{
|
||||||
trails.DisplayEndGlow();
|
trails.DisplayEndGlow(CurrentState, X, Scale * Body.Scale);
|
||||||
runHyperDashStateTransition(true);
|
runHyperDashStateTransition(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,13 +309,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
private void runHyperDashStateTransition(bool hyperDashing)
|
private void runHyperDashStateTransition(bool hyperDashing)
|
||||||
{
|
{
|
||||||
updateTrailVisibility();
|
|
||||||
|
|
||||||
this.FadeColour(hyperDashing ? hyperDashColour : Color4.White, HYPER_DASH_TRANSITION_DURATION, Easing.OutQuint);
|
this.FadeColour(hyperDashing ? hyperDashColour : Color4.White, HYPER_DASH_TRANSITION_DURATION, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTrailVisibility() => trails.DisplayTrail = Dashing || HyperDashing;
|
|
||||||
|
|
||||||
protected override void SkinChanged(ISkinSource skin)
|
protected override void SkinChanged(ISkinSource skin)
|
||||||
{
|
{
|
||||||
base.SkinChanged(skin);
|
base.SkinChanged(skin);
|
||||||
@ -373,6 +347,15 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
X = hyperDashTargetPosition;
|
X = hyperDashTargetPosition;
|
||||||
SetHyperDashState();
|
SetHyperDashState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Dashing || HyperDashing)
|
||||||
|
{
|
||||||
|
double lastTrailTime = trails.LastDashTrail?.LifetimeStart ?? double.NegativeInfinity;
|
||||||
|
double generationInterval = HyperDashing ? 25 : 50;
|
||||||
|
|
||||||
|
if (Time.Current - lastTrailTime >= generationInterval)
|
||||||
|
trails.DisplayDashTrail(CurrentState, X, Scale * Body.Scale, HyperDashing);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void placeCaughtObject(DrawablePalpableCatchHitObject drawableObject, Vector2 position)
|
private void placeCaughtObject(DrawablePalpableCatchHitObject drawableObject, Vector2 position)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// 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;
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -17,7 +17,10 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CatcherTrailDisplay : CompositeDrawable
|
public class CatcherTrailDisplay : CompositeDrawable
|
||||||
{
|
{
|
||||||
private readonly Catcher catcher;
|
[CanBeNull]
|
||||||
|
public CatcherTrail LastDashTrail => dashTrails.Concat(hyperDashTrails)
|
||||||
|
.OrderByDescending(trail => trail.LifetimeStart)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
private readonly DrawablePool<CatcherTrail> trailPool;
|
private readonly DrawablePool<CatcherTrail> trailPool;
|
||||||
|
|
||||||
@ -55,30 +58,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool trail;
|
public CatcherTrailDisplay()
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether to start displaying trails following the catcher.
|
|
||||||
/// </summary>
|
|
||||||
public bool DisplayTrail
|
|
||||||
{
|
{
|
||||||
get => trail;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (trail == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
trail = value;
|
|
||||||
|
|
||||||
if (trail)
|
|
||||||
displayTrail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public CatcherTrailDisplay([NotNull] Catcher catcher)
|
|
||||||
{
|
|
||||||
this.catcher = catcher ?? throw new ArgumentNullException(nameof(catcher));
|
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
@ -93,9 +74,11 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Displays a single end-glow catcher sprite.
|
/// Displays a single end-glow catcher sprite.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void DisplayEndGlow()
|
public void DisplayEndGlow(CatcherAnimationState animationState, float x, Vector2 scale)
|
||||||
{
|
{
|
||||||
var endGlow = createTrailSprite(endGlowSprites);
|
var endGlow = createTrail(animationState, x, scale);
|
||||||
|
|
||||||
|
endGlowSprites.Add(endGlow);
|
||||||
|
|
||||||
endGlow.MoveToOffset(new Vector2(0, -10), 1200, Easing.In);
|
endGlow.MoveToOffset(new Vector2(0, -10), 1200, Easing.In);
|
||||||
endGlow.ScaleTo(endGlow.Scale * 0.95f).ScaleTo(endGlow.Scale * 1.2f, 1200, Easing.In);
|
endGlow.ScaleTo(endGlow.Scale * 0.95f).ScaleTo(endGlow.Scale * 1.2f, 1200, Easing.In);
|
||||||
@ -103,28 +86,26 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
endGlow.Expire(true);
|
endGlow.Expire(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayTrail()
|
public void DisplayDashTrail(CatcherAnimationState animationState, float x, Vector2 scale, bool hyperDashing)
|
||||||
{
|
{
|
||||||
if (!DisplayTrail)
|
var sprite = createTrail(animationState, x, scale);
|
||||||
return;
|
|
||||||
|
|
||||||
var sprite = createTrailSprite(catcher.HyperDashing ? hyperDashTrails : dashTrails);
|
if (hyperDashing)
|
||||||
|
hyperDashTrails.Add(sprite);
|
||||||
|
else
|
||||||
|
dashTrails.Add(sprite);
|
||||||
|
|
||||||
sprite.FadeTo(0.4f).FadeOut(800, Easing.OutQuint);
|
sprite.FadeTo(0.4f).FadeOut(800, Easing.OutQuint);
|
||||||
sprite.Expire(true);
|
sprite.Expire(true);
|
||||||
|
|
||||||
Scheduler.AddDelayed(displayTrail, catcher.HyperDashing ? 25 : 50);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CatcherTrail createTrailSprite(Container<CatcherTrail> target)
|
private CatcherTrail createTrail(CatcherAnimationState animationState, float x, Vector2 scale)
|
||||||
{
|
{
|
||||||
CatcherTrail sprite = trailPool.Get();
|
CatcherTrail sprite = trailPool.Get();
|
||||||
|
|
||||||
sprite.AnimationState = catcher.CurrentState;
|
sprite.AnimationState = animationState;
|
||||||
sprite.Scale = catcher.Scale * catcher.Body.Scale;
|
sprite.Scale = scale;
|
||||||
sprite.Position = catcher.Position;
|
sprite.Position = new Vector2(x, 0);
|
||||||
|
|
||||||
target.Add(sprite);
|
|
||||||
|
|
||||||
return sprite;
|
return sprite;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user