Maintain catch hit explosion by lifetime entries

- Fix hit explosion not showing when a replay is rewound to a time after a hit object is caught
This commit is contained in:
ekrctb 2021-06-04 19:46:50 +09:00
parent 2069a5bd28
commit 181f1da3d3
5 changed files with 66 additions and 38 deletions

View File

@ -216,7 +216,7 @@ namespace osu.Game.Rulesets.Catch.Tests
AddStep("enable hit lighting", () => config.SetValue(OsuSetting.HitLighting, true));
AddStep("catch fruit", () => attemptCatch(new Fruit()));
AddAssert("correct hit lighting colour", () =>
catcher.ChildrenOfType<HitExplosion>().First()?.ObjectColour == fruitColour);
catcher.ChildrenOfType<HitExplosion>().First()?.Entry?.ObjectColour == fruitColour);
}
[Test]

View File

@ -126,8 +126,7 @@ namespace osu.Game.Rulesets.Catch.UI
private float hyperDashTargetPosition;
private Bindable<bool> hitLighting;
private readonly DrawablePool<HitExplosion> hitExplosionPool;
private readonly Container<HitExplosion> hitExplosionContainer;
private readonly HitExplosionContainer hitExplosionContainer;
private readonly DrawablePool<CaughtFruit> caughtFruitPool;
private readonly DrawablePool<CaughtBanana> caughtBananaPool;
@ -148,7 +147,6 @@ namespace osu.Game.Rulesets.Catch.UI
InternalChildren = new Drawable[]
{
hitExplosionPool = new DrawablePool<HitExplosion>(10),
caughtFruitPool = new DrawablePool<CaughtFruit>(50),
caughtBananaPool = new DrawablePool<CaughtBanana>(100),
// less capacity is needed compared to fruit because droplet is not stacked
@ -173,7 +171,7 @@ namespace osu.Game.Rulesets.Catch.UI
Anchor = Anchor.TopCentre,
Alpha = 0,
},
hitExplosionContainer = new Container<HitExplosion>
hitExplosionContainer = new HitExplosionContainer
{
Anchor = Anchor.TopCentre,
Origin = Anchor.BottomCentre,
@ -297,7 +295,6 @@ namespace osu.Game.Rulesets.Catch.UI
caughtObjectContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject);
droppedObjectTarget.RemoveAll(d => d.HitObject == drawableObject.HitObject);
hitExplosionContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject);
}
/// <summary>
@ -508,15 +505,8 @@ namespace osu.Game.Rulesets.Catch.UI
return position;
}
private void addLighting(CatchHitObject hitObject, float x, Color4 colour)
{
HitExplosion hitExplosion = hitExplosionPool.Get();
hitExplosion.HitObject = hitObject;
hitExplosion.X = x;
hitExplosion.Scale = new Vector2(hitObject.Scale);
hitExplosion.ObjectColour = colour;
hitExplosionContainer.Add(hitExplosion);
}
private void addLighting(CatchHitObject hitObject, float x, Color4 colour) =>
hitExplosionContainer.Add(new HitExplosionEntry(Time.Current, x, hitObject.Scale, colour));
private CaughtObject getCaughtObject(PalpableCatchHitObject source)
{

View File

@ -5,31 +5,15 @@ using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Pooling;
using osu.Framework.Utils;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Objects.Pooling;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Rulesets.Catch.UI
{
public class HitExplosion : PoolableDrawable
public class HitExplosion : PoolableDrawableWithLifetime<HitExplosionEntry>
{
private Color4 objectColour;
public CatchHitObject HitObject;
public Color4 ObjectColour
{
get => objectColour;
set
{
if (objectColour == value) return;
objectColour = value;
onColourChanged();
}
}
private readonly CircularContainer largeFaint;
private readonly CircularContainer smallFaint;
private readonly CircularContainer directionalGlow1;
@ -83,9 +67,19 @@ namespace osu.Game.Rulesets.Catch.UI
};
}
protected override void PrepareForUse()
protected override void OnApply(HitExplosionEntry entry)
{
base.PrepareForUse();
X = entry.Position;
Scale = new Vector2(entry.Scale);
setColour(entry.ObjectColour);
using (BeginAbsoluteSequence(entry.LifetimeStart))
applyTransforms();
}
private void applyTransforms()
{
ClearTransforms(true);
const double duration = 400;
@ -99,11 +93,10 @@ namespace osu.Game.Rulesets.Catch.UI
directionalGlow1.Rotation = RNG.NextSingle(-angle_variangle, angle_variangle);
directionalGlow2.Rotation = RNG.NextSingle(-angle_variangle, angle_variangle);
this.FadeInFromZero(50).Then().FadeOut(duration, Easing.Out);
Expire(true);
this.FadeInFromZero(50).Then().FadeOut(duration, Easing.Out).Expire();
}
private void onColourChanged()
private void setColour(Color4 objectColour)
{
const float roundness = 100;

View File

@ -0,0 +1,22 @@
// 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.Graphics.Pooling;
using osu.Game.Rulesets.Objects.Pooling;
namespace osu.Game.Rulesets.Catch.UI
{
public class HitExplosionContainer : PooledDrawableWithLifetimeContainer<HitExplosionEntry, HitExplosion>
{
protected override bool RemoveRewoundEntry => true;
private readonly DrawablePool<HitExplosion> pool;
public HitExplosionContainer()
{
AddInternal(pool = new DrawablePool<HitExplosion>(10));
}
protected override HitExplosion GetDrawable(HitExplosionEntry entry) => pool.Get(d => d.Apply(entry));
}
}

View File

@ -0,0 +1,23 @@
// 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.Graphics.Performance;
using osuTK.Graphics;
namespace osu.Game.Rulesets.Catch.UI
{
public class HitExplosionEntry : LifetimeEntry
{
public readonly float Position;
public readonly float Scale;
public readonly Color4 ObjectColour;
public HitExplosionEntry(double startTime, float position, float scale, Color4 objectColour)
{
LifetimeStart = startTime;
Position = position;
Scale = scale;
ObjectColour = objectColour;
}
}
}