Merge branch 'master' into catch-combo-counter

This commit is contained in:
Dean Herbert 2020-09-22 11:33:07 +09:00 committed by GitHub
commit c5717d8e41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 103 additions and 20 deletions

View File

@ -0,0 +1,44 @@
// 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.Linq;
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;
namespace osu.Game.Rulesets.Taiko.Tests
{
public class DrawableTestStrongHit : DrawableHit
{
private readonly HitResult type;
private readonly bool hitBoth;
public DrawableTestStrongHit(double startTime, HitResult type = HitResult.Great, bool hitBoth = true)
: base(new Hit
{
IsStrong = true,
StartTime = startTime,
})
{
// in order to create nested strong hit
HitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
this.type = type;
this.hitBoth = hitBoth;
}
protected override void LoadAsyncComplete()
{
base.LoadAsyncComplete();
Result.Type = type;
var nestedStrongHit = (DrawableStrongNestedHit)NestedHitObjects.Single();
nestedStrongHit.Result.Type = hitBoth ? type : HitResult.Miss;
}
public override bool OnPressed(TaikoAction action) => false;
}
}

View File

@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Scoring;
@ -15,24 +14,29 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
[TestFixture]
public class TestSceneHitExplosion : TaikoSkinnableTestScene
{
[BackgroundDependencyLoader]
private void load()
[Test]
public void TestNormalHit()
{
AddStep("Great", () => SetContents(() => getContentFor(HitResult.Great)));
AddStep("Good", () => SetContents(() => getContentFor(HitResult.Good)));
AddStep("Miss", () => SetContents(() => getContentFor(HitResult.Miss)));
AddStep("Great", () => SetContents(() => getContentFor(createHit(HitResult.Great))));
AddStep("Good", () => SetContents(() => getContentFor(createHit(HitResult.Good))));
AddStep("Miss", () => SetContents(() => getContentFor(createHit(HitResult.Miss))));
}
private Drawable getContentFor(HitResult type)
[Test]
public void TestStrongHit([Values(false, true)] bool hitBoth)
{
DrawableTaikoHitObject hit;
AddStep("Great", () => SetContents(() => getContentFor(createStrongHit(HitResult.Great, hitBoth))));
AddStep("Good", () => SetContents(() => getContentFor(createStrongHit(HitResult.Good, hitBoth))));
}
private Drawable getContentFor(DrawableTaikoHitObject hit)
{
return new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
hit = createHit(type),
hit,
new HitExplosion(hit)
{
Anchor = Anchor.Centre,
@ -43,5 +47,8 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
}
private DrawableTaikoHitObject createHit(HitResult type) => new DrawableTestHit(new Hit { StartTime = Time.Current }, type);
private DrawableTaikoHitObject createStrongHit(HitResult type, bool hitBoth)
=> new DrawableTestStrongHit(Time.Current, type, hitBoth);
}
}

View File

@ -174,7 +174,9 @@ namespace osu.Game.Rulesets.Taiko.Tests
private void addMissJudgement()
{
((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new DrawableTestHit(new Hit()), new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = HitResult.Miss });
DrawableTestHit h;
Add(h = new DrawableTestHit(new Hit(), HitResult.Miss));
((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = HitResult.Miss });
}
private void addBarLine(bool major, double delay = scroll_time)

View File

@ -75,7 +75,9 @@ namespace osu.Game.Rulesets.Taiko.Skinning
return null;
case TaikoSkinComponents.TaikoExplosionGood:
case TaikoSkinComponents.TaikoExplosionGoodStrong:
case TaikoSkinComponents.TaikoExplosionGreat:
case TaikoSkinComponents.TaikoExplosionGreatStrong:
case TaikoSkinComponents.TaikoExplosionMiss:
var sprite = this.GetAnimation(getHitName(taikoComponent.Component), true, false);
@ -107,8 +109,14 @@ namespace osu.Game.Rulesets.Taiko.Skinning
case TaikoSkinComponents.TaikoExplosionGood:
return "taiko-hit100";
case TaikoSkinComponents.TaikoExplosionGoodStrong:
return "taiko-hit100k";
case TaikoSkinComponents.TaikoExplosionGreat:
return "taiko-hit300";
case TaikoSkinComponents.TaikoExplosionGreatStrong:
return "taiko-hit300k";
}
throw new ArgumentOutOfRangeException(nameof(component), "Invalid result type");

View File

@ -17,7 +17,9 @@ namespace osu.Game.Rulesets.Taiko
BarLine,
TaikoExplosionMiss,
TaikoExplosionGood,
TaikoExplosionGoodStrong,
TaikoExplosionGreat,
TaikoExplosionGreatStrong,
Scroller,
Mascot,
}

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using osuTK;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
@ -9,6 +10,7 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables;
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Taiko.UI
@ -45,24 +47,41 @@ namespace osu.Game.Rulesets.Taiko.UI
[BackgroundDependencyLoader]
private void load()
{
Child = skinnable = new SkinnableDrawable(new TaikoSkinComponent(getComponentName(JudgedObject.Result?.Type ?? HitResult.Great)), _ => new DefaultHitExplosion());
Child = skinnable = new SkinnableDrawable(new TaikoSkinComponent(getComponentName(JudgedObject)), _ => new DefaultHitExplosion());
}
private TaikoSkinComponents getComponentName(HitResult resultType)
private TaikoSkinComponents getComponentName(DrawableHitObject judgedObject)
{
var resultType = judgedObject.Result?.Type ?? HitResult.Great;
switch (resultType)
{
case HitResult.Miss:
return TaikoSkinComponents.TaikoExplosionMiss;
case HitResult.Good:
return TaikoSkinComponents.TaikoExplosionGood;
return useStrongExplosion(judgedObject)
? TaikoSkinComponents.TaikoExplosionGoodStrong
: TaikoSkinComponents.TaikoExplosionGood;
case HitResult.Great:
return TaikoSkinComponents.TaikoExplosionGreat;
return useStrongExplosion(judgedObject)
? TaikoSkinComponents.TaikoExplosionGreatStrong
: TaikoSkinComponents.TaikoExplosionGreat;
}
throw new ArgumentOutOfRangeException(nameof(resultType), "Invalid result type");
throw new ArgumentOutOfRangeException(nameof(judgedObject), "Invalid result type");
}
private bool useStrongExplosion(DrawableHitObject judgedObject)
{
if (!(judgedObject.HitObject is Hit))
return false;
if (!(judgedObject.NestedHitObjects.SingleOrDefault() is DrawableStrongNestedHit nestedHit))
return false;
return judgedObject.Result.Type == nestedHit.Result.Type;
}
/// <summary>

View File

@ -205,9 +205,6 @@ namespace osu.Game.Rulesets.Taiko.UI
X = result.IsHit ? judgedObject.Position.X : 0,
});
if (!result.IsHit)
break;
var type = (judgedObject.HitObject as Hit)?.Type ?? HitType.Centre;
addExplosion(judgedObject, type);
@ -218,12 +215,16 @@ namespace osu.Game.Rulesets.Taiko.UI
private void addDrumRollHit(DrawableDrumRollTick drawableTick) =>
drumRollHitContainer.Add(new DrawableFlyingHit(drawableTick));
private void addExplosion(DrawableHitObject drawableObject, HitType type)
/// <remarks>
/// As legacy skins have different explosions for singular and double strong hits,
/// explosion addition is scheduled to ensure that both hits are processed if they occur on the same frame.
/// </remarks>
private void addExplosion(DrawableHitObject drawableObject, HitType type) => Schedule(() =>
{
hitExplosionContainer.Add(new HitExplosion(drawableObject));
if (drawableObject.HitObject.Kiai)
kiaiExplosionContainer.Add(new KiaiHitExplosion(drawableObject, type));
}
});
private class ProxyContainer : LifetimeManagementContainer
{