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

Integrate GameplayBeatmap changes

This commit is contained in:
Bartłomiej Dach 2020-05-11 22:53:05 +02:00
parent 43342c57b8
commit e5821ff2b2
3 changed files with 32 additions and 32 deletions

View File

@ -7,7 +7,6 @@ using System.Linq;
using Humanizer; using Humanizer;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Testing; using osu.Framework.Testing;
@ -76,23 +75,14 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
{ {
AddStep("set beatmap", () => setBeatmap()); AddStep("set beatmap", () => setBeatmap());
// the bindables need to be independent for each content cell to prevent interference, AddStep("create mascot", () => SetContents(() => new DrawableTaikoMascot { RelativeSizeAxes = Axes.Both }));
// as if some of the skins don't implement the animation they'll immediately revert to the previous state from the clear state.
var states = new List<Bindable<TaikoMascotAnimationState>>();
AddStep("create mascot", () => SetContents(() => AddStep("set clear state", () => mascots.ForEach(mascot => mascot.State.Value = TaikoMascotAnimationState.Clear));
{ AddStep("miss", () => mascots.ForEach(mascot => mascot.LastResult.Value = new JudgementResult(new Hit(), new TaikoJudgement()) { Type = HitResult.Miss }));
var state = new Bindable<TaikoMascotAnimationState>(TaikoMascotAnimationState.Clear);
states.Add(state);
return new DrawableTaikoMascot { State = { BindTarget = state }, RelativeSizeAxes = Axes.Both };
}));
AddStep("set clear state", () => states.ForEach(state => state.Value = TaikoMascotAnimationState.Clear));
AddStep("miss", () => mascots.ForEach(mascot => mascot.OnNewResult(new JudgementResult(new Hit(), new TaikoJudgement()) { Type = HitResult.Miss })));
AddAssert("skins with animations remain in clear state", () => someMascotsIn(TaikoMascotAnimationState.Clear)); AddAssert("skins with animations remain in clear state", () => someMascotsIn(TaikoMascotAnimationState.Clear));
AddUntilStep("state reverts to fail", () => allMascotsIn(TaikoMascotAnimationState.Fail)); AddUntilStep("state reverts to fail", () => allMascotsIn(TaikoMascotAnimationState.Fail));
AddStep("set clear state again", () => states.ForEach(state => state.Value = TaikoMascotAnimationState.Clear)); AddStep("set clear state again", () => mascots.ForEach(mascot => mascot.State.Value = TaikoMascotAnimationState.Clear));
AddAssert("skins with animations change to clear", () => someMascotsIn(TaikoMascotAnimationState.Clear)); AddAssert("skins with animations change to clear", () => someMascotsIn(TaikoMascotAnimationState.Clear));
} }
@ -220,6 +210,11 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
playfield.OnNewResult(hit, judgementResult); playfield.OnNewResult(hit, judgementResult);
} }
foreach (var mascot in mascots)
{
mascot.LastResult.Value = judgementResult;
}
} }
private bool allMascotsIn(TaikoMascotAnimationState state) => mascots.All(d => d.State.Value == state); private bool allMascotsIn(TaikoMascotAnimationState state) => mascots.All(d => d.State.Value == state);

View File

@ -12,14 +12,15 @@ using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Judgements;
using osu.Game.Screens.Play;
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.UI
{ {
public class DrawableTaikoMascot : BeatSyncedContainer public class DrawableTaikoMascot : BeatSyncedContainer
{ {
public IBindable<TaikoMascotAnimationState> State => state; public readonly Bindable<TaikoMascotAnimationState> State;
public readonly Bindable<JudgementResult> LastResult;
private readonly Bindable<TaikoMascotAnimationState> state;
private readonly Dictionary<TaikoMascotAnimationState, TaikoMascotAnimation> animations; private readonly Dictionary<TaikoMascotAnimationState, TaikoMascotAnimation> animations;
private TaikoMascotAnimation currentAnimation; private TaikoMascotAnimation currentAnimation;
@ -30,12 +31,14 @@ namespace osu.Game.Rulesets.Taiko.UI
{ {
Origin = Anchor = Anchor.BottomLeft; Origin = Anchor = Anchor.BottomLeft;
state = new Bindable<TaikoMascotAnimationState>(startingState); State = new Bindable<TaikoMascotAnimationState>(startingState);
LastResult = new Bindable<JudgementResult>();
animations = new Dictionary<TaikoMascotAnimationState, TaikoMascotAnimation>(); animations = new Dictionary<TaikoMascotAnimationState, TaikoMascotAnimation>();
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader(true)]
private void load(TextureStore textures) private void load(TextureStore textures, GameplayBeatmap gameplayBeatmap)
{ {
InternalChildren = new[] InternalChildren = new[]
{ {
@ -44,6 +47,9 @@ namespace osu.Game.Rulesets.Taiko.UI
animations[TaikoMascotAnimationState.Kiai] = new TaikoMascotAnimation(TaikoMascotAnimationState.Kiai), animations[TaikoMascotAnimationState.Kiai] = new TaikoMascotAnimation(TaikoMascotAnimationState.Kiai),
animations[TaikoMascotAnimationState.Fail] = new TaikoMascotAnimation(TaikoMascotAnimationState.Fail), animations[TaikoMascotAnimationState.Fail] = new TaikoMascotAnimation(TaikoMascotAnimationState.Fail),
}; };
if (gameplayBeatmap != null)
((IBindable<JudgementResult>)LastResult).BindTo(gameplayBeatmap.LastJudgementResult);
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -51,16 +57,22 @@ namespace osu.Game.Rulesets.Taiko.UI
base.LoadComplete(); base.LoadComplete();
animations.Values.ForEach(animation => animation.Hide()); animations.Values.ForEach(animation => animation.Hide());
state.BindValueChanged(mascotStateChanged, true);
State.BindValueChanged(mascotStateChanged, true);
LastResult.BindValueChanged(onNewResult);
} }
public void OnNewResult(JudgementResult result) private void onNewResult(ValueChangedEvent<JudgementResult> resultChangedEvent)
{ {
var result = resultChangedEvent.NewValue;
if (result == null)
return;
// TODO: missing support for clear/fail state transition at end of beatmap gameplay // TODO: missing support for clear/fail state transition at end of beatmap gameplay
if (triggerComboClear(result) || triggerSwellClear(result)) if (triggerComboClear(result) || triggerSwellClear(result))
{ {
state.Value = TaikoMascotAnimationState.Clear; State.Value = TaikoMascotAnimationState.Clear;
// always consider a clear equivalent to a hit to avoid clear -> miss transitions // always consider a clear equivalent to a hit to avoid clear -> miss transitions
lastObjectHit = true; lastObjectHit = true;
} }
@ -79,7 +91,7 @@ namespace osu.Game.Rulesets.Taiko.UI
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();
state.Value = getNextState(); State.Value = getNextState();
} }
private TaikoMascotAnimationState getNextState() private TaikoMascotAnimationState getNextState()
@ -87,7 +99,7 @@ namespace osu.Game.Rulesets.Taiko.UI
// don't change state if current animation is playing // don't change state if current animation is playing
// (used for clear state - others are manually animated on new beats) // (used for clear state - others are manually animated on new beats)
if (currentAnimation != null && !currentAnimation.Completed) if (currentAnimation != null && !currentAnimation.Completed)
return state.Value; return State.Value;
if (!lastObjectHit) if (!lastObjectHit)
return TaikoMascotAnimationState.Fail; return TaikoMascotAnimationState.Fail;

View File

@ -40,8 +40,6 @@ namespace osu.Game.Rulesets.Taiko.UI
private Container hitTargetOffsetContent; private Container hitTargetOffsetContent;
private SkinnableDrawable mascotDrawable;
public TaikoPlayfield(ControlPointInfo controlPoints) public TaikoPlayfield(ControlPointInfo controlPoints)
{ {
this.controlPoints = controlPoints; this.controlPoints = controlPoints;
@ -127,7 +125,7 @@ namespace osu.Game.Rulesets.Taiko.UI
}, },
} }
}, },
mascotDrawable = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.TaikoDon), _ => Empty()) new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.TaikoDon), _ => Empty())
{ {
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
Anchor = Anchor.TopLeft, Anchor = Anchor.TopLeft,
@ -212,11 +210,6 @@ namespace osu.Game.Rulesets.Taiko.UI
addExplosion(judgedObject, type); addExplosion(judgedObject, type);
break; break;
} }
if (mascotDrawable.Drawable is DrawableTaikoMascot mascot)
{
mascot.OnNewResult(result);
}
} }
private void addDrumRollHit(DrawableDrumRollTick drawableTick) => private void addDrumRollHit(DrawableDrumRollTick drawableTick) =>