public void TestHoldNoteChord() { // | | | // | * | * | // | * | * | // | * | * | // | | | var beatmap = new CrossBeatmap(new StageDefinition { Columns = 2 }); beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 }); beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000, Column = 1 }); var generated = new CrossAutoGenerator(beatmap).Generate(); Assert.IsTrue(generated.Frames.Count == 3, "Replay must have 3 frames"); Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect hit time"); Assert.AreEqual(3000 + CrossAutoGenerator.RELEASE_DELAY, generated.Frames[2].Time, "Incorrect release time"); Assert.IsTrue(checkContains(generated.Frames[1], CrossAction.Key1, CrossAction.Key2), "Key1 & Key2 have not been pressed"); Assert.IsFalse(checkContains(generated.Frames[2], CrossAction.Key1, CrossAction.Key2), "Key1 & Key2 have not been released"); }
public CrossAutoGenerator(CrossBeatmap beatmap) : base(beatmap) { Replay = new Replay(); columnActions = new CrossAction[Beatmap.TotalColumns]; var normalAction = CrossAction.Key1; var specialAction = CrossAction.Special1; int totalCounter = 0; foreach (var stage in Beatmap.Stages) { for (int i = 0; i < stage.Columns; i++) { if (stage.IsSpecialColumn(i)) { columnActions[totalCounter] = specialAction++; } else { columnActions[totalCounter] = normalAction++; } totalCounter++; } } }
public void TestHoldNoteWithReleasePress() { // | | | // | * | - | // | * | | // | * | | // | | | var beatmap = new CrossBeatmap(new StageDefinition { Columns = 2 }); beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 - CrossAutoGenerator.RELEASE_DELAY }); beatmap.HitObjects.Add(new Note { StartTime = 3000, Column = 1 }); var generated = new CrossAutoGenerator(beatmap).Generate(); Assert.IsTrue(generated.Frames.Count == 4, "Replay must have 4 frames"); Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect first note hit time"); Assert.AreEqual(3000, generated.Frames[2].Time, "Incorrect second note press time + first note release time"); Assert.AreEqual(3000 + CrossAutoGenerator.RELEASE_DELAY, generated.Frames[3].Time, "Incorrect second note release time"); Assert.IsTrue(checkContains(generated.Frames[1], CrossAction.Key1), "Key1 has not been pressed"); Assert.IsFalse(checkContains(generated.Frames[2], CrossAction.Key1), "Key1 has not been released"); Assert.IsTrue(checkContains(generated.Frames[2], CrossAction.Key2), "Key2 has not been pressed"); Assert.IsFalse(checkContains(generated.Frames[3], CrossAction.Key2), "Key2 has not been released"); }
protected PatternGenerator(FastRandom random, HitObject hitObject, CrossBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) : base(hitObject, beatmap, previousPattern) { if (random == null) { throw new ArgumentNullException(nameof(random)); } if (originalBeatmap == null) { throw new ArgumentNullException(nameof(originalBeatmap)); } Random = random; OriginalBeatmap = originalBeatmap; RandomStart = TotalColumns == 8 ? 1 : 0; }
protected PatternGenerator(HitObject hitObject, CrossBeatmap beatmap, Pattern previousPattern) { if (hitObject == null) { throw new ArgumentNullException(nameof(hitObject)); } if (beatmap == null) { throw new ArgumentNullException(nameof(beatmap)); } if (previousPattern == null) { throw new ArgumentNullException(nameof(previousPattern)); } HitObject = hitObject; Beatmap = beatmap; PreviousPattern = previousPattern; TotalColumns = Beatmap.TotalColumns; }
public void TestSingleNote() { // | | // | - | // | | var beatmap = new CrossBeatmap(new StageDefinition { Columns = 1 }); beatmap.HitObjects.Add(new Note { StartTime = 1000 }); var generated = new CrossAutoGenerator(beatmap).Generate(); Assert.IsTrue(generated.Frames.Count == 3, "Replay must have 3 frames"); Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect hit time"); Assert.AreEqual(1000 + CrossAutoGenerator.RELEASE_DELAY, generated.Frames[2].Time, "Incorrect release time"); Assert.IsTrue(checkContains(generated.Frames[1], CrossAction.Special1), "Special1 has not been pressed"); Assert.IsFalse(checkContains(generated.Frames[2], CrossAction.Special1), "Special1 has not been released"); }
public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, CrossBeatmap beatmap, IBeatmap originalBeatmap) : base(random, hitObject, beatmap, new Pattern(), originalBeatmap) { endTime = (HitObject as IHasEndTime)?.EndTime ?? 0; }
public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, CrossBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap) { convertType = PatternType.None; if (!Beatmap.ControlPointInfo.EffectPointAt(hitObject.StartTime).KiaiMode) convertType = PatternType.LowProbability; var distanceData = hitObject as IHasDistance; var repeatsData = hitObject as IHasRepeats; spanCount = repeatsData?.SpanCount() ?? 1; TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); DifficultyControlPoint difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(hitObject.StartTime); // The true distance, accounting for any repeats double distance = (distanceData?.Distance ?? 0) * spanCount; // The velocity of the osu! hit object - calculated as the velocity of a slider double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier / timingPoint.BeatLength; // The duration of the osu! hit object double osuDuration = distance / osuVelocity; EndTime = hitObject.StartTime + osuDuration; SegmentDuration = (EndTime - HitObject.StartTime) / spanCount; }
public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, CrossBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair, IBeatmap originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap) { StairType = lastStair; TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); EffectControlPoint effectPoint = beatmap.ControlPointInfo.EffectPointAt(hitObject.StartTime); var positionData = hitObject as IHasPosition; float positionSeparation = ((positionData?.Position ?? Vector2.Zero) - previousPosition).Length; double timeSeparation = hitObject.StartTime - previousTime; if (timeSeparation <= 80) { // More than 187 BPM convertType |= PatternType.ForceNotStack | PatternType.KeepSingle; } else if (timeSeparation <= 95) { // More than 157 BPM convertType |= PatternType.ForceNotStack | PatternType.KeepSingle | lastStair; } else if (timeSeparation <= 105) { // More than 140 BPM convertType |= PatternType.ForceNotStack | PatternType.LowProbability; } else if (timeSeparation <= 125) { // More than 120 BPM convertType |= PatternType.ForceNotStack; } else if (timeSeparation <= 135 && positionSeparation < 20) { // More than 111 BPM stream convertType |= PatternType.Cycle | PatternType.KeepSingle; } else if (timeSeparation <= 150 && positionSeparation < 20) { // More than 100 BPM stream convertType |= PatternType.ForceStack | PatternType.LowProbability; } else if (positionSeparation < 20 && density >= timingPoint.BeatLength / 2.5) { // Low density stream convertType |= PatternType.Reverse | PatternType.LowProbability; } else if (density < timingPoint.BeatLength / 2.5 || effectPoint.KiaiMode) { // High density } else { convertType |= PatternType.LowProbability; } if (!convertType.HasFlag(PatternType.KeepSingle)) { if (HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH) && TotalColumns != 8) { convertType |= PatternType.Mirror; } else if (HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP)) { convertType |= PatternType.Gathered; } } }