1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-01 00:12:56 +08:00

Merge pull request #2777 from smoogipoo/fix-taiko-proxies

Make taiko hitobjects properly unproxy when rewound
This commit is contained in:
Dean Herbert 2018-06-18 00:41:08 +09:00 committed by GitHub
commit c09b3f2a02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 36 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,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
.Expire(); .Expire();
break; break;
case ArmedState.Hit: case ArmedState.Hit:
// If we're far enough away from the left stage, we should bring outselves in front of it
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,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
/// </summary> /// </summary>
private int userHits; private int userHits;
private bool hasStarted;
private readonly SwellSymbolPiece symbol; private readonly SwellSymbolPiece symbol;
public DrawableSwell(Swell swell) public DrawableSwell(Swell swell)
@ -48,7 +41,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 +170,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
switch (state) switch (state)
{ {
case ArmedState.Idle:
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,11 +191,8 @@ 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)
{ ProxyContent();
OnStart?.Invoke();
hasStarted = true;
}
} }
private bool? lastWasCentre; private bool? lastWasCentre;

View File

@ -9,10 +9,75 @@ 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;
private 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;
private bool isProxied;
/// <summary>
/// Moves <see cref="Content"/> to a layer proxied above the playfield.
/// Does nothing is content is already proxied.
/// </summary>
protected void ProxyContent()
{
if (isProxied) return;
isProxied = true;
nonProxiedContent.Remove(Content);
proxiedContent.Add(Content);
}
/// <summary>
/// Moves <see cref="Content"/> to the normal hitobject layer.
/// Does nothing is content is not currently proxied.
/// </summary>
protected void UnproxyContent()
{
if (!isProxied) return;
isProxied = false;
proxiedContent.Remove(Content);
nonProxiedContent.Add(Content);
}
/// <summary>
/// Creates a proxy for the content of this <see cref="DrawableTaikoHitObject"/>.
/// </summary>
public Drawable CreateProxiedContent() => proxiedContent.CreateProxy();
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 +99,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 +109,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.CreateProxiedContent());
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)