osu/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs

126 lines
3.8 KiB
C#
Raw Normal View History

// 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.
2018-04-13 09:19:50 +00:00
using System;
using JetBrains.Annotations;
2018-11-20 07:51:59 +00:00
using osuTK;
2018-04-13 09:19:50 +00:00
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Pooling;
using osu.Game.Rulesets.Judgements;
2018-04-13 09:19:50 +00:00
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
2018-04-13 09:19:50 +00:00
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Skinning;
2018-04-13 09:19:50 +00:00
namespace osu.Game.Rulesets.Taiko.UI
{
/// <summary>
/// A circle explodes from the hit target to indicate a hitobject has been hit.
/// </summary>
internal class HitExplosion : PoolableDrawable
2018-04-13 09:19:50 +00:00
{
public override bool RemoveWhenNotAlive => true;
public override bool RemoveCompletedTransforms => false;
2020-09-25 10:37:34 +00:00
2020-09-25 10:25:58 +00:00
private readonly HitResult result;
2018-04-13 09:19:50 +00:00
private double? secondHitTime;
[CanBeNull]
public DrawableHitObject JudgedObject;
private SkinnableDrawable skinnable;
/// <summary>
/// This constructor only exists to meet the <c>new()</c> type constraint of <see cref="DrawablePool{T}"/>.
/// </summary>
public HitExplosion()
: this(HitResult.Great)
{
}
public HitExplosion(HitResult result)
2018-04-13 09:19:50 +00:00
{
2020-09-25 10:25:58 +00:00
this.result = result;
2018-04-13 09:19:50 +00:00
Anchor = Anchor.Centre;
2018-04-13 09:19:50 +00:00
Origin = Anchor.Centre;
Size = new Vector2(TaikoHitObject.DEFAULT_SIZE);
RelativeSizeAxes = Axes.Both;
2018-04-13 09:19:50 +00:00
RelativePositionAxes = Axes.Both;
}
[BackgroundDependencyLoader]
private void load()
2018-04-13 09:19:50 +00:00
{
InternalChild = skinnable = new SkinnableDrawable(new TaikoSkinComponent(getComponentName(result)), _ => new DefaultHitExplosion(result));
skinnable.OnSkinChanged += runAnimation;
}
public void Apply([CanBeNull] 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))
2021-03-15 19:38:11 +00:00
(skinnable.Drawable as IAnimatableHitExplosion)?.Animate(JudgedObject);
if (secondHitTime != null)
{
using (BeginAbsoluteSequence(secondHitTime.Value))
{
this.ResizeTo(new Vector2(TaikoStrongableHitObject.DEFAULT_STRONG_SIZE), 50);
(skinnable.Drawable as IAnimatableHitExplosion)?.AnimateSecondHit();
}
}
LifetimeEnd = skinnable.Drawable.LatestTransformEndTime;
}
private static TaikoSkinComponents getComponentName(HitResult result)
{
2020-09-25 10:25:58 +00:00
switch (result)
{
case HitResult.Miss:
return TaikoSkinComponents.TaikoExplosionMiss;
2020-09-29 08:16:55 +00:00
case HitResult.Ok:
return TaikoSkinComponents.TaikoExplosionOk;
case HitResult.Great:
return TaikoSkinComponents.TaikoExplosionGreat;
}
throw new ArgumentOutOfRangeException(nameof(result), $"Invalid result type: {result}");
2018-04-13 09:19:50 +00:00
}
public void VisualiseSecondHit(JudgementResult judgementResult)
2018-04-13 09:19:50 +00:00
{
secondHitTime = judgementResult.TimeAbsolute;
runAnimation();
2018-04-13 09:19:50 +00:00
}
}
}