mirror of
https://github.com/osukey/osukey.git
synced 2025-07-01 16:29:58 +09:00
Make object on the catcher plate separate CaughtObject class
This commit is contained in:
@ -275,7 +275,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
public class TestCatcher : Catcher
|
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)
|
public TestCatcher(Container trailsTarget, Container droppedObjectTarget, BeatmapDifficulty difficulty)
|
||||||
: base(trailsTarget, droppedObjectTarget, 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 Func<CatchHitObject, bool> CheckPosition;
|
||||||
|
|
||||||
public bool IsOnPlate;
|
|
||||||
|
|
||||||
public override bool RemoveWhenNotAlive => IsOnPlate;
|
|
||||||
|
|
||||||
protected override JudgementResult CreateResult(Judgement judgement) => new CatchJudgementResult(HitObject, judgement);
|
protected override JudgementResult CreateResult(Judgement judgement) => new CatchJudgementResult(HitObject, judgement);
|
||||||
|
|
||||||
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
||||||
|
@ -11,8 +11,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
|||||||
{
|
{
|
||||||
public class DrawableDroplet : DrawablePalpableCatchHitObject
|
public class DrawableDroplet : DrawablePalpableCatchHitObject
|
||||||
{
|
{
|
||||||
public override bool StaysOnPlate => false;
|
|
||||||
|
|
||||||
public DrawableDroplet()
|
public DrawableDroplet()
|
||||||
: this(null)
|
: this(null)
|
||||||
{
|
{
|
||||||
|
@ -24,11 +24,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual float ScaleFactor => 1;
|
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;
|
public float DisplayRadius => CatchHitObject.OBJECT_RADIUS * HitObject.Scale * ScaleFactor;
|
||||||
|
|
||||||
protected DrawablePalpableCatchHitObject([CanBeNull] CatchHitObject h)
|
protected DrawablePalpableCatchHitObject([CanBeNull] CatchHitObject h)
|
||||||
@ -43,7 +38,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
|||||||
{
|
{
|
||||||
XBindable.BindValueChanged(x =>
|
XBindable.BindValueChanged(x =>
|
||||||
{
|
{
|
||||||
if (!IsOnPlate) X = x.NewValue;
|
X = x.NewValue;
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
ScaleBindable.BindValueChanged(scale =>
|
ScaleBindable.BindValueChanged(scale =>
|
||||||
|
@ -21,6 +21,10 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default
|
|||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
protected DrawableHitObject DrawableHitObject { get; private set; }
|
protected DrawableHitObject DrawableHitObject { get; private set; }
|
||||||
|
|
||||||
|
[Resolved(canBeNull: true)]
|
||||||
|
[CanBeNull]
|
||||||
|
protected CaughtObject CaughtObject { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A part of this piece that will be faded out while falling in the playfield.
|
/// A part of this piece that will be faded out while falling in the playfield.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -45,6 +49,9 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default
|
|||||||
HyperDash.BindTo(hitObject.HyperDash);
|
HyperDash.BindTo(hitObject.HyperDash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CaughtObject != null)
|
||||||
|
AccentColour.BindTo(CaughtObject.AccentColour);
|
||||||
|
|
||||||
HyperDash.BindValueChanged(hyper =>
|
HyperDash.BindValueChanged(hyper =>
|
||||||
{
|
{
|
||||||
if (HyperBorderPiece != null)
|
if (HyperBorderPiece != null)
|
||||||
@ -54,8 +61,13 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default
|
|||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
if (BorderPiece != null && DrawableHitObject?.HitObject != null)
|
if (BorderPiece != null)
|
||||||
BorderPiece.Alpha = (float)Math.Clamp((DrawableHitObject.HitObject.StartTime - Time.Current) / 500, 0, 1);
|
{
|
||||||
|
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)
|
if (fruit != null)
|
||||||
VisualRepresentation.BindTo(fruit.VisualRepresentation);
|
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)
|
if (fruit != null)
|
||||||
VisualRepresentation.BindTo(fruit.VisualRepresentation);
|
VisualRepresentation.BindTo(fruit.VisualRepresentation);
|
||||||
|
|
||||||
|
var caughtFruit = (CaughtFruit)CaughtObject;
|
||||||
|
if (caughtFruit != null)
|
||||||
|
VisualRepresentation.BindTo(caughtFruit.VisualRepresentation);
|
||||||
|
|
||||||
VisualRepresentation.BindValueChanged(visual => setTexture(visual.NewValue), true);
|
VisualRepresentation.BindValueChanged(visual => setTexture(visual.NewValue), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,10 @@ namespace osu.Game.Rulesets.Catch.Skinning
|
|||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
protected DrawableHitObject DrawableHitObject { get; private set; }
|
protected DrawableHitObject DrawableHitObject { get; private set; }
|
||||||
|
|
||||||
|
[Resolved(canBeNull: true)]
|
||||||
|
[CanBeNull]
|
||||||
|
protected CaughtObject CaughtObject { get; private set; }
|
||||||
|
|
||||||
protected LegacyCatchHitObjectPiece()
|
protected LegacyCatchHitObjectPiece()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
@ -73,6 +77,9 @@ namespace osu.Game.Rulesets.Catch.Skinning
|
|||||||
HyperDash.BindTo(hitObject.HyperDash);
|
HyperDash.BindTo(hitObject.HyperDash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CaughtObject != null)
|
||||||
|
AccentColour.BindTo(CaughtObject.AccentColour);
|
||||||
|
|
||||||
hyperSprite.Colour = Skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDashFruit)?.Value ??
|
hyperSprite.Colour = Skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDashFruit)?.Value ??
|
||||||
Skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDash)?.Value ??
|
Skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDash)?.Value ??
|
||||||
Catcher.DEFAULT_HYPER_DASH_COLOUR;
|
Catcher.DEFAULT_HYPER_DASH_COLOUR;
|
||||||
|
@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
private readonly Container droppedObjectTarget;
|
private readonly Container droppedObjectTarget;
|
||||||
|
|
||||||
private readonly Container<DrawablePalpableCatchHitObject> caughtFruitContainer;
|
private readonly Container<CaughtObject> caughtFruitContainer;
|
||||||
|
|
||||||
public CatcherAnimationState CurrentState { get; private set; }
|
public CatcherAnimationState CurrentState { get; private set; }
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
hitExplosionPool = new DrawablePool<HitExplosion>(10),
|
hitExplosionPool = new DrawablePool<HitExplosion>(10),
|
||||||
caughtFruitContainer = new Container<DrawablePalpableCatchHitObject>
|
caughtFruitContainer = new Container<CaughtObject>
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.BottomCentre,
|
Origin = Anchor.BottomCentre,
|
||||||
@ -223,7 +223,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
var positionInStack = computePositionInStack(new Vector2(palpableObject.X - X, 0), palpableObject.DisplayRadius);
|
var positionInStack = computePositionInStack(new Vector2(palpableObject.X - X, 0), palpableObject.DisplayRadius);
|
||||||
|
|
||||||
placeCaughtObject(hitObject, positionInStack);
|
placeCaughtObject(palpableObject, positionInStack);
|
||||||
|
|
||||||
if (hitLighting.Value)
|
if (hitLighting.Value)
|
||||||
addLighting(hitObject, positionInStack.X, drawableObject.AccentColour.Value);
|
addLighting(hitObject, positionInStack.X, drawableObject.AccentColour.Value);
|
||||||
@ -450,21 +450,14 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
updateCatcher();
|
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;
|
if (caughtObject == null) return;
|
||||||
|
|
||||||
caughtObject.RelativePositionAxes = Axes.None;
|
caughtObject.CopyFrom(drawableObject);
|
||||||
caughtObject.Position = position;
|
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);
|
caughtFruitContainer.Add(caughtObject);
|
||||||
|
|
||||||
@ -500,21 +493,18 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
hitExplosionContainer.Add(hitExplosion);
|
hitExplosionContainer.Add(hitExplosion);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DrawablePalpableCatchHitObject createCaughtObject(PalpableCatchHitObject source)
|
private CaughtObject createCaughtObject(PalpableCatchHitObject source)
|
||||||
{
|
{
|
||||||
switch (source)
|
switch (source)
|
||||||
{
|
{
|
||||||
case Banana banana:
|
case Fruit _:
|
||||||
return new DrawableBanana(banana);
|
return new CaughtFruit();
|
||||||
|
|
||||||
case Fruit fruit:
|
case Banana _:
|
||||||
return new DrawableFruit(fruit);
|
return new CaughtBanana();
|
||||||
|
|
||||||
case TinyDroplet tiny:
|
case Droplet _:
|
||||||
return new DrawableTinyDroplet(tiny);
|
return new CaughtDroplet();
|
||||||
|
|
||||||
case Droplet droplet:
|
|
||||||
return new DrawableDroplet(droplet);
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
@ -532,7 +522,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
drop(caughtObject, animation);
|
drop(caughtObject, animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeFromPlate(DrawablePalpableCatchHitObject caughtObject, DroppedObjectAnimation animation)
|
private void removeFromPlate(CaughtObject caughtObject, DroppedObjectAnimation animation)
|
||||||
{
|
{
|
||||||
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");
|
||||||
@ -542,40 +532,28 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
drop(caughtObject, animation);
|
drop(caughtObject, animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drop(DrawablePalpableCatchHitObject d, DroppedObjectAnimation animation)
|
private void drop(CaughtObject d, DroppedObjectAnimation animation)
|
||||||
{
|
{
|
||||||
var originalX = d.X * Scale.X;
|
var originalX = d.X * Scale.X;
|
||||||
var startTime = Clock.CurrentTime;
|
|
||||||
|
|
||||||
d.Anchor = Anchor.TopLeft;
|
d.Anchor = Anchor.TopLeft;
|
||||||
d.Position = caughtFruitContainer.ToSpaceOfOtherDrawable(d.DrawPosition, droppedObjectTarget);
|
d.Position = caughtFruitContainer.ToSpaceOfOtherDrawable(d.DrawPosition, droppedObjectTarget);
|
||||||
|
|
||||||
// we cannot just apply the transforms because DHO clears transforms when state is updated
|
switch (animation)
|
||||||
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)
|
case DroppedObjectAnimation.Drop:
|
||||||
{
|
d.MoveToY(d.Y + 75, 750, Easing.InSine);
|
||||||
case DroppedObjectAnimation.Drop:
|
d.FadeOut(750);
|
||||||
d.MoveToY(d.Y + 75, 750, Easing.InSine);
|
break;
|
||||||
d.FadeOut(750);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DroppedObjectAnimation.Explode:
|
case DroppedObjectAnimation.Explode:
|
||||||
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);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
d.Expire();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.Expire();
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum DroppedObjectAnimation
|
private enum DroppedObjectAnimation
|
||||||
|
Reference in New Issue
Block a user