diff --git a/osu.Game.Rulesets.Hishigata/LinearMath/LineSegment.cs b/osu.Game.Rulesets.Hishigata/LinearMath/LineSegment.cs index ee6fcce..a7e27a4 100644 --- a/osu.Game.Rulesets.Hishigata/LinearMath/LineSegment.cs +++ b/osu.Game.Rulesets.Hishigata/LinearMath/LineSegment.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using osuTK; namespace osu.Game.Rulesets.Hishigata.LinearMath @@ -13,44 +11,44 @@ public struct LineSegment public readonly Vector2 PointA; public readonly Vector2 PointB; - public LineSegment (Vector2 a, Vector2 b) + public LineSegment(Vector2 a, Vector2 b) { PointA = a; PointB = b; } - public bool TryIntersect (LineSegment other, out Vector2 point) + public bool TryIntersect(LineSegment other, out Vector2 point) { - if ( Dx == 0 || other.Dx == 0 ) + if (Dx == 0 || other.Dx == 0) { var m1 = Dx / Dy; var m2 = other.Dx / other.Dy; - var b1 = PointA.X - m1 * PointA.Y; - var b2 = other.PointA.X - m2 * other.PointA.Y; + var b1 = PointA.X - (m1 * PointA.Y); + var b2 = other.PointA.X - (m2 * other.PointA.Y); - var y = ( b2 - b1 ) / ( m1 - m2 ); - point = new Vector2(m1 * y + b1, y); + var y = (b2 - b1) / (m1 - m2); + point = new Vector2((m1 * y) + b1, y); } else { var m1 = Dy / Dx; var m2 = other.Dy / other.Dx; - var b1 = PointA.Y - m1 * PointA.X; - var b2 = other.PointA.Y - m2 * other.PointA.X; + var b1 = PointA.Y - (m1 * PointA.X); + var b2 = other.PointA.Y - (m2 * other.PointA.X); - var x = ( b2 - b1 ) / ( m1 - m2 ); - point = new Vector2(x, m1 * x + b1); + var x = (b2 - b1) / (m1 - m2); + point = new Vector2(x, (m1 * x) + b1); } - return isInBounds( point ) && other.isInBounds( point ); + return isInBounds(point) && other.isInBounds(point); } - private bool isInBounds (Vector2 point) - => point.X > Math.Min(PointA.X, PointB.X) - 1 - && point.X < Math.Max(PointA.X, PointB.X) + 1 - && point.Y > Math.Min(PointA.Y, PointB.Y) - 1 - && point.Y < Math.Max(PointA.Y, PointB.Y) + 1; + private bool isInBounds(Vector2 point) + => point.X > Math.Min(PointA.X, PointB.X) + && point.X < Math.Max(PointA.X, PointB.X) + && point.Y > Math.Min(PointA.Y, PointB.Y) + && point.Y < Math.Max(PointA.Y, PointB.Y); } } diff --git a/osu.Game.Rulesets.Hishigata/UI/Components/MaskedPlayerArrow.cs b/osu.Game.Rulesets.Hishigata/UI/Components/MaskedPlayerArrow.cs index 8050fee..3836ef3 100644 --- a/osu.Game.Rulesets.Hishigata/UI/Components/MaskedPlayerArrow.cs +++ b/osu.Game.Rulesets.Hishigata/UI/Components/MaskedPlayerArrow.cs @@ -1,16 +1,16 @@ -using osu.Framework.Graphics.Containers; -using osuTK; -using osuTK.Graphics; +using System; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Allocation; -using osu.Framework.Bindables; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Rulesets.Hishigata.UI.Components { public class MaskedPlayerArrow : CompositeDrawable { private readonly Box chevron; + private readonly Container rotationContainer; public MaskedPlayerArrow() { @@ -28,22 +28,38 @@ public MaskedPlayerArrow() Anchor = Anchor.Centre, Origin = Anchor.Centre, Rotation = -45, - Child = chevron = new Box + Child = rotationContainer = new Container { RelativeSizeAxes = Axes.Both, - Size = new Vector2(2f), Anchor = Anchor.Centre, - Origin = Anchor.BottomCentre, - Alpha = 0, - AlwaysPresent = true + Origin = Anchor.Centre, + Child = chevron = new Box + { + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + // Using the hypotenuse length + Size = new Vector2(1.41f, 0.71f), + Anchor = Anchor.Centre, + Origin = Anchor.BottomCentre, + Alpha = 0, + AlwaysPresent = true + } } }; } - [BackgroundDependencyLoader] - private void load(BindableFloat angleBindable) + public void ChangeRotation(float newRotation, Easing easing = Easing.None) { - angleBindable.BindValueChanged(a => chevron.Rotation = a.NewValue, true); + FinishTransforms(true); + if (Math.Abs(newRotation - rotationContainer.Rotation) == 180) + { + chevron.MoveToY(0.71f, 50, easing).Then().MoveToY(0); + rotationContainer.Delay(50).RotateTo(newRotation); + } + else + { + rotationContainer.RotateTo(newRotation, 50, easing); + } } } } diff --git a/osu.Game.Rulesets.Hishigata/UI/Components/PathPlayerArrow.cs b/osu.Game.Rulesets.Hishigata/UI/Components/PathPlayerArrow.cs index 88fc453..26a05bc 100644 --- a/osu.Game.Rulesets.Hishigata/UI/Components/PathPlayerArrow.cs +++ b/osu.Game.Rulesets.Hishigata/UI/Components/PathPlayerArrow.cs @@ -1,10 +1,9 @@ using System; -using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Graphics.Lines; using osu.Framework.Graphics; -using osuTK; +using osu.Framework.Graphics.Lines; using osu.Game.Rulesets.Hishigata.LinearMath; +using osuTK; namespace osu.Game.Rulesets.Hishigata.UI.Components { @@ -17,7 +16,12 @@ public PathPlayerArrow() PathRadius = 5; AutoSizeAxes = Axes.None; - Size = new Vector2(( PathRadius + size ) * 2); + Size = new Vector2((PathRadius + size) * 2); + + angle.BindValueChanged(x => redraw()); + arc.BindValueChanged(x => redraw()); + + redraw(); } private const float size = 30; @@ -28,23 +32,37 @@ public PathPlayerArrow() new LineSegment( new Vector2(0,-size), new Vector2(size,0) ) }; - [BackgroundDependencyLoader] - private void load(BindableFloat angleBindable) + private const float deg_to_rad = MathF.PI / 180; + private BindableFloat arc = new BindableFloat(180); + private BindableFloat angle = new BindableFloat(0); + + public void ChangeRotation(float angle, Easing easing = Easing.None) { - angleBindable.BindValueChanged(a => redraw(a.NewValue), true); + FinishTransforms(); + + if (Math.Abs(angle - this.angle.Value) % 360 == 180) + { + this.TransformBindableTo(arc, 360, 25, easing) + .Then() + .TransformBindableTo(arc, 180, 25, easing) + .TransformBindableTo(this.angle, angle); + } + else + { + this.TransformBindableTo(this.angle, angle, 50, easing); + } } - private void redraw(float angle) + private void redraw() { - angle = angle / 180 * MathF.PI; // to radians ClearVertices(); - const int count = 30; + const int count = 60; const float radius = 100; for (int i = 0; i < count; i++) { float progress = i / (float)(count - 1); - var vertexAngle = angle - (MathF.PI / 2) + (progress * MathF.PI); + var vertexAngle = (angle.Value - (arc.Value / 2) + (progress * arc.Value)) * deg_to_rad; LineSegment ray = new LineSegment(Vector2.Zero, new Vector2(MathF.Sin(vertexAngle) * radius, -MathF.Cos(vertexAngle) * radius)); foreach (var segment in segments) diff --git a/osu.Game.Rulesets.Hishigata/UI/Components/Player.cs b/osu.Game.Rulesets.Hishigata/UI/Components/Player.cs index 2a4f4de..4f49e90 100644 --- a/osu.Game.Rulesets.Hishigata/UI/Components/Player.cs +++ b/osu.Game.Rulesets.Hishigata/UI/Components/Player.cs @@ -1,4 +1,3 @@ -using System; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Bindables; @@ -9,8 +8,8 @@ using osu.Framework.Utils; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Containers; -using osu.Game.Rulesets.Hishigata.Objects.Drawables; using osu.Game.Rulesets.Hishigata.Configuration; +using osu.Game.Rulesets.Hishigata.Objects.Drawables; using osuTK; using osuTK.Graphics; using System.Collections.Generic; @@ -24,8 +23,7 @@ public class PlayerVisual : BeatSyncedContainer, IKeyBindingHandler 180) difference -= 360; else if (difference < -180) difference += 360; - double totalDuration = Math.Abs(difference) / 90 * duration; - - this.TransformBindableTo(angleBindable, angleBindable.Value + difference, totalDuration, easing); + targetAngle += difference; + maskedArrow.ChangeRotation(targetAngle, easing); + pathArrow.ChangeRotation(targetAngle, easing); } private void setArrowSkin(ArrowStyle style)