1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 17:27:24 +08:00

Add taiko hit explosion skinning support

This commit is contained in:
Dean Herbert 2020-04-27 22:22:32 +09:00
parent 52779b2484
commit be59ee945a
7 changed files with 221 additions and 30 deletions

View File

@ -0,0 +1,79 @@
// 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 System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables;
using osu.Game.Rulesets.Taiko.Skinning;
using osu.Game.Rulesets.Taiko.UI;
namespace osu.Game.Rulesets.Taiko.Tests.Skinning
{
[TestFixture]
public class TestSceneHitExplosion : TaikoSkinnableTestScene
{
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
{
typeof(HitExplosion),
typeof(LegacyHitExplosion),
typeof(DefaultHitExplosion),
}).ToList();
[BackgroundDependencyLoader]
private void load()
{
AddStep("Great", () => SetContents(() => getContentFor(HitResult.Great)));
AddStep("Good", () => SetContents(() => getContentFor(HitResult.Good)));
AddStep("Miss", () => SetContents(() => getContentFor(HitResult.Miss)));
}
private Drawable getContentFor(HitResult type)
{
DrawableTaikoHitObject hit;
return new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
hit = createHit(type),
new HitExplosion(hit)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
}
};
}
private DrawableTaikoHitObject createHit(HitResult type) => new TestDrawableHit(new Hit { StartTime = Time.Current }, type);
private class TestDrawableHit : DrawableTaikoHitObject
{
private readonly HitResult type;
public TestDrawableHit(Hit hit, HitResult type)
: base(hit)
{
this.type = type;
}
[BackgroundDependencyLoader]
private void load()
{
Result.Type = type;
}
public override bool OnPressed(TaikoAction action) => false;
}
}
}

View File

@ -0,0 +1,29 @@
// 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;
using osu.Framework.Graphics.Containers;
namespace osu.Game.Rulesets.Taiko.Skinning
{
public class LegacyHitExplosion : CompositeDrawable
{
public LegacyHitExplosion(Drawable sprite)
{
InternalChild = sprite;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
AutoSizeAxes = Axes.Both;
}
protected override void LoadComplete()
{
base.LoadComplete();
this.FadeIn(120);
this.ScaleTo(0.6f).Then().ScaleTo(1, 240, Easing.OutElastic);
}
}
}

View File

@ -81,11 +81,38 @@ namespace osu.Game.Rulesets.Taiko.Skinning
return new LegacyBarLine(); return new LegacyBarLine();
return null; return null;
case TaikoSkinComponents.TaikoExplosionGood:
case TaikoSkinComponents.TaikoExplosionGreat:
case TaikoSkinComponents.TaikoExplosionMiss:
var sprite = this.GetAnimation(getHitname(taikoComponent.Component), true, false);
if (sprite != null)
return new LegacyHitExplosion(sprite);
return null;
} }
return source.GetDrawableComponent(component); return source.GetDrawableComponent(component);
} }
private string getHitname(TaikoSkinComponents component)
{
switch (component)
{
case TaikoSkinComponents.TaikoExplosionMiss:
return "taiko-hit0";
case TaikoSkinComponents.TaikoExplosionGood:
return "taiko-hit100";
case TaikoSkinComponents.TaikoExplosionGreat:
return "taiko-hit300";
}
return string.Empty;
}
public Texture GetTexture(string componentName) => source.GetTexture(componentName); public Texture GetTexture(string componentName) => source.GetTexture(componentName);
public SampleChannel GetSample(ISampleInfo sampleInfo) => source.GetSample(new LegacyTaikoSampleInfo(sampleInfo)); public SampleChannel GetSample(ISampleInfo sampleInfo) => source.GetSample(new LegacyTaikoSampleInfo(sampleInfo));

View File

@ -14,6 +14,9 @@ namespace osu.Game.Rulesets.Taiko
HitTarget, HitTarget,
PlayfieldBackgroundLeft, PlayfieldBackgroundLeft,
PlayfieldBackgroundRight, PlayfieldBackgroundRight,
BarLine BarLine,
TaikoExplosionMiss,
TaikoExplosionGood,
TaikoExplosionGreat,
} }
} }

View File

@ -0,0 +1,54 @@
// 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.Shapes;
using osu.Game.Graphics;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects;
using osuTK.Graphics;
namespace osu.Game.Rulesets.Taiko.UI
{
internal class DefaultHitExplosion : CircularContainer
{
[Resolved]
private DrawableHitObject judgedObject { get; set; }
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
RelativeSizeAxes = Axes.Both;
BorderColour = Color4.White;
BorderThickness = 1;
Alpha = 0.15f;
Masking = true;
if (judgedObject.Result.Type == HitResult.Miss)
return;
bool isRim = (judgedObject.HitObject as Hit)?.Type == HitType.Rim;
InternalChildren = new[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = isRim ? colours.BlueDarker : colours.PinkDarker,
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
this.ScaleTo(3f, 1000, Easing.OutQuint);
}
}
}

View File

@ -1,15 +1,15 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System;
using osuTK; using osuTK;
using osuTK.Graphics;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.UI
{ {
@ -20,15 +20,12 @@ namespace osu.Game.Rulesets.Taiko.UI
{ {
public override bool RemoveWhenNotAlive => true; public override bool RemoveWhenNotAlive => true;
[Cached(typeof(DrawableHitObject))]
public readonly DrawableHitObject JudgedObject; public readonly DrawableHitObject JudgedObject;
private readonly HitType type;
private readonly Box innerFill; public HitExplosion(DrawableHitObject judgedObject)
public HitExplosion(DrawableHitObject judgedObject, HitType type)
{ {
JudgedObject = judgedObject; JudgedObject = judgedObject;
this.type = type;
Anchor = Anchor.Centre; Anchor = Anchor.Centre;
Origin = Anchor.Centre; Origin = Anchor.Centre;
@ -37,35 +34,36 @@ namespace osu.Game.Rulesets.Taiko.UI
Size = new Vector2(TaikoHitObject.DEFAULT_SIZE); Size = new Vector2(TaikoHitObject.DEFAULT_SIZE);
RelativePositionAxes = Axes.Both; RelativePositionAxes = Axes.Both;
BorderColour = Color4.White;
BorderThickness = 1;
Alpha = 0.15f;
Masking = true;
Children = new[]
{
innerFill = new Box
{
RelativeSizeAxes = Axes.Both,
}
};
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load()
{ {
innerFill.Colour = type == HitType.Rim ? colours.BlueDarker : colours.PinkDarker; Child = new SkinnableDrawable(new TaikoSkinComponent(getComponentName(JudgedObject.Result?.Type ?? HitResult.Great)), _ => new DefaultHitExplosion());
}
private TaikoSkinComponents getComponentName(HitResult resultType)
{
switch (resultType)
{
case HitResult.Miss:
return TaikoSkinComponents.TaikoExplosionMiss;
case HitResult.Good:
return TaikoSkinComponents.TaikoExplosionGood;
case HitResult.Great:
return TaikoSkinComponents.TaikoExplosionGreat;
}
throw new ArgumentException("Invalid result type", nameof(resultType));
} }
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
this.ScaleTo(3f, 1000, Easing.OutQuint);
this.FadeOut(500); this.FadeOut(500);
Expire(true); Expire(true);
} }

View File

@ -185,7 +185,6 @@ namespace osu.Game.Rulesets.Taiko.UI
var drawableTick = (DrawableDrumRollTick)judgedObject; var drawableTick = (DrawableDrumRollTick)judgedObject;
addDrumRollHit(drawableTick); addDrumRollHit(drawableTick);
addExplosion(drawableTick, drawableTick.JudgementType);
break; break;
default: default:
@ -200,7 +199,9 @@ namespace osu.Game.Rulesets.Taiko.UI
if (!result.IsHit) if (!result.IsHit)
break; break;
addExplosion(judgedObject, (judgedObject.HitObject as Hit)?.Type ?? HitType.Centre); var type = (judgedObject.HitObject as Hit)?.Type ?? HitType.Centre;
addExplosion(judgedObject, type);
break; break;
} }
} }
@ -210,7 +211,7 @@ namespace osu.Game.Rulesets.Taiko.UI
private void addExplosion(DrawableHitObject drawableObject, HitType type) private void addExplosion(DrawableHitObject drawableObject, HitType type)
{ {
hitExplosionContainer.Add(new HitExplosion(drawableObject, type)); hitExplosionContainer.Add(new HitExplosion(drawableObject));
if (drawableObject.HitObject.Kiai) if (drawableObject.HitObject.Kiai)
kiaiExplosionContainer.Add(new KiaiHitExplosion(drawableObject, type)); kiaiExplosionContainer.Add(new KiaiHitExplosion(drawableObject, type));
} }