From 749d5380ca5a1c5bd118307e4f9459cd7df00130 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 22:38:10 +0900 Subject: [PATCH] Pool caught objects and dropped objects --- .../TestSceneCatcherArea.cs | 5 +- .../Objects/Drawables/CaughtObject.cs | 14 ++++- .../Objects/Drawables/IHasCatchObjectState.cs | 2 +- osu.Game.Rulesets.Catch/UI/Catcher.cs | 52 +++++++++++++------ 4 files changed, 53 insertions(+), 20 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index 8602c7aad1..3d5e44476e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -73,7 +73,10 @@ private void createCatcher(float size) SetContents(() => { - var droppedObjectContainer = new Container(); + var droppedObjectContainer = new Container + { + RelativeSizeAxes = Axes.Both + }; return new CatchInputManager(catchRuleset) { diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs index d3555ea771..f36d287126 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables [Cached(typeof(IHasCatchObjectState))] public abstract class CaughtObject : SkinnableDrawable, IHasCatchObjectState { - public CatchHitObject HitObject { get; private set; } + public PalpableCatchHitObject HitObject { get; private set; } public Bindable AccentColour { get; } = new Bindable(); public Bindable HyperDash { get; } = new Bindable(); @@ -29,7 +29,6 @@ public abstract class CaughtObject : SkinnableDrawable, IHasCatchObjectState protected CaughtObject(CatchSkinComponents skinComponent, Func defaultImplementation) : base(new CatchSkinComponent(skinComponent), defaultImplementation) { - Anchor = Anchor.TopCentre; Origin = Anchor.Centre; RelativeSizeAxes = Axes.None; @@ -44,6 +43,17 @@ public virtual void CopyFrom(IHasCatchObjectState objectState) AccentColour.Value = objectState.AccentColour.Value; HyperDash.Value = objectState.HyperDash.Value; } + + protected override void FreeAfterUse() + { + ClearTransforms(); + + Alpha = 1; + LifetimeStart = double.MinValue; + LifetimeEnd = double.MaxValue; + + base.FreeAfterUse(); + } } public class CaughtFruit : CaughtObject, IHasFruitState diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs index 01d833b61a..a282bc5da0 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { public interface IHasCatchObjectState { - CatchHitObject HitObject { get; } + PalpableCatchHitObject HitObject { get; } Bindable AccentColour { get; } Bindable HyperDash { get; } diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 4d540bce03..7aecd95efd 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -108,6 +108,10 @@ protected set private readonly DrawablePool hitExplosionPool; private readonly Container hitExplosionContainer; + private readonly DrawablePool caughtFruitPool; + private readonly DrawablePool caughtBananaPool; + private readonly DrawablePool caughtDropletPool; + public Catcher([NotNull] Container trailsTarget, [NotNull] Container droppedObjectTarget, BeatmapDifficulty difficulty = null) { this.trailsTarget = trailsTarget; @@ -124,6 +128,10 @@ public Catcher([NotNull] Container trailsTarget, [NotNull] Container droppedObje InternalChildren = new Drawable[] { hitExplosionPool = new DrawablePool(10), + caughtFruitPool = new DrawablePool(50), + caughtBananaPool = new DrawablePool(100), + // less capacity is needed compared to fruit because droplet is not stacked + caughtDropletPool = new DrawablePool(25), caughtFruitContainer = new Container { Anchor = Anchor.TopCentre, @@ -452,11 +460,12 @@ private void updateState(CatcherAnimationState state) private void placeCaughtObject(DrawablePalpableHasCatchHitObject drawableObject, Vector2 position) { - var caughtObject = createCaughtObject(drawableObject.HitObject); + var caughtObject = getCaughtObject(drawableObject.HitObject); if (caughtObject == null) return; caughtObject.CopyFrom(drawableObject); + caughtObject.Anchor = Anchor.TopCentre; caughtObject.Position = position; caughtObject.Scale /= 2; @@ -494,52 +503,62 @@ private void addLighting(CatchHitObject hitObject, float x, Color4 colour) hitExplosionContainer.Add(hitExplosion); } - private CaughtObject createCaughtObject(PalpableCatchHitObject source) + private CaughtObject getCaughtObject(PalpableCatchHitObject source) { switch (source) { case Fruit _: - return new CaughtFruit(); + return caughtFruitPool.Get(); case Banana _: - return new CaughtBanana(); + return caughtBananaPool.Get(); case Droplet _: - return new CaughtDroplet(); + return caughtDropletPool.Get(); default: return null; } } + private CaughtObject getDroppedObject(CaughtObject caughtObject) + { + var droppedObject = getCaughtObject(caughtObject.HitObject); + + droppedObject.CopyFrom(caughtObject); + droppedObject.Anchor = Anchor.TopLeft; + droppedObject.Position = caughtFruitContainer.ToSpaceOfOtherDrawable(caughtObject.DrawPosition, droppedObjectTarget); + + return droppedObject; + } + private void clearPlate(DroppedObjectAnimation animation) { var caughtObjects = caughtFruitContainer.Children.ToArray(); + var droppedObjects = caughtObjects.Select(getDroppedObject).ToArray(); + caughtFruitContainer.Clear(false); - droppedObjectTarget.AddRange(caughtObjects); + droppedObjectTarget.AddRange(droppedObjects); - foreach (var caughtObject in caughtObjects) - drop(caughtObject, animation); + foreach (var droppedObject in droppedObjects) + applyDropAnimation(droppedObject, animation); } private void removeFromPlate(CaughtObject caughtObject, DroppedObjectAnimation animation) { + var droppedObject = getDroppedObject(caughtObject); + if (!caughtFruitContainer.Remove(caughtObject)) throw new InvalidOperationException("Can only drop a caught object on the plate"); - droppedObjectTarget.Add(caughtObject); + droppedObjectTarget.Add(droppedObject); - drop(caughtObject, animation); + applyDropAnimation(droppedObject, animation); } - private void drop(CaughtObject d, DroppedObjectAnimation animation) + private void applyDropAnimation(Drawable d, DroppedObjectAnimation animation) { - var originalX = d.X * Scale.X; - - d.Anchor = Anchor.TopLeft; - d.Position = caughtFruitContainer.ToSpaceOfOtherDrawable(d.DrawPosition, droppedObjectTarget); - switch (animation) { case DroppedObjectAnimation.Drop: @@ -548,6 +567,7 @@ private void drop(CaughtObject d, DroppedObjectAnimation animation) break; case DroppedObjectAnimation.Explode: + var originalX = droppedObjectTarget.ToSpaceOfOtherDrawable(d.DrawPosition, caughtFruitContainer).X * Scale.X; d.MoveToY(d.Y - 50, 250, Easing.OutSine).Then().MoveToY(d.Y + 50, 500, Easing.InSine); d.MoveToX(d.X + originalX * 6, 1000); d.FadeOut(750);