diff --git a/osu-framework b/osu-framework index dd0daafcfc..d29abdf0d0 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit dd0daafcfc0d625bb588c8e12d7db58bc00c255e +Subproject commit d29abdf0d042d832f0849c013d14762db04730e7 diff --git a/osu-resources b/osu-resources index 76656c51f2..f6042e1cb3 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit 76656c51f281e7934159e9ed4414378fef24d130 +Subproject commit f6042e1cb37cfad6c879d0e1245f7880c7fcd5f5 diff --git a/osu.Desktop.Tests/Visual/TestCaseCatcher.cs b/osu.Desktop.Tests/Visual/TestCaseCatcher.cs new file mode 100644 index 0000000000..0e92b5114b --- /dev/null +++ b/osu.Desktop.Tests/Visual/TestCaseCatcher.cs @@ -0,0 +1,29 @@ +// 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.Game.Rulesets.Catch.UI; +using OpenTK; + +namespace osu.Desktop.Tests.Visual +{ + internal class TestCaseCatcher : OsuTestCase + { + protected override void LoadComplete() + { + base.LoadComplete(); + + Children = new Drawable[] + { + new CatcherArea + { + RelativePositionAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Size = new Vector2(1, 0.2f), + } + }; + } + } +} diff --git a/osu.Desktop.Tests/osu.Desktop.Tests.csproj b/osu.Desktop.Tests/osu.Desktop.Tests.csproj index 194c120bc7..3111088ff6 100644 --- a/osu.Desktop.Tests/osu.Desktop.Tests.csproj +++ b/osu.Desktop.Tests/osu.Desktop.Tests.csproj @@ -71,6 +71,7 @@ + diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index f9859cd244..d6efe45adf 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -8,6 +8,7 @@ using System; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.UI; namespace osu.Game.Rulesets.Catch.Beatmaps { @@ -15,9 +16,16 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; - protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) + protected override IEnumerable ConvertHitObject(HitObject obj, Beatmap beatmap) { - yield return null; + if (!(obj is IHasXPosition)) + yield break; + + yield return new Fruit + { + StartTime = obj.StartTime, + Position = ((IHasXPosition)obj).X / OsuPlayfield.BASE_SIZE.X + }; } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 3e7d9bd6d7..aa92f36d23 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -2,34 +2,114 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.MathUtils; +using osu.Game.Graphics; +using osu.Game.Rulesets.Catch.Judgements; +using osu.Game.Rulesets.Objects.Drawables; using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawable { - internal class DrawableFruit : Sprite + internal class DrawableFruit : DrawableHitObject { - //private readonly CatchBaseHit h; - - public DrawableFruit(CatchBaseHit h) + private class Pulp : Circle, IHasAccentColour { - //this.h = h; + public Pulp() + { + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Radius = 5, + Colour = AccentColour.Opacity(0.5f), + }; + } + public Color4 AccentColour { get; set; } = Color4.White; + } + + + public DrawableFruit(CatchBaseHit h) : base(h) + { Origin = Anchor.Centre; - Scale = new Vector2(0.1f); - RelativePositionAxes = Axes.Y; + Size = new Vector2(50); + RelativePositionAxes = Axes.Both; Position = new Vector2(h.Position, -0.1f); + Rotation = (float)(RNG.NextDouble() - 0.5f) * 40; + + Alpha = 0; } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private void load() { - Texture = textures.Get(@"Menu/logo"); + Children = new Framework.Graphics.Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Red, + }, + new Pulp + { + RelativePositionAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre, + Scale = new Vector2(0.12f), + Y = 0.08f, + }, + new Pulp + { + RelativePositionAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre, + Scale = new Vector2(0.32f), + Position = new Vector2(-0.16f, 0.3f), + }, + new Pulp + { + RelativePositionAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre, + Scale = new Vector2(0.32f), + Position = new Vector2(0.16f, 0.3f), + }, + new Pulp + { + RelativePositionAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre, + Scale = new Vector2(0.32f), + Position = new Vector2(0, 0.6f), + }, + }; + + Alpha = 0; + } + + protected override CatchJudgement CreateJudgement() => new CatchJudgement(); + + private const float preempt = 1000; + + protected override void UpdateState(ArmedState state) + { + using (BeginAbsoluteSequence(HitObject.StartTime - preempt)) + { + // default state + this.MoveToY(-0.1f).FadeOut(); + + // animation + this.FadeIn(200).MoveToY(1, preempt); + } - //Transforms.Add(new TransformPosition { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = new Vector2(h.Position, -0.1f), EndValue = new Vector2(h.Position, 0.9f) }); - //Transforms.Add(new TransformAlpha { StartTime = h.StartTime + duration + 200, EndTime = h.StartTime + duration + 400, StartValue = 1, EndValue = 0 }); Expire(true); } } diff --git a/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs b/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs index 179440adb3..cd6adfeea9 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs @@ -6,6 +6,7 @@ using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; @@ -26,6 +27,12 @@ namespace osu.Game.Rulesets.Catch.UI protected override Playfield CreatePlayfield() => new CatchPlayfield(); - protected override DrawableHitObject GetVisualRepresentation(CatchBaseHit h) => null; + protected override DrawableHitObject GetVisualRepresentation(CatchBaseHit h) + { + if (h is Fruit) + return new DrawableFruit(h); + + return null; + } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 8be52150fc..03aabc5632 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.UI; using OpenTK; @@ -14,11 +13,21 @@ namespace osu.Game.Rulesets.Catch.UI { public CatchPlayfield() { - Size = new Vector2(1, 0.9f); - Anchor = Anchor.BottomCentre; - Origin = Anchor.BottomCentre; + Size = new Vector2(1); - Add(new Box { RelativeSizeAxes = Axes.Both, Alpha = 0.5f }); + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; + + Children = new Drawable[] + { + new CatcherArea + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.BottomLeft, + Origin = Anchor.TopLeft, + Height = 0.3f + } + }; } } } \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs new file mode 100644 index 0000000000..153302c1d1 --- /dev/null +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -0,0 +1,146 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Input; +using OpenTK; +using OpenTK.Input; + +namespace osu.Game.Rulesets.Catch.UI +{ + public class CatcherArea : Container + { + public override bool HandleInput => true; + + private Sprite catcher; + + private Drawable createAdditiveFrame() => new Sprite + { + RelativePositionAxes = Axes.Both, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + + Texture = catcher.Texture, + BlendingMode = BlendingMode.Additive, + Position = catcher.Position, + Scale = catcher.Scale, + }; + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Children = new Drawable[] + { + catcher = new Sprite + { + RelativePositionAxes = Axes.Both, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + + X = 0.5f, + Texture = textures.Get(@"Play/Catch/fruit-catcher-idle"), + }, + }; + } + + private bool leftPressed; + private bool rightPressed; + + private int currentDirection; + + private bool dashing; + + protected bool Dashing + { + get + { + return dashing; + } + set + { + if (value == dashing) return; + + dashing = value; + + if (dashing) + Schedule(addAdditiveSprite); + } + } + + private void addAdditiveSprite() + { + if (!dashing) return; + + var additive = createAdditiveFrame(); + + Add(additive); + + additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint).Expire(); + + Scheduler.AddDelayed(addAdditiveSprite, 50); + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Repeat) return true; + + switch (args.Key) + { + case Key.Left: + currentDirection = -1; + leftPressed = true; + return true; + case Key.Right: + currentDirection = 1; + rightPressed = true; + return true; + case Key.ShiftLeft: + Dashing = true; + return true; + } + + return base.OnKeyDown(state, args); + } + + protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + { + switch (args.Key) + { + case Key.Left: + currentDirection = rightPressed ? 1 : 0; + leftPressed = false; + return true; + case Key.Right: + currentDirection = leftPressed ? -1 : 0; + rightPressed = false; + return true; + case Key.ShiftLeft: + Dashing = false; + return true; + } + + return base.OnKeyUp(state, args); + } + + protected override void Update() + { + base.Update(); + + if (currentDirection == 0) return; + + float speed = Dashing ? 1.5f : 1; + + catcher.Scale = new Vector2(Math.Sign(currentDirection), 1); + catcher.X = (float)MathHelper.Clamp(catcher.X + currentDirection * Clock.ElapsedFrameTime / 1800 * speed, 0, 1); + } + } +} diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 83996df41a..003fe2763e 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -57,6 +57,7 @@ +