public void Add(DrawableHitObject fruit, Vector2 absolutePosition) { fruit.RelativePositionAxes = Axes.None; fruit.Position = new Vector2(ToLocalSpace(absolutePosition).X - DrawSize.X / 2, 0); fruit.Anchor = Anchor.TopCentre; fruit.Origin = Anchor.BottomCentre; fruit.Scale *= 0.7f; fruit.LifetimeEnd = double.MaxValue; float distance = fruit.DrawSize.X / 2 * fruit.Scale.X; while (caughtFruit.Any(f => f.LifetimeEnd == double.MaxValue && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) { fruit.X += RNG.Next(-5, 5); fruit.Y -= RNG.Next(0, 5); } caughtFruit.Add(fruit); if (((CatchBaseHit)fruit.HitObject).LastInCombo) { explode(); } }
/// <summary> /// Determines which drawable should currently receive a tooltip, taking into account /// <see cref="AppearDelay"/> and <see cref="AppearRadius"/>. Returns null if no valid /// target is found. /// </summary> /// <returns>The tooltip target. null if no valid one is found.</returns> private IHasTooltip findTooltipTarget() { // While we are dragging a tooltipped drawable we should show a tooltip for it. IHasTooltip draggedTarget = inputManager.DraggedDrawable as IHasTooltip; if (draggedTarget != null) { return(hasValidTooltip(draggedTarget) ? draggedTarget : null); } // Always keep 10 positions at equally-sized time intervals that add up to AppearDelay. double positionRecordInterval = AppearDelay / 10; if (Time.Current - lastRecordedPositionTime >= positionRecordInterval) { lastRecordedPositionTime = Time.Current; recentMousePositions.Add(new TimedPosition { Time = Time.Current, Position = ToLocalSpace(inputManager.CurrentState.Mouse.Position) }); } recentMousePositions.RemoveAll(t => Time.Current - t.Time > AppearDelay); // For determining whether to show a tooltip we first select only those positions // which happened within a shorter, alpha-adjusted appear delay. double alphaModifiedAppearDelay = (1 - currentTooltip.Alpha) * AppearDelay; var relevantPositions = recentMousePositions.Where(t => Time.Current - t.Time <= alphaModifiedAppearDelay); // We then check whether all relevant positions fall within a radius of AppearRadius within the // first relevant position. If so, then the mouse has stayed within a small circular region of // AppearRadius for the duration of the modified appear delay, and we therefore want to display // the tooltip. Vector2 first = relevantPositions.FirstOrDefault().Position; float appearRadiusSq = AppearRadius * AppearRadius; if (relevantPositions.All(t => Vector2Extensions.DistanceSquared(t.Position, first) < appearRadiusSq)) { // Only return the target if it has a valid tooltip IHasTooltip target = FindTarget(); if (hasValidTooltip(target)) { return(target); } } return(null); }
private ITooltipContentProvider handlePotentialTarget(ITooltipContentProvider targetCandidate) { // this method is intentionally split out from the main lookup above as it has several expensive delegate (LINQ) allocations. // this allows the case where no tooltip is displayed to run with no allocations. // further optimisation work can be done here to reduce allocations while a tooltip is being displayed. double appearDelay = (targetCandidate as IHasAppearDelay)?.AppearDelay ?? AppearDelay; // Always keep 10 positions at equally-sized time intervals that add up to AppearDelay. double positionRecordInterval = appearDelay / 10; if (Time.Current - lastRecordedPositionTime >= positionRecordInterval) { lastRecordedPositionTime = Time.Current; recentMousePositions.Add(new TimedPosition { Time = Time.Current, Position = ToLocalSpace(inputManager.CurrentState.Mouse.Position) }); } // check that we have recorded enough positions to make a judgement about whether or not the cursor has been standing still for the required amount of time. // we can skip this if the appear-delay is set to 0, since then tooltips can appear instantly and we don't need to wait to record enough positions. if (appearDelay > 0 && (recentMousePositions.Count == 0 || lastRecordedPositionTime - recentMousePositions[0].Time < appearDelay - positionRecordInterval)) { return(null); } recentMousePositions.RemoveAll(t => Time.Current - t.Time > appearDelay); // For determining whether to show a tooltip we first select only those positions // which happened within a shorter, alpha-adjusted appear delay. double alphaModifiedAppearDelay = (1 - CurrentTooltip.Alpha) * appearDelay; var relevantPositions = recentMousePositions.Where(t => Time.Current - t.Time <= alphaModifiedAppearDelay); // We then check whether all relevant positions fall within a radius of AppearRadius within the // first relevant position. If so, then the mouse has stayed within a small circular region of // AppearRadius for the duration of the modified appear delay, and we therefore want to display // the tooltip. Vector2 first = relevantPositions.FirstOrDefault().Position; float appearRadiusSq = AppearRadius * AppearRadius; if (relevantPositions.All(t => Vector2Extensions.DistanceSquared(t.Position, first) < appearRadiusSq)) { return(targetCandidate); } return(null); }
public void Add(DrawableHitObject fruit) { float distance = fruit.DrawSize.X / 2 * fruit.Scale.X; while (caughtFruit.Any(f => f.LifetimeEnd == double.MaxValue && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) { fruit.X += RNG.Next(-5, 5); fruit.Y -= RNG.Next(0, 5); } caughtFruit.Add(fruit); if (((CatchHitObject)fruit.HitObject).LastInCombo) { explode(); } }
public void AddToStack(DrawableHitObject fruit, Vector2 absolutePosition) { fruit.RelativePositionAxes = Axes.None; fruit.Position = new Vector2(ToLocalSpace(absolutePosition).X - DrawSize.X / 2, 0); fruit.Anchor = Anchor.TopCentre; fruit.Origin = Anchor.BottomCentre; fruit.Scale *= 0.7f; fruit.LifetimeEnd = double.MaxValue; float distance = fruit.DrawSize.X / 2 * fruit.Scale.X; while (Children.OfType <DrawableFruit>().Any(f => Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) { fruit.X += RNG.Next(-5, 5); fruit.Y -= RNG.Next(0, 5); } Add(fruit); }
/// <summary> /// Distance squared from an arbitrary point p to this line. /// </summary> public float DistanceSquaredToPoint(Vector2 p) { return(Vector2Extensions.DistanceSquared(p, ClosestPointTo(p))); }
/// <summary> /// Determines which drawable should currently receive a tooltip, taking into account /// <see cref="AppearDelay"/> and <see cref="AppearRadius"/>. Returns null if no valid /// target is found. /// </summary> /// <returns>The tooltip target. null if no valid one is found.</returns> private IHasTooltip findTooltipTarget() { // While we are dragging a tooltipped drawable we should show a tooltip for it. if (inputManager.DraggedDrawable is IHasTooltip draggedTarget) { return(hasValidTooltip(draggedTarget) ? draggedTarget : null); } IHasTooltip targetCandidate = FindTargets().Find(t => t.TooltipText != null); // check this first - if we find no target candidate we still want to clear the recorded positions and update the lastCandidate. if (targetCandidate != lastCandidate) { recentMousePositions.Clear(); lastCandidate = targetCandidate; } if (targetCandidate == null) { return(null); } double appearDelay = (targetCandidate as IHasAppearDelay)?.AppearDelay ?? AppearDelay; // Always keep 10 positions at equally-sized time intervals that add up to AppearDelay. double positionRecordInterval = appearDelay / 10; if (Time.Current - lastRecordedPositionTime >= positionRecordInterval) { lastRecordedPositionTime = Time.Current; recentMousePositions.Add(new TimedPosition { Time = Time.Current, Position = ToLocalSpace(inputManager.CurrentState.Mouse.Position) }); } // check that we have recorded enough positions to make a judgement about whether or not the cursor has been standing still for the required amount of time. // we can skip this if the appear-delay is set to 0, since then tooltips can appear instantly and we don't need to wait to record enough positions. if (appearDelay > 0 && (recentMousePositions.Count == 0 || lastRecordedPositionTime - recentMousePositions[0].Time < appearDelay - positionRecordInterval)) { return(null); } recentMousePositions.RemoveAll(t => Time.Current - t.Time > appearDelay); // For determining whether to show a tooltip we first select only those positions // which happened within a shorter, alpha-adjusted appear delay. double alphaModifiedAppearDelay = (1 - CurrentTooltip.Alpha) * appearDelay; var relevantPositions = recentMousePositions.Where(t => Time.Current - t.Time <= alphaModifiedAppearDelay); // We then check whether all relevant positions fall within a radius of AppearRadius within the // first relevant position. If so, then the mouse has stayed within a small circular region of // AppearRadius for the duration of the modified appear delay, and we therefore want to display // the tooltip. Vector2 first = relevantPositions.FirstOrDefault().Position; float appearRadiusSq = AppearRadius * AppearRadius; if (relevantPositions.All(t => Vector2Extensions.DistanceSquared(t.Position, first) < appearRadiusSq)) { return(targetCandidate); } return(null); }