1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-06 07:42:55 +08:00

new Approach to approach rate

This commit is contained in:
Shawdooow 2017-12-31 11:15:14 -05:00
parent dc365bfc11
commit 3ba5dce052
9 changed files with 41 additions and 30 deletions

View File

@ -37,7 +37,6 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
private void applyStacking(Beatmap<OsuHitObject> beatmap) private void applyStacking(Beatmap<OsuHitObject> beatmap)
{ {
const int stack_distance = 3; const int stack_distance = 3;
float stackThreshold = DrawableOsuHitObject.TIME_PREEMPT * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f;
// Reset stacking // Reset stacking
for (int i = 0; i <= beatmap.HitObjects.Count - 1; i++) for (int i = 0; i <= beatmap.HitObjects.Count - 1; i++)
@ -58,6 +57,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
continue; continue;
double endTime = (stackBaseObject as IHasEndTime)?.EndTime ?? stackBaseObject.StartTime; double endTime = (stackBaseObject as IHasEndTime)?.EndTime ?? stackBaseObject.StartTime;
float stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f;
if (objectN.StartTime - endTime > stackThreshold) if (objectN.StartTime - endTime > stackThreshold)
//We are no longer within stacking range of the next object. //We are no longer within stacking range of the next object.
@ -112,6 +112,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
if (objectN is Spinner) continue; if (objectN is Spinner) continue;
double endTime = (objectN as IHasEndTime)?.EndTime ?? objectN.StartTime; double endTime = (objectN as IHasEndTime)?.EndTime ?? objectN.StartTime;
float stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f;
if (objectI.StartTime - endTime > stackThreshold) if (objectI.StartTime - endTime > stackThreshold)
//We are no longer within stacking range of the previous object. //We are no longer within stacking range of the previous object.
@ -165,6 +166,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
OsuHitObject objectN = beatmap.HitObjects[n]; OsuHitObject objectN = beatmap.HitObjects[n];
if (objectN is Spinner) continue; if (objectN is Spinner) continue;
float stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f;
if (objectI.StartTime - objectN.StartTime > stackThreshold) if (objectI.StartTime - objectN.StartTime > stackThreshold)
//We are no longer within stacking range of the previous object. //We are no longer within stacking range of the previous object.
break; break;

View File

@ -36,14 +36,12 @@ namespace osu.Game.Rulesets.Osu.Mods
private const double fade_in_duration_multiplier = 0.4; private const double fade_in_duration_multiplier = 0.4;
private const double fade_out_duration_multiplier = 0.3; private const double fade_out_duration_multiplier = 0.3;
private float preEmpt => DrawableOsuHitObject.TIME_PREEMPT;
public void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables) public void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables)
{ {
foreach (var d in drawables.OfType<DrawableOsuHitObject>()) foreach (var d in drawables.OfType<DrawableOsuHitObject>())
{ {
d.ApplyCustomUpdateState += ApplyHiddenState; d.ApplyCustomUpdateState += ApplyHiddenState;
d.FadeInDuration = preEmpt * fade_in_duration_multiplier; d.FadeInDuration = d.HitObject.TimePreempt * fade_in_duration_multiplier;
} }
} }
@ -52,8 +50,8 @@ namespace osu.Game.Rulesets.Osu.Mods
if (!(drawable is DrawableOsuHitObject d)) if (!(drawable is DrawableOsuHitObject d))
return; return;
var fadeOutStartTime = d.HitObject.StartTime - preEmpt + d.FadeInDuration; var fadeOutStartTime = d.HitObject.StartTime - d.HitObject.TimePreempt + d.FadeInDuration;
var fadeOutDuration = preEmpt * fade_out_duration_multiplier; var fadeOutDuration = d.HitObject.TimePreempt * fade_out_duration_multiplier;
// new duration from completed fade in to end (before fading out) // new duration from completed fade in to end (before fading out)
var longFadeDuration = ((d.HitObject as IHasEndTime)?.EndTime ?? d.HitObject.StartTime) - fadeOutStartTime; var longFadeDuration = ((d.HitObject as IHasEndTime)?.EndTime ?? d.HitObject.StartTime) - fadeOutStartTime;

View File

@ -96,12 +96,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
using (fp.BeginAbsoluteSequence(fadeInTime)) using (fp.BeginAbsoluteSequence(fadeInTime))
{ {
fp.FadeIn(DrawableOsuHitObject.TIME_FADEIN); fp.FadeIn(currHitObject.TimeFadein);
fp.ScaleTo(1, DrawableOsuHitObject.TIME_FADEIN, Easing.Out); fp.ScaleTo(1, currHitObject.TimeFadein, Easing.Out);
fp.MoveTo(pointEndPosition, DrawableOsuHitObject.TIME_FADEIN, Easing.Out); fp.MoveTo(pointEndPosition, currHitObject.TimeFadein, Easing.Out);
fp.Delay(fadeOutTime - fadeInTime).FadeOut(DrawableOsuHitObject.TIME_FADEIN); fp.Delay(fadeOutTime - fadeInTime).FadeOut(currHitObject.TimeFadein);
} }
fp.Expire(true); fp.Expire(true);

View File

@ -88,8 +88,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
base.UpdatePreemptState(); base.UpdatePreemptState();
ApproachCircle.FadeIn(Math.Min(FadeInDuration * 2, TIME_PREEMPT)); ApproachCircle.FadeIn(Math.Min(FadeInDuration * 2, HitObject.TimePreempt));
ApproachCircle.ScaleTo(1.1f, TIME_PREEMPT); ApproachCircle.ScaleTo(1.1f, HitObject.TimePreempt);
} }
protected override void UpdateCurrentState(ArmedState state) protected override void UpdateCurrentState(ArmedState state)
@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
switch (state) switch (state)
{ {
case ArmedState.Idle: case ArmedState.Idle:
this.Delay(TIME_PREEMPT).FadeOut(500); this.Delay(HitObject.TimePreempt).FadeOut(500);
Expire(true); Expire(true);

View File

@ -10,26 +10,25 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
public class DrawableOsuHitObject : DrawableHitObject<OsuHitObject> public class DrawableOsuHitObject : DrawableHitObject<OsuHitObject>
{ {
public const float TIME_PREEMPT = 600;
public const float TIME_FADEIN = 400;
/// <summary> /// <summary>
/// The number of milliseconds used to fade in. /// The number of milliseconds used to fade in.
/// </summary> /// </summary>
public virtual double FadeInDuration { get; set; } = TIME_FADEIN; public virtual double FadeInDuration { get; set; }
public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - TIME_PREEMPT; public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - HitObject.TimePreempt;
protected DrawableOsuHitObject(OsuHitObject hitObject) protected DrawableOsuHitObject(OsuHitObject hitObject)
: base(hitObject) : base(hitObject)
{ {
FadeInDuration = hitObject.TimeFadein;
AccentColour = HitObject.ComboColour; AccentColour = HitObject.ComboColour;
Alpha = 0; Alpha = 0;
} }
protected sealed override void UpdateState(ArmedState state) protected sealed override void UpdateState(ArmedState state)
{ {
double transformTime = HitObject.StartTime - TIME_PREEMPT; double transformTime = HitObject.StartTime - HitObject.TimePreempt;
base.ApplyTransformsAt(transformTime, true); base.ApplyTransformsAt(transformTime, true);
base.ClearTransformsAfter(transformTime, true); base.ClearTransformsAfter(transformTime, true);
@ -38,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
UpdatePreemptState(); UpdatePreemptState();
using (BeginDelayedSequence(TIME_PREEMPT + (Judgements.FirstOrDefault()?.TimeOffset ?? 0), true)) using (BeginDelayedSequence(HitObject.TimePreempt + (Judgements.FirstOrDefault()?.TimeOffset ?? 0), true))
UpdateCurrentState(state); UpdateCurrentState(state);
} }
} }

View File

@ -191,14 +191,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
base.UpdatePreemptState(); base.UpdatePreemptState();
circleContainer.ScaleTo(spinner.Scale * 0.3f); circleContainer.ScaleTo(spinner.Scale * 0.3f);
circleContainer.ScaleTo(spinner.Scale, TIME_PREEMPT / 1.4f, Easing.OutQuint); circleContainer.ScaleTo(spinner.Scale, HitObject.TimePreempt / 1.4f, Easing.OutQuint);
Disc.RotateTo(-720); Disc.RotateTo(-720);
symbol.RotateTo(-720); symbol.RotateTo(-720);
mainContainer mainContainer
.ScaleTo(0) .ScaleTo(0)
.ScaleTo(spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, TIME_PREEMPT - 150, Easing.OutQuint) .ScaleTo(spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, HitObject.TimePreempt - 150, Easing.OutQuint)
.Then() .Then()
.ScaleTo(1, 500, Easing.OutQuint); .ScaleTo(1, 500, Easing.OutQuint);
} }

View File

@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
public void UpdateProgress(double progress, int repeat) public void UpdateProgress(double progress, int repeat)
{ {
double start = 0; double start = 0;
double end = snakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - DrawableOsuHitObject.TIME_PREEMPT)) / DrawableOsuHitObject.TIME_FADEIN, 0, 1) : 1; double end = snakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / slider.TimeFadein, 0, 1) : 1;
if (repeat >= slider.RepeatCount - 1) if (repeat >= slider.RepeatCount - 1)
{ {

View File

@ -20,6 +20,9 @@ namespace osu.Game.Rulesets.Osu.Objects
private const double hit_window_100 = 80; private const double hit_window_100 = 80;
private const double hit_window_300 = 30; private const double hit_window_300 = 30;
public float TimePreempt = 600;
public float TimeFadein = 400;
public Vector2 Position { get; set; } public Vector2 Position { get; set; }
public float X => Position.X; public float X => Position.X;
public float Y => Position.Y; public float Y => Position.Y;
@ -72,6 +75,13 @@ namespace osu.Game.Rulesets.Osu.Objects
{ {
base.ApplyDefaultsToSelf(controlPointInfo, difficulty); base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
if (difficulty.ApproachRate >= 5)
TimePreempt = 1200 - (difficulty.ApproachRate - 5) * 150;
else
TimePreempt = 1800 - difficulty.ApproachRate * 120;
TimeFadein = TimePreempt / 3;
Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2; Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2;
} }
} }

View File

@ -9,6 +9,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
@ -133,7 +134,7 @@ namespace osu.Game.Rulesets.Osu.Replays
// Do some nice easing for cursor movements // Do some nice easing for cursor movements
if (Frames.Count > 0) if (Frames.Count > 0)
{ {
moveToHitObject(h.StartTime, startPosition, h.Radius, easing); moveToHitObject(h, startPosition, easing);
} }
// Add frames to click the hitobject // Add frames to click the hitobject
@ -191,12 +192,12 @@ namespace osu.Game.Rulesets.Osu.Replays
} }
} }
private void moveToHitObject(double targetTime, Vector2 targetPos, double hitObjectRadius, Easing easing) private void moveToHitObject(OsuHitObject h, Vector2 targetPos, Easing easing)
{ {
ReplayFrame lastFrame = Frames[Frames.Count - 1]; ReplayFrame lastFrame = Frames[Frames.Count - 1];
// Wait until Auto could "see and react" to the next note. // Wait until Auto could "see and react" to the next note.
double waitTime = targetTime - Math.Max(0.0, DrawableOsuHitObject.TIME_PREEMPT - reactionTime); double waitTime = h.StartTime - Math.Max(0.0, h.TimePreempt - reactionTime);
if (waitTime > lastFrame.Time) if (waitTime > lastFrame.Time)
{ {
lastFrame = new ReplayFrame(waitTime, lastFrame.MouseX, lastFrame.MouseY, lastFrame.ButtonState); lastFrame = new ReplayFrame(waitTime, lastFrame.MouseX, lastFrame.MouseY, lastFrame.ButtonState);
@ -205,17 +206,17 @@ namespace osu.Game.Rulesets.Osu.Replays
Vector2 lastPosition = lastFrame.Position; Vector2 lastPosition = lastFrame.Position;
double timeDifference = ApplyModsToTime(targetTime - lastFrame.Time); double timeDifference = ApplyModsToTime(h.StartTime - lastFrame.Time);
// Only "snap" to hitcircles if they are far enough apart. As the time between hitcircles gets shorter the snapping threshold goes up. // Only "snap" to hitcircles if they are far enough apart. As the time between hitcircles gets shorter the snapping threshold goes up.
if (timeDifference > 0 && // Sanity checks if (timeDifference > 0 && // Sanity checks
((lastPosition - targetPos).Length > hitObjectRadius * (1.5 + 100.0 / timeDifference) || // Either the distance is big enough ((lastPosition - targetPos).Length > h.Radius * (1.5 + 100.0 / timeDifference) || // Either the distance is big enough
timeDifference >= 266)) // ... or the beats are slow enough to tap anyway. timeDifference >= 266)) // ... or the beats are slow enough to tap anyway.
{ {
// Perform eased movement // Perform eased movement
for (double time = lastFrame.Time + FrameDelay; time < targetTime; time += FrameDelay) for (double time = lastFrame.Time + FrameDelay; time < h.StartTime; time += FrameDelay)
{ {
Vector2 currentPosition = Interpolation.ValueAt(time, lastPosition, targetPos, lastFrame.Time, targetTime, easing); Vector2 currentPosition = Interpolation.ValueAt(time, lastPosition, targetPos, lastFrame.Time, h.StartTime, easing);
AddFrameToReplay(new ReplayFrame((int)time, currentPosition.X, currentPosition.Y, lastFrame.ButtonState)); AddFrameToReplay(new ReplayFrame((int)time, currentPosition.X, currentPosition.Y, lastFrame.ButtonState));
} }