From 77ee161be8afa156dc8c95d22ed3c0111cad94bf Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 10 Feb 2017 06:16:23 +0100 Subject: [PATCH] Add follow points. --- .../Objects/Drawables/FollowPoint.cs | 64 +++++++++++++++++ osu.Game.Modes.Osu/UI/OsuPlayfield.cs | 71 ++++++++++++++++++- osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj | 1 + osu.Game/Modes/UI/HitRenderer.cs | 1 + osu.Game/Modes/UI/Playfield.cs | 6 +- 5 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 osu.Game.Modes.Osu/Objects/Drawables/FollowPoint.cs diff --git a/osu.Game.Modes.Osu/Objects/Drawables/FollowPoint.cs b/osu.Game.Modes.Osu/Objects/Drawables/FollowPoint.cs new file mode 100644 index 0000000000..22ffead4d9 --- /dev/null +++ b/osu.Game.Modes.Osu/Objects/Drawables/FollowPoint.cs @@ -0,0 +1,64 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +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.Graphics.Transformations; + +namespace osu.Game.Modes.Osu.Objects.Drawables +{ + public class FollowPoint : Container + { + private Sprite followPoint; + + public double StartTime; + public double EndTime; + public Vector2 EndPosition; + + public FollowPoint() + { + Origin = Anchor.Centre; + Alpha = 0; + + Children = new Drawable[] + { + followPoint = new Sprite + { + Size = new Vector2(12f), + Origin = Anchor.Centre, + BlendingMode = BlendingMode.Additive, + Alpha = 0.5f + }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + DelayReset(); + + Delay(StartTime); + FadeIn(DrawableOsuHitObject.TIME_FADEIN); + ScaleTo(1.5f); + ScaleTo(1, DrawableOsuHitObject.TIME_FADEIN, EasingTypes.Out); + MoveTo(EndPosition, DrawableOsuHitObject.TIME_FADEIN, EasingTypes.Out); + + Delay(EndTime - StartTime); + FadeOut(DrawableOsuHitObject.TIME_FADEIN); + + Delay(DrawableOsuHitObject.TIME_FADEIN); + Expire(true); + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + followPoint.Texture = textures.Get(@"Play/osu/ring-glow"); + } + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs index 49c6869189..1be73a0452 100644 --- a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs @@ -1,13 +1,16 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Objects; using osu.Game.Modes.Osu.Objects.Drawables; using osu.Game.Modes.UI; -using OpenTK; +using System; +using System.Collections.Generic; +using System.Linq; namespace osu.Game.Modes.Osu.UI { @@ -15,6 +18,7 @@ namespace osu.Game.Modes.Osu.UI { private Container approachCircles; private Container judgementLayer; + private Container followPointsLayer; public override Vector2 Size { @@ -36,11 +40,16 @@ namespace osu.Game.Modes.Osu.UI Add(new Drawable[] { - judgementLayer = new Container + followPointsLayer = new Container { RelativeSizeAxes = Axes.Both, Depth = 1, }, + judgementLayer = new Container + { + RelativeSizeAxes = Axes.Both, + Depth = 0, + }, approachCircles = new Container { RelativeSizeAxes = Axes.Both, @@ -63,11 +72,69 @@ namespace osu.Game.Modes.Osu.UI base.Add(h); } + public override void PostProcess() + { + AddFollowPoints(); + } + private void judgement(DrawableHitObject h, JudgementInfo j) { HitExplosion explosion = new HitExplosion((OsuJudgementInfo)j, (OsuHitObject)h.HitObject); judgementLayer.Add(explosion); } + + public void AddFollowPoints(int startIndex = 0, int endIndex = -1) + { + var followLineDistance = 32; + var followLinePreEmpt = 800; + + var hitObjects = new List(HitObjects.Children + .Select(d => (OsuHitObject)d.HitObject) + .OrderBy(h => h.StartTime)); + + if (endIndex < 0) + endIndex = hitObjects.Count - 1; + + for (int i = startIndex + 1; i <= endIndex; i++) + { + var prevHitObject = hitObjects[i - 1]; + var currHitObject = hitObjects[i]; + + if (prevHitObject.StartTime > currHitObject.StartTime) + throw new Exception(); + + if (!currHitObject.NewCombo && !(prevHitObject is Spinner) && !(currHitObject is Spinner)) + { + Vector2 startPosition = prevHitObject.EndPosition; + Vector2 endPosition = currHitObject.Position; + double startTime = prevHitObject.EndTime; + double endTime = currHitObject.StartTime; + + Vector2 distanceVector = endPosition - startPosition; + int distance = (int)distanceVector.Length; + float rotation = (float)Math.Atan2(distanceVector.Y, distanceVector.X); + double duration = endTime - startTime; + + for (int d = (int)(followLineDistance * 1.5); d < distance - followLineDistance; d += followLineDistance) + { + float fraction = ((float)d / distance); + Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; + Vector2 pointEndPosition = startPosition + fraction * distanceVector; + double fadeOutTime = startTime + fraction * duration; + double fadeInTime = fadeOutTime - followLinePreEmpt; + + followPointsLayer.Add(new FollowPoint() + { + StartTime = fadeInTime, + EndTime = fadeOutTime, + Position = pointStartPosition, + EndPosition = pointEndPosition, + Rotation = rotation, + }); + } + } + } + } } } \ No newline at end of file diff --git a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj index a9a346f563..88d25cb8f4 100644 --- a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj @@ -47,6 +47,7 @@ + diff --git a/osu.Game/Modes/UI/HitRenderer.cs b/osu.Game/Modes/UI/HitRenderer.cs index aa2af83cb4..14d9599be6 100644 --- a/osu.Game/Modes/UI/HitRenderer.cs +++ b/osu.Game/Modes/UI/HitRenderer.cs @@ -83,6 +83,7 @@ namespace osu.Game.Modes.UI Playfield.Add(drawableObject); } + Playfield.PostProcess(); } private void onJudgement(DrawableHitObject o, JudgementInfo j) => TriggerOnJudgement(j); diff --git a/osu.Game/Modes/UI/Playfield.cs b/osu.Game/Modes/UI/Playfield.cs index 748c71a8b3..91eddce73c 100644 --- a/osu.Game/Modes/UI/Playfield.cs +++ b/osu.Game/Modes/UI/Playfield.cs @@ -1,10 +1,10 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Modes.Objects.Drawables; -using OpenTK; namespace osu.Game.Modes.UI { @@ -32,6 +32,10 @@ namespace osu.Game.Modes.UI }); } + public virtual void PostProcess() + { + } + public class ScaledContainer : Container { protected override Vector2 DrawScale => new Vector2(DrawSize.X / 512);