protected override IEnumerable <DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) { float halfCatchWidth; using (var catcher = new CatcherArea.Catcher(beatmap.BeatmapInfo.BaseDifficulty)) { halfCatchWidth = catcher.CatchWidth * 0.5f; // We're only using 80% of the catcher's width to simulate imperfect gameplay, reduced further at circle sizes above 5.5 halfCatchWidth *= Math.Min(1.075f - (0.05f * beatmap.BeatmapInfo.BaseDifficulty.CircleSize), 0.8f); } CatchHitObject lastObject = null; // In 2B beatmaps, it is possible that a normal Fruit is placed in the middle of a JuiceStream. foreach (var hitObject in beatmap.HitObjects .SelectMany(obj => obj is JuiceStream stream ? stream.NestedHitObjects : new[] { obj }) .Cast <CatchHitObject>() .OrderBy(x => x.StartTime)) { // We want to only consider fruits that contribute to the combo. if (hitObject is BananaShower || hitObject is TinyDroplet) { continue; } if (lastObject != null) { yield return(new CatchDifficultyHitObject(hitObject, lastObject, clockRate, halfCatchWidth)); } lastObject = hitObject; } }
public CatchDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { var catcher = new CatcherArea.Catcher(beatmap.BeatmapInfo.BaseDifficulty); halfCatchWidth = catcher.CatchWidth * 0.5f; // We're only using 80% of the catcher's width to simulate imperfect gameplay. halfCatchWidth *= 0.8f; }
protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) { if (!beatmap.HitObjects.Any()) { return(new CatchDifficultyAttributes(mods, 0)); } var catcher = new CatcherArea.Catcher(beatmap.BeatmapInfo.BaseDifficulty); float halfCatchWidth = catcher.CatchWidth * 0.5f; var difficultyHitObjects = new List <CatchDifficultyHitObject>(); foreach (var hitObject in beatmap.HitObjects) { switch (hitObject) { // We want to only consider fruits that contribute to the combo. Droplets are addressed as accuracy and spinners are not relevant for "skill" calculations. case Fruit fruit: difficultyHitObjects.Add(new CatchDifficultyHitObject(fruit, halfCatchWidth)); break; case JuiceStream _: difficultyHitObjects.AddRange(hitObject.NestedHitObjects.OfType <CatchHitObject>().Where(o => !(o is TinyDroplet)).Select(o => new CatchDifficultyHitObject(o, halfCatchWidth))); break; } } difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); if (!calculateStrainValues(difficultyHitObjects, timeRate)) { return(new CatchDifficultyAttributes(mods, 0)); } // this is the same as osu!, so there's potential to share the implementation... maybe double preempt = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / timeRate; double starRating = Math.Sqrt(calculateDifficulty(difficultyHitObjects, timeRate)) * star_scaling_factor; return(new CatchDifficultyAttributes(mods, starRating) { ApproachRate = preempt > 1200.0 ? -(preempt - 1800.0) / 120.0 : -(preempt - 1200.0) / 150.0 + 5.0, MaxCombo = difficultyHitObjects.Count }); }
protected override IEnumerable <DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) { float halfCatchWidth; using (var catcher = new CatcherArea.Catcher(beatmap.BeatmapInfo.BaseDifficulty)) { halfCatchWidth = catcher.CatchWidth * 0.5f; halfCatchWidth *= 0.8f; // We're only using 80% of the catcher's width to simulate imperfect gameplay. } CatchHitObject lastObject = null; foreach (var hitObject in beatmap.HitObjects.OfType <CatchHitObject>()) { if (lastObject == null) { lastObject = hitObject; continue; } switch (hitObject) { // We want to only consider fruits that contribute to the combo. Droplets are addressed as accuracy and spinners are not relevant for "skill" calculations. case Fruit fruit: yield return(new CatchDifficultyHitObject(fruit, lastObject, clockRate, halfCatchWidth)); lastObject = hitObject; break; case JuiceStream _: foreach (var nested in hitObject.NestedHitObjects.OfType <CatchHitObject>().Where(o => !(o is TinyDroplet))) { yield return(new CatchDifficultyHitObject(nested, lastObject, clockRate, halfCatchWidth)); lastObject = nested; } break; } } }
public MouseInputHelper(CatchPlayfield playfield) { catcher = playfield.CatcherArea.MovableCatcher; RelativeSizeAxes = Axes.Both; }