1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-17 17:22:54 +08:00
osu-lazer/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs

123 lines
4.1 KiB
C#
Raw Normal View History

// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
2018-04-13 17:19:50 +08:00
using System;
using System.Collections.Generic;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.MathUtils;
2018-04-13 17:19:50 +08:00
using osu.Game.Rulesets.Objects.Drawables;
2018-11-20 15:51:59 +08:00
using osuTK;
2018-04-13 17:19:50 +08:00
using osu.Game.Rulesets.Scoring;
2018-07-30 02:51:06 +08:00
using osu.Game.Skinning;
2018-04-13 17:19:50 +08:00
namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
public class DrawableRepeatPoint : DrawableOsuHitObject, ITrackSnaking
{
private readonly RepeatPoint repeatPoint;
private readonly DrawableSlider drawableSlider;
private double animDuration;
public DrawableRepeatPoint(RepeatPoint repeatPoint, DrawableSlider drawableSlider)
: base(repeatPoint)
{
this.repeatPoint = repeatPoint;
this.drawableSlider = drawableSlider;
Size = new Vector2(45 * repeatPoint.Scale);
Blending = BlendingMode.Additive;
Origin = Anchor.Centre;
InternalChildren = new Drawable[]
{
2018-07-30 02:51:06 +08:00
new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon
2018-04-13 17:19:50 +08:00
{
RelativeSizeAxes = Axes.Both,
2019-04-02 18:55:24 +08:00
Icon = FontAwesome.Solid.ChevronRight
2018-07-30 02:51:06 +08:00
}, restrictSize: false)
2018-04-13 17:19:50 +08:00
};
}
protected override void CheckForResult(bool userTriggered, double timeOffset)
2018-04-13 17:19:50 +08:00
{
if (repeatPoint.StartTime <= Time.Current)
ApplyResult(r => r.Type = drawableSlider.Tracking.Value ? HitResult.Great : HitResult.Miss);
2018-04-13 17:19:50 +08:00
}
protected override void UpdatePreemptState()
{
animDuration = Math.Min(150, repeatPoint.SpanDuration / 2);
this.Animate(
d => d.FadeIn(animDuration),
d => d.ScaleTo(0.5f).ScaleTo(1f, animDuration * 4, Easing.OutElasticHalf)
);
}
protected override void UpdateCurrentState(ArmedState state)
{
switch (state)
{
case ArmedState.Idle:
this.Delay(HitObject.TimePreempt).FadeOut();
break;
2019-04-01 11:44:46 +08:00
2018-04-13 17:19:50 +08:00
case ArmedState.Miss:
this.FadeOut(animDuration);
break;
2019-04-01 11:44:46 +08:00
2018-04-13 17:19:50 +08:00
case ArmedState.Hit:
this.FadeOut(animDuration, Easing.OutQuint)
.ScaleTo(Scale * 1.5f, animDuration, Easing.Out);
break;
}
}
private bool hasRotation;
2018-04-13 17:19:50 +08:00
public void UpdateSnakingPosition(Vector2 start, Vector2 end)
{
bool isRepeatAtEnd = repeatPoint.RepeatIndex % 2 == 0;
List<Vector2> curve = drawableSlider.Body.CurrentCurve;
Position = isRepeatAtEnd ? end : start;
if (curve.Count < 2)
return;
int searchStart = isRepeatAtEnd ? curve.Count - 1 : 0;
int direction = isRepeatAtEnd ? -1 : 1;
Vector2 aimRotationVector = Vector2.Zero;
2018-04-13 17:19:50 +08:00
// find the next vector2 in the curve which is not equal to our current position to infer a rotation.
for (int i = searchStart; i >= 0 && i < curve.Count; i += direction)
{
if (Precision.AlmostEquals(curve[i], Position))
2018-04-13 17:19:50 +08:00
continue;
aimRotationVector = curve[i];
2018-04-13 17:19:50 +08:00
break;
}
float aimRotation = MathHelper.RadiansToDegrees((float)Math.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X));
while (Math.Abs(aimRotation - Rotation) > 180)
aimRotation += aimRotation < Rotation ? 360 : -360;
if (!hasRotation)
{
Rotation = aimRotation;
hasRotation = true;
}
else
{
2018-07-31 15:47:13 +08:00
// If we're already snaking, interpolate to smooth out sharp curves (linear sliders, mainly).
Rotation = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint);
}
2018-04-13 17:19:50 +08:00
}
}
}