From 3f6b17c0bf463945337e13b630ecd6d0b09d5900 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 28 Mar 2017 15:05:45 +0900 Subject: [PATCH 1/6] Add drawable Swell. --- .../Tests/TestCaseTaikoHitObjects.cs | 26 +--- .../Tests/TestCaseTaikoPlayfield.cs | 12 ++ .../Objects/Drawable/DrawableSwell.cs | 115 ++++++++++++++++++ .../Drawable/Pieces/SwellCirclePiece.cs | 35 ++++++ osu.Game.Modes.Taiko/Objects/Swell.cs | 2 +- .../osu.Game.Modes.Taiko.csproj | 1 + 6 files changed, 166 insertions(+), 25 deletions(-) create mode 100644 osu.Game.Modes.Taiko/Objects/Drawable/Pieces/SwellCirclePiece.cs diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs index 0204058b8a..82fbb27d15 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs @@ -62,7 +62,7 @@ namespace osu.Desktop.VisualTests.Tests Position = new Vector2(350, 300) }); - Add(new SwellCircle(new CirclePiece() + Add(new SwellCirclePiece(new CirclePiece { KiaiMode = kiai }) @@ -70,7 +70,7 @@ namespace osu.Desktop.VisualTests.Tests Position = new Vector2(100, 500) }); - Add(new SwellCircle(new StrongCirclePiece() + Add(new SwellCirclePiece(new StrongCirclePiece { KiaiMode = kiai }) @@ -97,28 +97,6 @@ namespace osu.Desktop.VisualTests.Tests }); } - private class SwellCircle : BaseCircle - { - public SwellCircle(CirclePiece piece) - : base(piece) - { - Piece.Add(new TextAwesome - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - TextSize = SYMBOL_INNER_SIZE, - Icon = FontAwesome.fa_asterisk, - Shadow = false - }); - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Piece.AccentColour = colours.YellowDark; - } - } - private class DrumRollCircle : BaseCircle { public DrumRollCircle(CirclePiece piece) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs index 395a0cab13..2cef59238d 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs @@ -6,6 +6,7 @@ using osu.Framework.Screens.Testing; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; using osu.Game.Modes.Taiko.Objects; +using osu.Game.Modes.Taiko.Objects.Drawable; using osu.Game.Modes.Taiko.UI; namespace osu.Desktop.VisualTests.Tests @@ -22,6 +23,7 @@ namespace osu.Desktop.VisualTests.Tests AddButton("Hit!", addHitJudgement); AddButton("Miss :(", addMissJudgement); + AddButton("Swell", addSwell); Add(playfield = new TaikoPlayfield { @@ -60,6 +62,16 @@ namespace osu.Desktop.VisualTests.Tests }); } + private void addSwell() + { + playfield.Add(new DrawableSwell(new Swell + { + StartTime = Time.Current + 1000, + EndTime = Time.Current + 5000, + PreEmpt = 1000 + })); + } + private class DrawableTestHit : DrawableHitObject { public DrawableTestHit(TaikoHitObject hitObject) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs index 15584ac73f..405fc48f3e 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs @@ -1,15 +1,30 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using OpenTK; +using OpenTK.Graphics; using OpenTK.Input; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Transforms; +using osu.Game.Graphics; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; +using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; using System; namespace osu.Game.Modes.Taiko.Objects.Drawable { public class DrawableSwell : DrawableTaikoHitObject { + private const float target_ring_thick_border = 4f; + private const float target_ring_thin_border = 1f; + private const float target_ring_scale = 5f; + private const float inner_ring_alpha = 0.35f; + /// /// The amount of times the user has hit this swell. /// @@ -17,10 +32,94 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable private readonly Swell swell; + private readonly Container bodyContainer; + private readonly CircularContainer targetRing; + private readonly CircularContainer innerRing; + public DrawableSwell(Swell swell) : base(swell) { this.swell = swell; + + Children = new Framework.Graphics.Drawable[] + { + bodyContainer = new Container + { + Children = new Framework.Graphics.Drawable[] + { + innerRing = new CircularContainer + { + Name = "Inner ring", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2), + Masking = true, + Children = new [] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = inner_ring_alpha, + } + } + }, + targetRing = new CircularContainer + { + Name = "Target ring (thick border)", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2), + Masking = true, + BorderThickness = target_ring_thick_border, + Children = new Framework.Graphics.Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + }, + new CircularContainer + { + Name = "Target ring (thin border)", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = target_ring_thin_border, + BorderColour = Color4.White, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + } + } + } + } + }, + new SwellCirclePiece(new CirclePiece()) + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + innerRing.Colour = colours.YellowDark; + targetRing.BorderColour = colours.YellowDark.Opacity(0.25f); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + LifetimeEnd = swell.EndTime + HitObject.PreEmpt; + + targetRing.Delay(HitObject.StartTime - Time.Current).ScaleTo(target_ring_scale, 600, EasingTypes.OutQuint); } protected override void CheckJudgement(bool userTriggered) @@ -32,6 +131,10 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable userHits++; + innerRing.FadeTo(1); + innerRing.FadeTo(inner_ring_alpha, 500, EasingTypes.OutQuint); + innerRing.ScaleTo(1f + (target_ring_scale - 1) * userHits / swell.RequiredHits, 1200, EasingTypes.OutElastic); + if (userHits == swell.RequiredHits) { Judgement.Result = HitResult.Hit; @@ -55,6 +158,18 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override void UpdateState(ArmedState state) { + switch (state) + { + case ArmedState.Idle: + break; + case ArmedState.Miss: + bodyContainer.FadeOut(100); + break; + case ArmedState.Hit: + bodyContainer.ScaleTo(1.2f, 400, EasingTypes.OutQuad); + bodyContainer.FadeOut(600, EasingTypes.OutQuint); + break; + } } protected override void UpdateScrollPosition(double time) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/SwellCirclePiece.cs b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/SwellCirclePiece.cs new file mode 100644 index 0000000000..8274a2bff0 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/SwellCirclePiece.cs @@ -0,0 +1,35 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; + +namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces +{ + public class SwellCirclePiece : Container + { + private readonly CirclePiece circle; + + public SwellCirclePiece(CirclePiece piece) + { + Add(circle = piece); + + circle.Add(new TextAwesome + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + TextSize = CirclePiece.SYMBOL_INNER_SIZE, + Icon = FontAwesome.fa_asterisk, + Shadow = false + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + circle.AccentColour = colours.YellowDark; + } + } +} diff --git a/osu.Game.Modes.Taiko/Objects/Swell.cs b/osu.Game.Modes.Taiko/Objects/Swell.cs index 20b9a6effb..4cbb5904c7 100644 --- a/osu.Game.Modes.Taiko/Objects/Swell.cs +++ b/osu.Game.Modes.Taiko/Objects/Swell.cs @@ -17,7 +17,7 @@ namespace osu.Game.Modes.Taiko.Objects /// /// The number of hits required to complete the swell successfully. /// - public int RequiredHits { get; protected set; } + public int RequiredHits { get; protected set; } = 10; public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty) { diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index fa09ae2c82..7cec1bfa7f 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -57,6 +57,7 @@ + From 45653d7b430fead6698063044d09e0b3b20b16ee Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 08:32:34 +0900 Subject: [PATCH 2/6] Fix post-merge errors. --- osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs index 405fc48f3e..73e7a87f95 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs @@ -9,7 +9,6 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Transforms; using osu.Game.Graphics; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; From 6bee57c94ffec06b0ababb8c1d47d7e1a19f8a11 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 08:41:50 +0900 Subject: [PATCH 3/6] Better life time ends. --- osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs index 73e7a87f95..a2bbedd9c6 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs @@ -116,7 +116,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { base.LoadComplete(); - LifetimeEnd = swell.EndTime + HitObject.PreEmpt; + LifetimeEnd = double.MaxValue; targetRing.Delay(HitObject.StartTime - Time.Current).ScaleTo(target_ring_scale, 600, EasingTypes.OutQuint); } @@ -162,11 +162,14 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable case ArmedState.Idle: break; case ArmedState.Miss: - bodyContainer.FadeOut(100); + FadeOut(100); + Expire(); break; case ArmedState.Hit: bodyContainer.ScaleTo(1.2f, 400, EasingTypes.OutQuad); - bodyContainer.FadeOut(600, EasingTypes.OutQuint); + + FadeOut(600); + Expire(); break; } } From 7fc68864beab883202e40f5b051a275c210802ec Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 09:01:40 +0900 Subject: [PATCH 4/6] Move swells on top of the playfield when they reach the hit target. --- .../Objects/Drawable/DrawableSwell.cs | 19 ++++++++++++++++++- osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs | 16 +++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs index a2bbedd9c6..862b81c5dc 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs @@ -19,6 +19,12 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { public class DrawableSwell : DrawableTaikoHitObject { + /// + /// Invoked when the swell has reached the hit target, i.e. when CurrentTime >= StartTime. + /// This is only ever invoked once. + /// + public event Action OnStart; + private const float target_ring_thick_border = 4f; private const float target_ring_thin_border = 1f; private const float target_ring_scale = 5f; @@ -35,6 +41,8 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable private readonly CircularContainer targetRing; private readonly CircularContainer innerRing; + private bool hasStarted; + public DrawableSwell(Swell swell) : base(swell) { @@ -176,7 +184,16 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override void UpdateScrollPosition(double time) { - base.UpdateScrollPosition(Math.Min(time, HitObject.StartTime)); + // Make the swell stop at the hit target + double t = Math.Min(HitObject.StartTime, time); + + if (t == HitObject.StartTime && !hasStarted) + { + OnStart?.Invoke(); + hasStarted = true; + } + + base.UpdateScrollPosition(t); } protected override bool HandleKeyPress(Key key) diff --git a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs index 9bc75a55f5..41e22ea371 100644 --- a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Primitives; +using osu.Game.Modes.Taiko.Objects.Drawable; namespace osu.Game.Modes.Taiko.UI { @@ -52,7 +53,7 @@ namespace osu.Game.Modes.Taiko.UI private readonly Container judgementContainer; private readonly Container hitObjectContainer; - //private Container topLevelHitContainer; + private Container topLevelHitContainer; private readonly Container leftBackgroundContainer; private readonly Container rightBackgroundContainer; private readonly Box leftBackground; @@ -154,10 +155,10 @@ namespace osu.Game.Modes.Taiko.UI }, } }, - //topLevelHitContainer = new Container - //{ - // RelativeSizeAxes = Axes.Both, - //} + topLevelHitContainer = new Container + { + RelativeSizeAxes = Axes.Both, + } }); } @@ -177,6 +178,11 @@ namespace osu.Game.Modes.Taiko.UI h.Scale = new Vector2(PLAYFIELD_SCALE); base.Add(h); + + // Swells should be moved at the very top of the playfield when they reach the hit target + var swell = h as DrawableSwell; + if (swell != null) + swell.OnStart += () => topLevelHitContainer.Add(swell.CreateProxy()); } public override void OnJudgement(DrawableHitObject judgedObject) From 6d5b0a13e46bbdeb460b8d06d64a9ce5fc8c43f9 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 09:02:49 +0900 Subject: [PATCH 5/6] Fix resharper warning. --- osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs index 41e22ea371..1dce4a5c7b 100644 --- a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs @@ -53,7 +53,7 @@ namespace osu.Game.Modes.Taiko.UI private readonly Container judgementContainer; private readonly Container hitObjectContainer; - private Container topLevelHitContainer; + private readonly Container topLevelHitContainer; private readonly Container leftBackgroundContainer; private readonly Container rightBackgroundContainer; private readonly Box leftBackground; From d74454141bc903aeb37de8404a076542cac8c16c Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 09:12:21 +0900 Subject: [PATCH 6/6] Remove explicit life time end. --- osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs | 2 -- osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs | 1 - 2 files changed, 3 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs index 862b81c5dc..b5246321da 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs @@ -124,8 +124,6 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { base.LoadComplete(); - LifetimeEnd = double.MaxValue; - targetRing.Delay(HitObject.StartTime - Time.Current).ScaleTo(target_ring_scale, 600, EasingTypes.OutQuint); } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs index c14dc6d7b0..5d6d669dc1 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs @@ -30,7 +30,6 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override void LoadComplete() { LifetimeStart = HitObject.StartTime - HitObject.PreEmpt * 2; - LifetimeEnd = HitObject.StartTime + HitObject.PreEmpt; base.LoadComplete(); }