// 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.Timing; namespace osu.Game.Rulesets.Mania.Timing { /// /// A that emulates a form of gravity where hit objects speed up over time. /// internal class GravityScrollingDrawableTimingSection : DrawableTimingSection { private readonly MultiplierControlPoint controlPoint; public GravityScrollingDrawableTimingSection(MultiplierControlPoint controlPoint) : base(Axes.Y) { this.controlPoint = controlPoint; } protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); // The gravity-adjusted start position float startPos = (float)computeGravityTime(controlPoint.StartTime); // The gravity-adjusted end position float endPos = (float)computeGravityTime(controlPoint.StartTime + RelativeChildSize.Y); Y = startPos; Height = endPos - startPos; } /// /// Applies gravity to a time value based on the current time. /// /// The time value gravity should be applied to. /// The time after gravity is applied to . private double computeGravityTime(double time) { double relativeTime = relativeTimeAt(time); // The sign of the relative time, this is used to apply backwards acceleration leading into startTime double sign = relativeTime < 0 ? -1 : 1; return VisibleTimeRange - acceleration * relativeTime * relativeTime * sign; } /// /// The acceleration due to "gravity" of the content of this container. /// private double acceleration => 1 / VisibleTimeRange; /// /// Computes the current time relative to , accounting for . /// /// The non-offset time. /// The current time relative to - . private double relativeTimeAt(double time) => Time.Current - time + VisibleTimeRange; } }