From e9547542ead87b0f2df143f191daf0d4d74009e0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Jun 2022 17:17:09 +0900 Subject: [PATCH] Add circle gameplay --- osu.Game/Screens/Utility/CircleGameplay.cs | 163 ++++++++++++++++++++- 1 file changed, 162 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Utility/CircleGameplay.cs b/osu.Game/Screens/Utility/CircleGameplay.cs index 0667a54ced..abd7c40532 100644 --- a/osu.Game/Screens/Utility/CircleGameplay.cs +++ b/osu.Game/Screens/Utility/CircleGameplay.cs @@ -2,11 +2,172 @@ // See the LICENCE file in the repository root for full licence text. #nullable enable +using System; +using System.Collections.Generic; +using osu.Framework.Audio.Track; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Utility { - public class CircleGameplay : CompositeDrawable + public class CircleGameplay : BeatSyncedContainer { + private int nextLocation; + + private OsuSpriteText unstableRate = null!; + + private readonly List hitEvents = new List(); + + protected override void LoadComplete() + { + base.LoadComplete(); + + InternalChildren = new Drawable[] + { + unstableRate = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.Default.With(size: 24) + } + }; + } + + protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) + { + base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); + + nextLocation++; + + Vector2 location; + + switch (nextLocation % 4) + { + default: + location = new Vector2(0.25f, 0.25f); + break; + + case 1: + location = new Vector2(0.75f, 0.75f); + break; + + case 2: + location = new Vector2(0.75f, 0.25f); + break; + + case 3: + location = new Vector2(0.25f, 0.75f); + break; + } + + AddInternal(new SampleHitCircle(Clock.CurrentTime + timingPoint.BeatLength) + { + RelativePositionAxes = Axes.Both, + Position = location, + Hit = hit, + }); + } + + private void hit(HitEvent h) + { + hitEvents.Add(h); + unstableRate.Text = $"{hitEvents.CalculateUnstableRate():N1}"; + } + + public class SampleHitCircle : CompositeDrawable + { + public HitEvent? HitEvent; + + public Action? Hit { get; set; } + + public readonly double HitTime; + + private readonly CircularContainer approach; + private readonly Circle circle; + + private const float size = 100; + + public SampleHitCircle(double hitTime) + { + HitTime = hitTime; + + Origin = Anchor.Centre; + + AutoSizeAxes = Axes.Both; + + InternalChildren = new Drawable[] + { + circle = new Circle + { + Colour = Color4.White, + Size = new Vector2(size), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + approach = new CircularContainer + { + BorderColour = Color4.Yellow, + Size = new Vector2(size), + Masking = true, + BorderThickness = 4, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Box + { + Colour = Color4.Black, + Alpha = 0, + AlwaysPresent = true, + RelativeSizeAxes = Axes.Both, + }, + } + }, + }; + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + if (HitEvent != null) + return false; + + approach.Expire(); + + circle + .FadeOut(200) + .ScaleTo(1.5f, 200); + + HitEvent = new HitEvent(Clock.CurrentTime - HitTime, HitResult.Good, new HitObject + { + HitWindows = new HitWindows(), + }, null, null); + + Hit?.Invoke(HitEvent.Value); + + this.Delay(200).Expire(); + + return true; + } + + protected override void Update() + { + base.Update(); + + approach.Scale = new Vector2((float)MathHelper.Clamp((HitTime - Clock.CurrentTime) / 40, 1, 100)); + + if (Clock.CurrentTime > HitTime + 80) + Expire(); + } + } } }