1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 00:53:22 +08:00

Merge pull request #8877 from peppy/taiko-explosion-skinning

Add taiko hit explosion skinning support
This commit is contained in:
Dan Balasescu 2020-04-28 12:44:21 +09:00 committed by GitHub
commit d997b4d20b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 234 additions and 38 deletions

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.Allocation;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables;
namespace osu.Game.Rulesets.Taiko.Tests
{
internal class DrawableTestHit : DrawableTaikoHitObject
{
private readonly HitResult type;
public DrawableTestHit(Hit hit, HitResult type = HitResult.Great)
: base(hit)
{
this.type = type;
}
[BackgroundDependencyLoader]
private void load()
{
Result.Type = type;
}
public override bool OnPressed(TaikoAction action) => false;
}
}

View File

@ -0,0 +1,58 @@
// 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.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 DrawableTestHit(new Hit { StartTime = Time.Current }, type);
}
}

View File

@ -149,6 +149,8 @@ namespace osu.Game.Rulesets.Taiko.Tests
var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) };
Add(h);
((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = hitResult });
}
@ -164,6 +166,8 @@ namespace osu.Game.Rulesets.Taiko.Tests
var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) };
Add(h);
((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = hitResult });
((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new TestStrongNestedHit(h), new JudgementResult(new HitObject(), new TaikoStrongJudgement()) { Type = HitResult.Great });
}
@ -249,13 +253,5 @@ namespace osu.Game.Rulesets.Taiko.Tests
public override bool OnPressed(TaikoAction action) => false;
}
private class DrawableTestHit : DrawableHitObject<TaikoHitObject>
{
public DrawableTestHit(TaikoHitObject hitObject)
: base(hitObject)
{
}
}
}
}

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

@ -1,6 +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 System;
using System.Collections.Generic;
using osu.Framework.Audio.Sample;
using osu.Framework.Bindables;
@ -81,11 +82,38 @@ namespace osu.Game.Rulesets.Taiko.Skinning
return new LegacyBarLine();
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);
}
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";
}
throw new ArgumentOutOfRangeException(nameof(component), "Invalid result type");
}
public Texture GetTexture(string componentName) => source.GetTexture(componentName);
public SampleChannel GetSample(ISampleInfo sampleInfo) => source.GetSample(new LegacyTaikoSampleInfo(sampleInfo));

View File

@ -14,6 +14,9 @@ namespace osu.Game.Rulesets.Taiko
HitTarget,
PlayfieldBackgroundLeft,
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.
// See the LICENCE file in the repository root for full licence text.
using System;
using osuTK;
using osuTK.Graphics;
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 osu.Game.Skinning;
namespace osu.Game.Rulesets.Taiko.UI
{
@ -20,15 +20,12 @@ namespace osu.Game.Rulesets.Taiko.UI
{
public override bool RemoveWhenNotAlive => true;
[Cached(typeof(DrawableHitObject))]
public readonly DrawableHitObject JudgedObject;
private readonly HitType type;
private readonly Box innerFill;
public HitExplosion(DrawableHitObject judgedObject, HitType type)
public HitExplosion(DrawableHitObject judgedObject)
{
JudgedObject = judgedObject;
this.type = type;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
@ -37,35 +34,36 @@ namespace osu.Game.Rulesets.Taiko.UI
Size = new Vector2(TaikoHitObject.DEFAULT_SIZE);
RelativePositionAxes = Axes.Both;
BorderColour = Color4.White;
BorderThickness = 1;
Alpha = 0.15f;
Masking = true;
Children = new[]
{
innerFill = new Box
{
RelativeSizeAxes = Axes.Both,
}
};
}
[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 ArgumentOutOfRangeException(nameof(resultType), "Invalid result type");
}
protected override void LoadComplete()
{
base.LoadComplete();
this.ScaleTo(3f, 1000, Easing.OutQuint);
this.FadeOut(500);
Expire(true);
}

View File

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