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

Make taiko hitobject properly unproxy when rewound

This commit is contained in:
smoogipoo 2018-06-11 21:45:19 +09:00
parent f07e6370ca
commit 22dfe46572
4 changed files with 70 additions and 34 deletions

View File

@ -86,6 +86,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
switch (State.Value) switch (State.Value)
{ {
case ArmedState.Idle: case ArmedState.Idle:
UnproxyContent();
this.Delay(HitObject.HitWindows.HalfWindowFor(HitResult.Miss)).Expire(); this.Delay(HitObject.HitWindows.HalfWindowFor(HitResult.Miss)).Expire();
break; break;
case ArmedState.Miss: case ArmedState.Miss:
@ -93,6 +94,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
.Expire(); .Expire();
break; break;
case ArmedState.Hit: case ArmedState.Hit:
if (X >= -0.05f)
ProxyContent();
var flash = circlePiece?.FlashBox; var flash = circlePiece?.FlashBox;
if (flash != null) if (flash != null)
{ {

View File

@ -20,12 +20,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {
public class DrawableSwell : DrawableTaikoHitObject<Swell> public class DrawableSwell : DrawableTaikoHitObject<Swell>
{ {
/// <summary>
/// Invoked when the swell has reached the hit target, i.e. when CurrentTime >= StartTime.
/// This is only ever invoked once.
/// </summary>
public event Action OnStart;
private const float target_ring_thick_border = 1.4f; private const float target_ring_thick_border = 1.4f;
private const float target_ring_thin_border = 1f; private const float target_ring_thin_border = 1f;
private const float target_ring_scale = 5f; private const float target_ring_scale = 5f;
@ -40,7 +34,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
/// </summary> /// </summary>
private int userHits; private int userHits;
private bool hasStarted; private bool hasProxied;
private readonly SwellSymbolPiece symbol; private readonly SwellSymbolPiece symbol;
public DrawableSwell(Swell swell) public DrawableSwell(Swell swell)
@ -48,7 +42,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {
FillMode = FillMode.Fit; FillMode = FillMode.Fit;
AddInternal(bodyContainer = new Container Content.Add(bodyContainer = new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Depth = 1, Depth = 1,
@ -177,6 +171,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
switch (state) switch (state)
{ {
case ArmedState.Idle:
hasProxied = false;
UnproxyContent();
break;
case ArmedState.Hit: case ArmedState.Hit:
bodyContainer.Delay(untilJudgement).ScaleTo(1.4f, out_transition_time); bodyContainer.Delay(untilJudgement).ScaleTo(1.4f, out_transition_time);
break; break;
@ -195,10 +193,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
X = Math.Max(0, X); X = Math.Max(0, X);
double t = Math.Min(HitObject.StartTime, Time.Current); double t = Math.Min(HitObject.StartTime, Time.Current);
if (t == HitObject.StartTime && !hasStarted) if (t == HitObject.StartTime && !hasProxied)
{ {
OnStart?.Invoke(); ProxyContent();
hasStarted = true; hasProxied = true;
} }
} }

View File

@ -9,10 +9,62 @@ using OpenTK;
using System.Linq; using System.Linq;
using osu.Game.Audio; using osu.Game.Audio;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {
public abstract class DrawableTaikoHitObject<TaikoHitType> : DrawableHitObject<TaikoHitObject>, IKeyBindingHandler<TaikoAction> public abstract class DrawableTaikoHitObject : DrawableHitObject<TaikoHitObject>, IKeyBindingHandler<TaikoAction>
{
protected readonly Container Content;
public readonly Container ProxiedContent;
private readonly Container nonProxiedContent;
protected DrawableTaikoHitObject(TaikoHitObject hitObject)
: base(hitObject)
{
InternalChildren = new[]
{
nonProxiedContent = new Container
{
RelativeSizeAxes = Axes.Both,
Child = Content = new Container { RelativeSizeAxes = Axes.Both }
},
ProxiedContent = new Container { RelativeSizeAxes = Axes.Both }
};
}
/// <summary>
/// <see cref="ProxiedContent"/> is proxied into an upper layer. We don't want to get masked away otherwise <see cref="ProxiedContent"/> would too.
/// </summary>
protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false;
/// <summary>
/// Moves <see cref="Content"/> to a layer proxied above the playfield.
/// </summary>
protected void ProxyContent()
{
nonProxiedContent.Remove(Content);
ProxiedContent.Remove(Content);
ProxiedContent.Add(Content);
}
/// <summary>
/// Moves <see cref="Content"/> to the normal hitobject layer.
/// </summary>
protected void UnproxyContent()
{
ProxiedContent.Remove(Content);
nonProxiedContent.Remove(Content);
nonProxiedContent.Add(Content);
}
public abstract bool OnPressed(TaikoAction action);
public virtual bool OnReleased(TaikoAction action) => false;
}
public abstract class DrawableTaikoHitObject<TaikoHitType> : DrawableTaikoHitObject
where TaikoHitType : TaikoHitObject where TaikoHitType : TaikoHitObject
{ {
public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); public override Vector2 OriginPosition => new Vector2(DrawHeight / 2);
@ -34,7 +86,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Size = BaseSize = new Vector2(HitObject.IsStrong ? TaikoHitObject.DEFAULT_STRONG_SIZE : TaikoHitObject.DEFAULT_SIZE); Size = BaseSize = new Vector2(HitObject.IsStrong ? TaikoHitObject.DEFAULT_STRONG_SIZE : TaikoHitObject.DEFAULT_SIZE);
InternalChild = MainPiece = CreateMainPiece(); Content.Add(MainPiece = CreateMainPiece());
MainPiece.KiaiMode = HitObject.Kiai; MainPiece.KiaiMode = HitObject.Kiai;
} }
@ -44,9 +96,5 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
protected override string SampleNamespace => "Taiko"; protected override string SampleNamespace => "Taiko";
protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(); protected virtual TaikoPiece CreateMainPiece() => new CirclePiece();
public abstract bool OnPressed(TaikoAction action);
public virtual bool OnReleased(TaikoAction action) => false;
} }
} }

View File

@ -216,10 +216,9 @@ namespace osu.Game.Rulesets.Taiko.UI
if (barline != null) if (barline != null)
barlineContainer.Add(barline.CreateProxy()); barlineContainer.Add(barline.CreateProxy());
// Swells should be moved at the very top of the playfield when they reach the hit target var taikoObject = h as DrawableTaikoHitObject;
var swell = h as DrawableSwell; if (taikoObject != null)
if (swell != null) topLevelHitContainer.Add(taikoObject.ProxiedContent.CreateProxy());
swell.OnStart += () => topLevelHitContainer.Add(swell.CreateProxy());
} }
internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
@ -244,19 +243,6 @@ namespace osu.Game.Rulesets.Taiko.UI
hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == judgedObject)?.VisualiseSecondHit(); hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == judgedObject)?.VisualiseSecondHit();
else else
{ {
if (judgedObject.X >= -0.05f && judgedObject is DrawableHit)
{
// If we're far enough away from the left stage, we should bring outselves in front of it
// Todo: The following try-catch is temporary for replay rewinding support
try
{
topLevelHitContainer.Add(judgedObject.CreateProxy());
}
catch
{
}
}
hitExplosionContainer.Add(new HitExplosion(judgedObject, isRim)); hitExplosionContainer.Add(new HitExplosion(judgedObject, isRim));
if (judgedObject.HitObject.Kiai) if (judgedObject.HitObject.Kiai)