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

Add catcher kiai/fail animation states

This commit is contained in:
Dean Herbert 2020-03-10 15:26:39 +09:00
parent a6cf6207aa
commit 7069cef9ce
6 changed files with 134 additions and 14 deletions

View File

@ -10,9 +10,15 @@ using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Catch.Beatmaps;
using osu.Game.Rulesets.Catch.Judgements;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawables;
using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Catch.Tests
@ -34,9 +40,41 @@ namespace osu.Game.Rulesets.Catch.Tests
CreatedDrawables.OfType<CatchInputManager>().Select(i => i.Child)
.OfType<TestCatcherArea>().ForEach(c => c.ToggleHyperDash(t)));
AddRepeatStep("catch fruit", () =>
this.ChildrenOfType<CatcherArea>().ForEach(area =>
area.MovableCatcher.PlaceOnPlate(new DrawableFruit(new TestSceneFruitObjects.TestCatchFruit(FruitVisualRepresentation.Grape)))), 20);
AddRepeatStep("catch fruit", () => catchFruit(new TestFruit(false)
{
X = this.ChildrenOfType<CatcherArea>().First().MovableCatcher.X
}), 20);
AddRepeatStep("catch fruit last in combo", () => catchFruit(new TestFruit(false)
{
X = this.ChildrenOfType<CatcherArea>().First().MovableCatcher.X,
LastInCombo = true,
}), 20);
AddRepeatStep("catch kiai fruit", () => catchFruit(new TestFruit(true)
{
X = this.ChildrenOfType<CatcherArea>().First().MovableCatcher.X,
}), 20);
AddRepeatStep("miss fruit", () => catchFruit(new Fruit
{
X = this.ChildrenOfType<CatcherArea>().First().MovableCatcher.X + 100,
LastInCombo = true,
}, true), 20);
}
private void catchFruit(Fruit fruit, bool miss = false)
{
this.ChildrenOfType<CatcherArea>().ForEach(area =>
{
DrawableFruit drawable = new DrawableFruit(fruit);
area.Add(drawable);
Schedule(() =>
{
area.AttemptCatch(fruit);
area.OnResult(drawable, new JudgementResult(fruit, new CatchJudgement()) { Type = miss ? HitResult.Miss : HitResult.Great });
drawable.Expire();
});
});
}
private void createCatcher(float size)
@ -47,7 +85,8 @@ namespace osu.Game.Rulesets.Catch.Tests
Child = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size })
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.TopLeft
Origin = Anchor.TopLeft,
CreateDrawableRepresentation = ((DrawableRuleset<CatchHitObject>)catchRuleset.CreateInstance().CreateDrawableRulesetWith(new CatchBeatmap())).CreateDrawableRepresentation
},
});
}
@ -58,6 +97,17 @@ namespace osu.Game.Rulesets.Catch.Tests
catchRuleset = rulesets.GetRuleset(2);
}
public class TestFruit : Fruit
{
public TestFruit(bool kiai)
{
var kiaiCpi = new ControlPointInfo();
kiaiCpi.Add(0, new EffectControlPoint { KiaiMode = kiai });
ApplyDefaultsToSelf(kiaiCpi, new BeatmapDifficulty());
}
}
private class TestCatcherArea : CatcherArea
{
public TestCatcherArea(BeatmapDifficulty beatmapDifficulty)

View File

@ -11,6 +11,8 @@ namespace osu.Game.Rulesets.Catch
FruitOrange,
FruitPear,
Droplet,
CatcherIdle
CatcherIdle,
CatcherFail,
CatcherKiai
}
}

View File

@ -48,6 +48,14 @@ namespace osu.Game.Rulesets.Catch.Skinning
case CatchSkinComponents.CatcherIdle:
return this.GetAnimation("fruit-catcher-idle", true, true, true) ??
this.GetAnimation("fruit-ryuuta", true, true, true);
case CatchSkinComponents.CatcherFail:
return this.GetAnimation("fruit-catcher-fail", true, true, true) ??
this.GetAnimation("fruit-ryuuta", true, true, true);
case CatchSkinComponents.CatcherKiai:
return this.GetAnimation("fruit-catcher-kiai", true, true, true) ??
this.GetAnimation("fruit-ryuuta", true, true, true);
}
return null;

View File

@ -0,0 +1,12 @@
// 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.
namespace osu.Game.Rulesets.Catch.UI
{
public enum CatcherAnimationState
{
Idle,
Fail,
Kiai
}
}

View File

@ -155,11 +155,21 @@ namespace osu.Game.Rulesets.Catch.UI
Anchor = Anchor.TopCentre,
Origin = Anchor.BottomCentre,
},
createCatcherSprite().With(c =>
{
c.Anchor = Anchor.TopCentre;
})
};
updateCatcher();
}
private Drawable catcherSprite;
private void updateCatcher()
{
catcherSprite?.Expire();
Add(catcherSprite = createCatcherSprite().With(c =>
{
c.Anchor = Anchor.TopCentre;
}));
}
private int currentDirection;
@ -222,7 +232,7 @@ namespace osu.Game.Rulesets.Catch.UI
Scheduler.AddDelayed(beginTrail, HyperDashing ? 25 : 50);
}
private Drawable createCatcherSprite() => new CatcherSprite();
private Drawable createCatcherSprite() => new CatcherSprite(currentState);
/// <summary>
/// Add a caught fruit to the catcher's stack.
@ -290,9 +300,25 @@ namespace osu.Game.Rulesets.Catch.UI
SetHyperDashState();
}
if (validCatch)
updateState(fruit.Kiai ? CatcherAnimationState.Kiai : CatcherAnimationState.Idle);
else
updateState(CatcherAnimationState.Fail);
return validCatch;
}
private void updateState(CatcherAnimationState state)
{
if (currentState == state)
return;
currentState = state;
updateCatcher();
}
private CatcherAnimationState currentState;
private double hyperDashModifier = 1;
private int hyperDashDirection;
private float hyperDashTargetPosition;

View File

@ -14,9 +14,9 @@ namespace osu.Game.Rulesets.Catch.UI
{
protected override bool ApplySizeRestrictionsToDefault => true;
public CatcherSprite()
: base(new CatchSkinComponent(CatchSkinComponents.CatcherIdle), _ =>
new DefaultCatcherSprite(), confineMode: ConfineMode.ScaleDownToFit)
public CatcherSprite(CatcherAnimationState state)
: base(new CatchSkinComponent(componentFromState(state)), _ =>
new DefaultCatcherSprite(state), confineMode: ConfineMode.ScaleDownToFit)
{
RelativeSizeAxes = Axes.None;
Size = new Vector2(CatcherArea.CATCHER_SIZE);
@ -25,12 +25,34 @@ namespace osu.Game.Rulesets.Catch.UI
OriginPosition = new Vector2(0.5f, 0.06f) * CatcherArea.CATCHER_SIZE;
}
private static CatchSkinComponents componentFromState(CatcherAnimationState state)
{
switch (state)
{
case CatcherAnimationState.Fail:
return CatchSkinComponents.CatcherFail;
case CatcherAnimationState.Kiai:
return CatchSkinComponents.CatcherKiai;
default:
return CatchSkinComponents.CatcherIdle;
}
}
private class DefaultCatcherSprite : Sprite
{
private readonly CatcherAnimationState state;
public DefaultCatcherSprite(CatcherAnimationState state)
{
this.state = state;
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
Texture = textures.Get("Gameplay/catch/fruit-catcher-idle");
Texture = textures.Get($"Gameplay/catch/fruit-catcher-{state.ToString().ToLower()}");
}
}
}