Pool caught objects and dropped objects

This commit is contained in:
ekrctb
2020-12-08 22:38:10 +09:00
parent a32dac00dd
commit 749d5380ca
4 changed files with 53 additions and 20 deletions

View File

@ -73,7 +73,10 @@ namespace osu.Game.Rulesets.Catch.Tests
SetContents(() => SetContents(() =>
{ {
var droppedObjectContainer = new Container(); var droppedObjectContainer = new Container
{
RelativeSizeAxes = Axes.Both
};
return new CatchInputManager(catchRuleset) return new CatchInputManager(catchRuleset)
{ {

View File

@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
[Cached(typeof(IHasCatchObjectState))] [Cached(typeof(IHasCatchObjectState))]
public abstract class CaughtObject : SkinnableDrawable, IHasCatchObjectState public abstract class CaughtObject : SkinnableDrawable, IHasCatchObjectState
{ {
public CatchHitObject HitObject { get; private set; } public PalpableCatchHitObject HitObject { get; private set; }
public Bindable<Color4> AccentColour { get; } = new Bindable<Color4>(); public Bindable<Color4> AccentColour { get; } = new Bindable<Color4>();
public Bindable<bool> HyperDash { get; } = new Bindable<bool>(); public Bindable<bool> HyperDash { get; } = new Bindable<bool>();
@ -29,7 +29,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
protected CaughtObject(CatchSkinComponents skinComponent, Func<ISkinComponent, Drawable> defaultImplementation) protected CaughtObject(CatchSkinComponents skinComponent, Func<ISkinComponent, Drawable> defaultImplementation)
: base(new CatchSkinComponent(skinComponent), defaultImplementation) : base(new CatchSkinComponent(skinComponent), defaultImplementation)
{ {
Anchor = Anchor.TopCentre;
Origin = Anchor.Centre; Origin = Anchor.Centre;
RelativeSizeAxes = Axes.None; RelativeSizeAxes = Axes.None;
@ -44,6 +43,17 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
AccentColour.Value = objectState.AccentColour.Value; AccentColour.Value = objectState.AccentColour.Value;
HyperDash.Value = objectState.HyperDash.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 public class CaughtFruit : CaughtObject, IHasFruitState

View File

@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
{ {
public interface IHasCatchObjectState public interface IHasCatchObjectState
{ {
CatchHitObject HitObject { get; } PalpableCatchHitObject HitObject { get; }
Bindable<Color4> AccentColour { get; } Bindable<Color4> AccentColour { get; }
Bindable<bool> HyperDash { get; } Bindable<bool> HyperDash { get; }

View File

@ -108,6 +108,10 @@ namespace osu.Game.Rulesets.Catch.UI
private readonly DrawablePool<HitExplosion> hitExplosionPool; private readonly DrawablePool<HitExplosion> hitExplosionPool;
private readonly Container<HitExplosion> hitExplosionContainer; private readonly Container<HitExplosion> hitExplosionContainer;
private readonly DrawablePool<CaughtFruit> caughtFruitPool;
private readonly DrawablePool<CaughtBanana> caughtBananaPool;
private readonly DrawablePool<CaughtDroplet> caughtDropletPool;
public Catcher([NotNull] Container trailsTarget, [NotNull] Container droppedObjectTarget, BeatmapDifficulty difficulty = null) public Catcher([NotNull] Container trailsTarget, [NotNull] Container droppedObjectTarget, BeatmapDifficulty difficulty = null)
{ {
this.trailsTarget = trailsTarget; this.trailsTarget = trailsTarget;
@ -124,6 +128,10 @@ namespace osu.Game.Rulesets.Catch.UI
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
hitExplosionPool = new DrawablePool<HitExplosion>(10), 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
caughtDropletPool = new DrawablePool<CaughtDroplet>(25),
caughtFruitContainer = new Container<CaughtObject> caughtFruitContainer = new Container<CaughtObject>
{ {
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
@ -452,11 +460,12 @@ namespace osu.Game.Rulesets.Catch.UI
private void placeCaughtObject(DrawablePalpableHasCatchHitObject drawableObject, Vector2 position) private void placeCaughtObject(DrawablePalpableHasCatchHitObject drawableObject, Vector2 position)
{ {
var caughtObject = createCaughtObject(drawableObject.HitObject); var caughtObject = getCaughtObject(drawableObject.HitObject);
if (caughtObject == null) return; if (caughtObject == null) return;
caughtObject.CopyFrom(drawableObject); caughtObject.CopyFrom(drawableObject);
caughtObject.Anchor = Anchor.TopCentre;
caughtObject.Position = position; caughtObject.Position = position;
caughtObject.Scale /= 2; caughtObject.Scale /= 2;
@ -494,52 +503,62 @@ namespace osu.Game.Rulesets.Catch.UI
hitExplosionContainer.Add(hitExplosion); hitExplosionContainer.Add(hitExplosion);
} }
private CaughtObject createCaughtObject(PalpableCatchHitObject source) private CaughtObject getCaughtObject(PalpableCatchHitObject source)
{ {
switch (source) switch (source)
{ {
case Fruit _: case Fruit _:
return new CaughtFruit(); return caughtFruitPool.Get();
case Banana _: case Banana _:
return new CaughtBanana(); return caughtBananaPool.Get();
case Droplet _: case Droplet _:
return new CaughtDroplet(); return caughtDropletPool.Get();
default: default:
return null; 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) private void clearPlate(DroppedObjectAnimation animation)
{ {
var caughtObjects = caughtFruitContainer.Children.ToArray(); var caughtObjects = caughtFruitContainer.Children.ToArray();
var droppedObjects = caughtObjects.Select(getDroppedObject).ToArray();
caughtFruitContainer.Clear(false); caughtFruitContainer.Clear(false);
droppedObjectTarget.AddRange(caughtObjects); droppedObjectTarget.AddRange(droppedObjects);
foreach (var caughtObject in caughtObjects) foreach (var droppedObject in droppedObjects)
drop(caughtObject, animation); applyDropAnimation(droppedObject, animation);
} }
private void removeFromPlate(CaughtObject caughtObject, DroppedObjectAnimation animation) private void removeFromPlate(CaughtObject caughtObject, DroppedObjectAnimation animation)
{ {
var droppedObject = getDroppedObject(caughtObject);
if (!caughtFruitContainer.Remove(caughtObject)) if (!caughtFruitContainer.Remove(caughtObject))
throw new InvalidOperationException("Can only drop a caught object on the plate"); 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) switch (animation)
{ {
case DroppedObjectAnimation.Drop: case DroppedObjectAnimation.Drop:
@ -548,6 +567,7 @@ namespace osu.Game.Rulesets.Catch.UI
break; break;
case DroppedObjectAnimation.Explode: 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.MoveToY(d.Y - 50, 250, Easing.OutSine).Then().MoveToY(d.Y + 50, 500, Easing.InSine);
d.MoveToX(d.X + originalX * 6, 1000); d.MoveToX(d.X + originalX * 6, 1000);
d.FadeOut(750); d.FadeOut(750);