mirror of
https://github.com/ppy/osu.git
synced 2025-02-21 23:05:34 +08:00
KiaiHitExplosion pool
This commit is contained in:
parent
7deccd1136
commit
d57ed5841a
@ -7,12 +7,14 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Rulesets.Taiko.UI;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Skinning.Default
|
||||
{
|
||||
public partial class DefaultKiaiHitExplosion : CircularContainer
|
||||
public partial class DefaultKiaiHitExplosion : CircularContainer, IAnimatableHitExplosion
|
||||
{
|
||||
public override bool RemoveWhenNotAlive => true;
|
||||
|
||||
@ -51,14 +53,16 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
public void Animate(DrawableHitObject _drawableHitObject)
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
this.ScaleTo(new Vector2(1, 3f), 500, Easing.OutQuint);
|
||||
this.FadeOut(250);
|
||||
}
|
||||
|
||||
Expire(true);
|
||||
public void AnimateSecondHit()
|
||||
{
|
||||
this.ScaleTo(new Vector2(TaikoStrongableHitObject.STRONG_SCALE, 3f), 500, Easing.OutQuint);
|
||||
this.FadeOut(250);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,35 +2,23 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osuTK;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Rulesets.Taiko.Skinning.Default;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// A circle explodes from the hit target to indicate a hitobject has been hit.
|
||||
/// </summary>
|
||||
internal partial class HitExplosion : PoolableDrawable
|
||||
internal partial class HitExplosion : HitExplosionBase
|
||||
{
|
||||
public override bool RemoveWhenNotAlive => true;
|
||||
public override bool RemoveCompletedTransforms => false;
|
||||
|
||||
private readonly HitResult result;
|
||||
|
||||
private double? secondHitTime;
|
||||
|
||||
public DrawableHitObject? JudgedObject;
|
||||
|
||||
private SkinnableDrawable skinnable = null!;
|
||||
|
||||
/// <summary>
|
||||
/// This constructor only exists to meet the <c>new()</c> type constraint of <see cref="DrawablePool{T}"/>.
|
||||
/// </summary>
|
||||
@ -42,60 +30,12 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
public HitExplosion(HitResult result)
|
||||
{
|
||||
this.result = result;
|
||||
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Size = new Vector2(TaikoHitObject.DEFAULT_SIZE);
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
RelativePositionAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChild = skinnable = new SkinnableDrawable(new TaikoSkinComponentLookup(getComponentName(result)), _ => new DefaultHitExplosion(result));
|
||||
skinnable.OnSkinChanged += runAnimation;
|
||||
}
|
||||
|
||||
public void Apply(DrawableHitObject? drawableHitObject)
|
||||
{
|
||||
JudgedObject = drawableHitObject;
|
||||
secondHitTime = null;
|
||||
}
|
||||
|
||||
protected override void PrepareForUse()
|
||||
{
|
||||
base.PrepareForUse();
|
||||
runAnimation();
|
||||
}
|
||||
|
||||
private void runAnimation()
|
||||
{
|
||||
if (JudgedObject?.Result == null)
|
||||
return;
|
||||
|
||||
double resultTime = JudgedObject.Result.TimeAbsolute;
|
||||
|
||||
LifetimeStart = resultTime;
|
||||
|
||||
ApplyTransformsAt(double.MinValue, true);
|
||||
ClearTransforms(true);
|
||||
|
||||
using (BeginAbsoluteSequence(resultTime))
|
||||
(skinnable.Drawable as IAnimatableHitExplosion)?.Animate(JudgedObject);
|
||||
|
||||
if (secondHitTime != null)
|
||||
{
|
||||
using (BeginAbsoluteSequence(secondHitTime.Value))
|
||||
{
|
||||
(skinnable.Drawable as IAnimatableHitExplosion)?.AnimateSecondHit();
|
||||
}
|
||||
}
|
||||
|
||||
LifetimeEnd = skinnable.Drawable.LatestTransformEndTime;
|
||||
}
|
||||
protected override SkinnableDrawable OnLoadSkinnableCreate() =>
|
||||
new SkinnableDrawable(new TaikoSkinComponentLookup(getComponentName(result)), _ => new DefaultHitExplosion(result));
|
||||
|
||||
private static TaikoSkinComponents getComponentName(HitResult result)
|
||||
{
|
||||
@ -113,11 +53,5 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(result), $"Invalid result type: {result}");
|
||||
}
|
||||
|
||||
public void VisualiseSecondHit(JudgementResult judgementResult)
|
||||
{
|
||||
secondHitTime = judgementResult.TimeAbsolute;
|
||||
runAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
87
osu.Game.Rulesets.Taiko/UI/HitExplosionBase.cs
Normal file
87
osu.Game.Rulesets.Taiko/UI/HitExplosionBase.cs
Normal file
@ -0,0 +1,87 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for taiko explosions from target hitting to indicate a hitobject has been hit.
|
||||
/// </summary>
|
||||
internal abstract partial class HitExplosionBase : PoolableDrawable
|
||||
{
|
||||
protected abstract SkinnableDrawable OnLoadSkinnableCreate();
|
||||
|
||||
public override bool RemoveWhenNotAlive => true;
|
||||
public override bool RemoveCompletedTransforms => false;
|
||||
|
||||
|
||||
protected double? SecondHitTime;
|
||||
|
||||
public DrawableHitObject? JudgedObject;
|
||||
|
||||
protected SkinnableDrawable Skinnable = null!;
|
||||
|
||||
public HitExplosionBase()
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChild = Skinnable = OnLoadSkinnableCreate();
|
||||
Skinnable.OnSkinChanged += RunAnimation;
|
||||
}
|
||||
|
||||
public void Apply(DrawableHitObject? drawableHitObject)
|
||||
{
|
||||
JudgedObject = drawableHitObject;
|
||||
SecondHitTime = null;
|
||||
}
|
||||
|
||||
protected override void PrepareForUse()
|
||||
{
|
||||
base.PrepareForUse();
|
||||
RunAnimation();
|
||||
}
|
||||
|
||||
protected void RunAnimation()
|
||||
{
|
||||
if (JudgedObject?.Result is null) return;
|
||||
|
||||
double resultTime = JudgedObject.Result.TimeAbsolute;
|
||||
LifetimeStart = resultTime;
|
||||
|
||||
// Clear transforms
|
||||
ApplyTransformsAt(double.MinValue, true);
|
||||
ClearTransforms(true);
|
||||
|
||||
if (Skinnable.Drawable is IAnimatableHitExplosion animatable)
|
||||
{
|
||||
using (BeginAbsoluteSequence(resultTime))
|
||||
animatable.Animate(JudgedObject);
|
||||
|
||||
if (SecondHitTime != null)
|
||||
using (BeginAbsoluteSequence(SecondHitTime.Value))
|
||||
animatable.AnimateSecondHit();
|
||||
}
|
||||
|
||||
LifetimeEnd = Skinnable.Drawable.LatestTransformEndTime;
|
||||
}
|
||||
|
||||
public void VisualiseSecondHit(JudgementResult judgementResult)
|
||||
{
|
||||
SecondHitTime = judgementResult.TimeAbsolute;
|
||||
RunAnimation();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Rulesets.Taiko.Skinning.Default;
|
||||
@ -12,37 +10,30 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
public partial class KiaiHitExplosion : Container
|
||||
/// <summary>
|
||||
/// An explosion from the hit target in Kiai mode to indicate a hitobject has been hit.
|
||||
/// </summary>
|
||||
internal partial class KiaiHitExplosion : HitExplosionBase
|
||||
{
|
||||
public override bool RemoveWhenNotAlive => true;
|
||||
|
||||
[Cached(typeof(DrawableHitObject))]
|
||||
public readonly DrawableHitObject JudgedObject;
|
||||
|
||||
private readonly HitType hitType;
|
||||
|
||||
private SkinnableDrawable skinnable = null!;
|
||||
/// <summary>
|
||||
/// This constructor only exists to meet the <c>new()</c> type constraint of <see cref="DrawablePool{T}"/>.
|
||||
/// </summary>
|
||||
public KiaiHitExplosion() : this(HitType.Centre) { }
|
||||
|
||||
public override double LifetimeStart => skinnable.Drawable.LifetimeStart;
|
||||
|
||||
public override double LifetimeEnd => skinnable.Drawable.LifetimeEnd;
|
||||
|
||||
public KiaiHitExplosion(DrawableHitObject judgedObject, HitType hitType)
|
||||
public KiaiHitExplosion(HitType hitType)
|
||||
{
|
||||
JudgedObject = judgedObject;
|
||||
this.hitType = hitType;
|
||||
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Size = new Vector2(TaikoHitObject.DEFAULT_SIZE, 1);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
public KiaiHitExplosion(DrawableHitObject judgedObject, HitType hitType) : this(hitType)
|
||||
{
|
||||
Child = skinnable = new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.TaikoExplosionKiai), _ => new DefaultKiaiHitExplosion(hitType));
|
||||
Apply(judgedObject);
|
||||
}
|
||||
|
||||
protected override SkinnableDrawable OnLoadSkinnableCreate() =>
|
||||
new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.TaikoExplosionKiai), _ => new DefaultKiaiHitExplosion(hitType));
|
||||
}
|
||||
}
|
||||
|
23
osu.Game.Rulesets.Taiko/UI/KiaiHitExplosionPool.cs
Normal file
23
osu.Game.Rulesets.Taiko/UI/KiaiHitExplosionPool.cs
Normal 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.Pooling;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Pool for hit explosions of a specific type.
|
||||
/// </summary>
|
||||
internal partial class KiaiHitExplosionPool : DrawablePool<KiaiHitExplosion>
|
||||
{
|
||||
private readonly HitType hitType;
|
||||
|
||||
public KiaiHitExplosionPool(HitType hitType) : base(15)
|
||||
{
|
||||
this.hitType = hitType;
|
||||
}
|
||||
|
||||
protected override KiaiHitExplosion CreateNewDrawable() => new KiaiHitExplosion(hitType);
|
||||
}
|
||||
}
|
@ -42,6 +42,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
private JudgementPooler<DrawableTaikoJudgement> judgementPooler = null!;
|
||||
private readonly IDictionary<HitResult, HitExplosionPool> explosionPools = new Dictionary<HitResult, HitExplosionPool>();
|
||||
private readonly IDictionary<HitType, KiaiHitExplosionPool> kiaiExplosionPools = new Dictionary<HitType, KiaiHitExplosionPool>();
|
||||
|
||||
private ProxyContainer topLevelHitContainer = null!;
|
||||
private InputDrum inputDrum = null!;
|
||||
@ -202,6 +203,10 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
explosionPools.Add(result, new HitExplosionPool(result));
|
||||
AddRangeInternal(explosionPools.Values);
|
||||
|
||||
foreach (var type in Enum.GetValues<HitType>())
|
||||
kiaiExplosionPools.Add(type, new KiaiHitExplosionPool(type));
|
||||
AddRangeInternal(kiaiExplosionPools.Values);
|
||||
|
||||
AddRangeInternal(poolsHit.Values);
|
||||
}
|
||||
|
||||
@ -320,7 +325,11 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
case TaikoStrongJudgement:
|
||||
if (result.IsHit)
|
||||
{
|
||||
hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongNestedHit)judgedObject).ParentHitObject)?.VisualiseSecondHit(result);
|
||||
if (result.HitObject.Kiai)
|
||||
kiaiExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongNestedHit)judgedObject).ParentHitObject)?.VisualiseSecondHit(result);
|
||||
}
|
||||
break;
|
||||
|
||||
case TaikoDrumRollTickJudgement:
|
||||
@ -356,8 +365,12 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
hitExplosionContainer.Add(explosionPools[result]
|
||||
.Get(explosion => explosion.Apply(drawableObject)));
|
||||
if (drawableObject.HitObject.Kiai)
|
||||
kiaiExplosionContainer.Add(new KiaiHitExplosion(drawableObject, type));
|
||||
|
||||
//TODO: should we check `result.IsHit` ?
|
||||
if (drawableObject.HitObject.Kiai && result.IsHit())
|
||||
kiaiExplosionContainer.Add(
|
||||
kiaiExplosionPools[type].Get(
|
||||
explosion => explosion.Apply(drawableObject)));
|
||||
}
|
||||
|
||||
private partial class ProxyContainer : LifetimeManagementContainer
|
||||
|
Loading…
Reference in New Issue
Block a user