mirror of
https://github.com/ppy/osu.git
synced 2024-12-13 07:43:00 +08:00
Make object on the catcher plate separate CaughtObject class
This commit is contained in:
parent
ed50fd445e
commit
c301223d8c
@ -275,7 +275,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
|
||||
public class TestCatcher : Catcher
|
||||
{
|
||||
public IEnumerable<DrawablePalpableCatchHitObject> CaughtObjects => this.ChildrenOfType<DrawablePalpableCatchHitObject>();
|
||||
public IEnumerable<CaughtObject> CaughtObjects => this.ChildrenOfType<CaughtObject>();
|
||||
|
||||
public TestCatcher(Container trailsTarget, Container droppedObjectTarget, BeatmapDifficulty difficulty)
|
||||
: base(trailsTarget, droppedObjectTarget, difficulty)
|
||||
|
83
osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs
Normal file
83
osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs
Normal file
@ -0,0 +1,83 @@
|
||||
// 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 System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Skinning.Default;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
{
|
||||
[Cached(typeof(CaughtObject))]
|
||||
public abstract class CaughtObject : SkinnableDrawable
|
||||
{
|
||||
public readonly Bindable<Color4> AccentColour = new Bindable<Color4>();
|
||||
|
||||
public CatchHitObject HitObject { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this hit object should stay on the catcher plate when the object is caught by the catcher.
|
||||
/// </summary>
|
||||
public virtual bool StaysOnPlate => true;
|
||||
|
||||
public override bool RemoveWhenNotAlive => true;
|
||||
|
||||
protected CaughtObject(CatchSkinComponents skinComponent, Func<ISkinComponent, Drawable> defaultImplementation)
|
||||
: base(new CatchSkinComponent(skinComponent), defaultImplementation)
|
||||
{
|
||||
Anchor = Anchor.TopCentre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
RelativeSizeAxes = Axes.None;
|
||||
Size = new Vector2(CatchHitObject.OBJECT_RADIUS * 2);
|
||||
}
|
||||
|
||||
public virtual void CopyFrom(DrawablePalpableCatchHitObject drawableObject)
|
||||
{
|
||||
HitObject = drawableObject.HitObject;
|
||||
Scale = drawableObject.Scale / 2;
|
||||
Rotation = drawableObject.Rotation;
|
||||
AccentColour.Value = drawableObject.AccentColour.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public class CaughtFruit : CaughtObject
|
||||
{
|
||||
public readonly Bindable<FruitVisualRepresentation> VisualRepresentation = new Bindable<FruitVisualRepresentation>();
|
||||
|
||||
public CaughtFruit()
|
||||
: base(CatchSkinComponents.Fruit, _ => new FruitPiece())
|
||||
{
|
||||
}
|
||||
|
||||
public override void CopyFrom(DrawablePalpableCatchHitObject drawableObject)
|
||||
{
|
||||
base.CopyFrom(drawableObject);
|
||||
|
||||
var drawableFruit = (DrawableFruit)drawableObject;
|
||||
VisualRepresentation.Value = drawableFruit.VisualRepresentation.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public class CaughtBanana : CaughtObject
|
||||
{
|
||||
public CaughtBanana()
|
||||
: base(CatchSkinComponents.Banana, _ => new BananaPiece())
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class CaughtDroplet : CaughtObject
|
||||
{
|
||||
public override bool StaysOnPlate => false;
|
||||
|
||||
public CaughtDroplet()
|
||||
: base(CatchSkinComponents.Droplet, _ => new DropletPiece())
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -50,10 +50,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
|
||||
public Func<CatchHitObject, bool> CheckPosition;
|
||||
|
||||
public bool IsOnPlate;
|
||||
|
||||
public override bool RemoveWhenNotAlive => IsOnPlate;
|
||||
|
||||
protected override JudgementResult CreateResult(Judgement judgement) => new CatchJudgementResult(HitObject, judgement);
|
||||
|
||||
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
||||
|
@ -11,8 +11,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
{
|
||||
public class DrawableDroplet : DrawablePalpableCatchHitObject
|
||||
{
|
||||
public override bool StaysOnPlate => false;
|
||||
|
||||
public DrawableDroplet()
|
||||
: this(null)
|
||||
{
|
||||
|
@ -24,11 +24,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
/// </summary>
|
||||
protected virtual float ScaleFactor => 1;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this hit object should stay on the catcher plate when the object is caught by the catcher.
|
||||
/// </summary>
|
||||
public virtual bool StaysOnPlate => true;
|
||||
|
||||
public float DisplayRadius => CatchHitObject.OBJECT_RADIUS * HitObject.Scale * ScaleFactor;
|
||||
|
||||
protected DrawablePalpableCatchHitObject([CanBeNull] CatchHitObject h)
|
||||
@ -43,7 +38,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
{
|
||||
XBindable.BindValueChanged(x =>
|
||||
{
|
||||
if (!IsOnPlate) X = x.NewValue;
|
||||
X = x.NewValue;
|
||||
}, true);
|
||||
|
||||
ScaleBindable.BindValueChanged(scale =>
|
||||
|
@ -21,6 +21,10 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default
|
||||
[CanBeNull]
|
||||
protected DrawableHitObject DrawableHitObject { get; private set; }
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
[CanBeNull]
|
||||
protected CaughtObject CaughtObject { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A part of this piece that will be faded out while falling in the playfield.
|
||||
/// </summary>
|
||||
@ -45,6 +49,9 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default
|
||||
HyperDash.BindTo(hitObject.HyperDash);
|
||||
}
|
||||
|
||||
if (CaughtObject != null)
|
||||
AccentColour.BindTo(CaughtObject.AccentColour);
|
||||
|
||||
HyperDash.BindValueChanged(hyper =>
|
||||
{
|
||||
if (HyperBorderPiece != null)
|
||||
@ -54,8 +61,13 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
if (BorderPiece != null && DrawableHitObject?.HitObject != null)
|
||||
BorderPiece.Alpha = (float)Math.Clamp((DrawableHitObject.HitObject.StartTime - Time.Current) / 500, 0, 1);
|
||||
if (BorderPiece != null)
|
||||
{
|
||||
if (DrawableHitObject?.HitObject != null)
|
||||
BorderPiece.Alpha = (float)Math.Clamp((DrawableHitObject.HitObject.StartTime - Time.Current) / 500, 0, 1);
|
||||
else
|
||||
BorderPiece.Alpha = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,10 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default
|
||||
|
||||
if (fruit != null)
|
||||
VisualRepresentation.BindTo(fruit.VisualRepresentation);
|
||||
|
||||
var caughtFruit = (CaughtFruit)CaughtObject;
|
||||
if (caughtFruit != null)
|
||||
VisualRepresentation.BindTo(caughtFruit.VisualRepresentation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,10 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||
if (fruit != null)
|
||||
VisualRepresentation.BindTo(fruit.VisualRepresentation);
|
||||
|
||||
var caughtFruit = (CaughtFruit)CaughtObject;
|
||||
if (caughtFruit != null)
|
||||
VisualRepresentation.BindTo(caughtFruit.VisualRepresentation);
|
||||
|
||||
VisualRepresentation.BindValueChanged(visual => setTexture(visual.NewValue), true);
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,10 @@ namespace osu.Game.Rulesets.Catch.Skinning
|
||||
[CanBeNull]
|
||||
protected DrawableHitObject DrawableHitObject { get; private set; }
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
[CanBeNull]
|
||||
protected CaughtObject CaughtObject { get; private set; }
|
||||
|
||||
protected LegacyCatchHitObjectPiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
@ -73,6 +77,9 @@ namespace osu.Game.Rulesets.Catch.Skinning
|
||||
HyperDash.BindTo(hitObject.HyperDash);
|
||||
}
|
||||
|
||||
if (CaughtObject != null)
|
||||
AccentColour.BindTo(CaughtObject.AccentColour);
|
||||
|
||||
hyperSprite.Colour = Skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDashFruit)?.Value ??
|
||||
Skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDash)?.Value ??
|
||||
Catcher.DEFAULT_HYPER_DASH_COLOUR;
|
||||
|
@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
private readonly Container droppedObjectTarget;
|
||||
|
||||
private readonly Container<DrawablePalpableCatchHitObject> caughtFruitContainer;
|
||||
private readonly Container<CaughtObject> caughtFruitContainer;
|
||||
|
||||
public CatcherAnimationState CurrentState { get; private set; }
|
||||
|
||||
@ -124,7 +124,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
hitExplosionPool = new DrawablePool<HitExplosion>(10),
|
||||
caughtFruitContainer = new Container<DrawablePalpableCatchHitObject>
|
||||
caughtFruitContainer = new Container<CaughtObject>
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
@ -223,7 +223,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
var positionInStack = computePositionInStack(new Vector2(palpableObject.X - X, 0), palpableObject.DisplayRadius);
|
||||
|
||||
placeCaughtObject(hitObject, positionInStack);
|
||||
placeCaughtObject(palpableObject, positionInStack);
|
||||
|
||||
if (hitLighting.Value)
|
||||
addLighting(hitObject, positionInStack.X, drawableObject.AccentColour.Value);
|
||||
@ -450,21 +450,14 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
updateCatcher();
|
||||
}
|
||||
|
||||
private void placeCaughtObject(PalpableCatchHitObject source, Vector2 position)
|
||||
private void placeCaughtObject(DrawablePalpableCatchHitObject drawableObject, Vector2 position)
|
||||
{
|
||||
var caughtObject = createCaughtObject(source);
|
||||
var caughtObject = createCaughtObject(drawableObject.HitObject);
|
||||
|
||||
if (caughtObject == null) return;
|
||||
|
||||
caughtObject.RelativePositionAxes = Axes.None;
|
||||
caughtObject.CopyFrom(drawableObject);
|
||||
caughtObject.Position = position;
|
||||
caughtObject.IsOnPlate = true;
|
||||
|
||||
caughtObject.Anchor = Anchor.TopCentre;
|
||||
caughtObject.Origin = Anchor.Centre;
|
||||
caughtObject.Scale *= 0.5f;
|
||||
caughtObject.LifetimeStart = source.StartTime;
|
||||
caughtObject.LifetimeEnd = double.MaxValue;
|
||||
|
||||
caughtFruitContainer.Add(caughtObject);
|
||||
|
||||
@ -500,21 +493,18 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
hitExplosionContainer.Add(hitExplosion);
|
||||
}
|
||||
|
||||
private DrawablePalpableCatchHitObject createCaughtObject(PalpableCatchHitObject source)
|
||||
private CaughtObject createCaughtObject(PalpableCatchHitObject source)
|
||||
{
|
||||
switch (source)
|
||||
{
|
||||
case Banana banana:
|
||||
return new DrawableBanana(banana);
|
||||
case Fruit _:
|
||||
return new CaughtFruit();
|
||||
|
||||
case Fruit fruit:
|
||||
return new DrawableFruit(fruit);
|
||||
case Banana _:
|
||||
return new CaughtBanana();
|
||||
|
||||
case TinyDroplet tiny:
|
||||
return new DrawableTinyDroplet(tiny);
|
||||
|
||||
case Droplet droplet:
|
||||
return new DrawableDroplet(droplet);
|
||||
case Droplet _:
|
||||
return new CaughtDroplet();
|
||||
|
||||
default:
|
||||
return null;
|
||||
@ -532,7 +522,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
drop(caughtObject, animation);
|
||||
}
|
||||
|
||||
private void removeFromPlate(DrawablePalpableCatchHitObject caughtObject, DroppedObjectAnimation animation)
|
||||
private void removeFromPlate(CaughtObject caughtObject, DroppedObjectAnimation animation)
|
||||
{
|
||||
if (!caughtFruitContainer.Remove(caughtObject))
|
||||
throw new InvalidOperationException("Can only drop a caught object on the plate");
|
||||
@ -542,40 +532,28 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
drop(caughtObject, animation);
|
||||
}
|
||||
|
||||
private void drop(DrawablePalpableCatchHitObject d, DroppedObjectAnimation animation)
|
||||
private void drop(CaughtObject d, DroppedObjectAnimation animation)
|
||||
{
|
||||
var originalX = d.X * Scale.X;
|
||||
var startTime = Clock.CurrentTime;
|
||||
|
||||
d.Anchor = Anchor.TopLeft;
|
||||
d.Position = caughtFruitContainer.ToSpaceOfOtherDrawable(d.DrawPosition, droppedObjectTarget);
|
||||
|
||||
// we cannot just apply the transforms because DHO clears transforms when state is updated
|
||||
d.ApplyCustomUpdateState += (o, state) => animate(o, animation, originalX, startTime);
|
||||
if (d.IsLoaded)
|
||||
animate(d, animation, originalX, startTime);
|
||||
}
|
||||
|
||||
private void animate(Drawable d, DroppedObjectAnimation animation, float originalX, double startTime)
|
||||
{
|
||||
using (d.BeginAbsoluteSequence(startTime))
|
||||
switch (animation)
|
||||
{
|
||||
switch (animation)
|
||||
{
|
||||
case DroppedObjectAnimation.Drop:
|
||||
d.MoveToY(d.Y + 75, 750, Easing.InSine);
|
||||
d.FadeOut(750);
|
||||
break;
|
||||
case DroppedObjectAnimation.Drop:
|
||||
d.MoveToY(d.Y + 75, 750, Easing.InSine);
|
||||
d.FadeOut(750);
|
||||
break;
|
||||
|
||||
case DroppedObjectAnimation.Explode:
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
d.Expire();
|
||||
case DroppedObjectAnimation.Explode:
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
d.Expire();
|
||||
}
|
||||
|
||||
private enum DroppedObjectAnimation
|
||||
|
Loading…
Reference in New Issue
Block a user