1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-14 03:25:11 +08:00

Move spinner bonus scoring to it's own component class

Also fixes counter rewinding issue and does optimizations.
This commit is contained in:
Salman Ahmed 2019-12-25 05:34:12 +03:00
parent 419656cea4
commit 949ab4e0d3
3 changed files with 100 additions and 42 deletions

View File

@ -26,11 +26,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected readonly Spinner Spinner;
private readonly Container<DrawableSpinnerTick> ticks;
private readonly OsuSpriteText bonusCounter;
public readonly SpinnerDisc Disc;
public readonly SpinnerTicks Ticks;
public readonly SpinnerSpmCounter SpmCounter;
private readonly SpinnerBonusComponent bonusComponent;
private readonly Container mainContainer;
@ -123,13 +123,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Y = 120,
Alpha = 0
},
bonusCounter = new OsuSpriteText
bonusComponent = new SpinnerBonusComponent(this, ticks)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Y = -120,
Font = OsuFont.Numeric.With(size: 24),
Alpha = 0,
}
};
}
@ -226,8 +224,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
base.Update();
}
private int currentSpins;
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
@ -235,30 +231,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
circle.Rotation = Disc.Rotation;
Ticks.Rotation = Disc.Rotation;
SpmCounter.SetRotation(Disc.RotationAbsolute);
var newSpins = (int)(Disc.RotationAbsolute / 360) - currentSpins;
for (int i = currentSpins; i < currentSpins + newSpins; i++)
{
if (i < 0 || i >= ticks.Count)
break;
var tick = ticks[i];
tick.HasBonusPoints = Progress >= 1 && i > Spinner.SpinsRequired;
if (tick.HasBonusPoints)
{
bonusCounter.Text = $"{(i - Spinner.SpinsRequired) * 1000}";
bonusCounter
.FadeOutFromOne(1500)
.ScaleTo(1.5f).ScaleTo(1f, 1000, Easing.OutQuint);
}
tick.TriggerResult(HitResult.Great);
}
currentSpins += newSpins;
bonusComponent.UpdateRotation(Disc.RotationAbsolute);
float relativeCircleScale = Spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight;
Disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint);
@ -299,15 +272,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
sequence.ScaleTo(Scale * 0.8f, 320, Easing.In);
break;
}
if (state != ArmedState.Idle)
{
Schedule(() =>
{
foreach (var tick in ticks.Where(t => !t.IsHit))
tick.TriggerResult(HitResult.Miss);
});
}
}
}
}

View File

@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
/// <summary>
/// Whether this judgement has a bonus of 1,000 points additional to the numeric result.
/// Should be set when a spin occured after the spinner has completed.
/// Set when a spin occured after the spinner has completed.
/// </summary>
public bool HasBonusPoints
{
@ -44,10 +44,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Samples.AddAdjustment(AdjustableProperty.Volume, bonusSampleVolume);
}
public void TriggerResult(HitResult result)
/// <summary>
/// Apply a judgement result.
/// </summary>
/// <param name="hit">Whether to apply a <see cref="HitResult.Great"/> result, <see cref="HitResult.Miss"/> otherwise.</param>
internal void TriggerResult(bool hit)
{
HitObject.StartTime = Time.Current;
ApplyResult(r => r.Type = result);
ApplyResult(r => r.Type = hit ? HitResult.Great : HitResult.Miss);
}
}
}

View File

@ -0,0 +1,90 @@
// 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.
using System;
using System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
/// <summary>
/// A component that tracks spinner spins and add bonus score for it.
/// </summary>
public class SpinnerBonusComponent : CompositeDrawable
{
private readonly DrawableSpinner drawableSpinner;
private readonly Container<DrawableSpinnerTick> ticks;
private readonly OsuSpriteText bonusCounter;
public SpinnerBonusComponent(DrawableSpinner drawableSpinner, Container<DrawableSpinnerTick> ticks)
{
this.drawableSpinner = drawableSpinner;
this.ticks = ticks;
drawableSpinner.OnNewResult += onNewResult;
AutoSizeAxes = Axes.Both;
InternalChild = bonusCounter = new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Font = OsuFont.Numeric.With(size: 24),
Alpha = 0,
};
}
private int currentSpins;
public void UpdateRotation(double rotation)
{
if (ticks.Count == 0)
return;
int spinsRequired = ((Spinner)drawableSpinner.HitObject).SpinsRequired;
int newSpins = Math.Clamp((int)(rotation / 360), 0, ticks.Count - 1);
int direction = Math.Sign(newSpins - currentSpins);
while (currentSpins != newSpins)
{
var tick = ticks[currentSpins];
if (direction >= 0)
{
tick.HasBonusPoints = currentSpins > spinsRequired;
tick.TriggerResult(true);
}
if (tick.HasBonusPoints)
{
bonusCounter.Text = $"{1000 * (currentSpins - spinsRequired)}";
bonusCounter.FadeOutFromOne(1500);
bonusCounter.ScaleTo(1.5f).Then().ScaleTo(1f, 1000, Easing.OutQuint);
}
currentSpins += direction;
}
}
private void onNewResult(DrawableHitObject hitObject, JudgementResult result)
{
if (!result.HasResult || hitObject != drawableSpinner)
return;
// Trigger a miss result for remaining ticks to avoid infinite gameplay.
foreach (var tick in ticks.Where(t => !t.IsHit))
tick.TriggerResult(false);
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
drawableSpinner.OnNewResult -= onNewResult;
}
}
}