mirror of
https://github.com/osukey/osukey.git
synced 2025-08-05 07:33:55 +09:00
Merge branch 'master' into update-branch
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
|
@ -1,11 +1,10 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
{
|
||||
@ -29,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count;
|
||||
}
|
||||
|
||||
obj.ComboIndex = comboIndex++;
|
||||
obj.IndexInCurrentCombo = comboIndex++;
|
||||
obj.ComboColour = beatmap.ComboColors[colourIndex];
|
||||
}
|
||||
}
|
||||
@ -37,7 +36,6 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
private void applyStacking(Beatmap<OsuHitObject> beatmap)
|
||||
{
|
||||
const int stack_distance = 3;
|
||||
float stackThreshold = DrawableOsuHitObject.TIME_PREEMPT * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f;
|
||||
|
||||
// Reset stacking
|
||||
for (int i = 0; i <= beatmap.HitObjects.Count - 1; i++)
|
||||
@ -58,6 +56,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
continue;
|
||||
|
||||
double endTime = (stackBaseObject as IHasEndTime)?.EndTime ?? stackBaseObject.StartTime;
|
||||
double stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f;
|
||||
|
||||
if (objectN.StartTime - endTime > stackThreshold)
|
||||
//We are no longer within stacking range of the next object.
|
||||
@ -100,6 +99,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
OsuHitObject objectI = beatmap.HitObjects[i];
|
||||
if (objectI.StackHeight != 0 || objectI is Spinner) continue;
|
||||
|
||||
double stackThreshold = objectI.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f;
|
||||
|
||||
/* If this object is a hitcircle, then we enter this "special" case.
|
||||
* It either ends with a stack of hitcircles only, or a stack of hitcircles that are underneath a slider.
|
||||
* Any other case is handled by the "is Slider" code below this.
|
||||
|
@ -1,15 +1,12 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
public class OsuEditPlayfield : OsuPlayfield
|
||||
{
|
||||
protected override CursorContainer CreateCursor() => null;
|
||||
|
||||
protected override bool ProxyApproachCircles => false;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
@ -15,5 +16,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
}
|
||||
|
||||
protected override Playfield CreatePlayfield() => new OsuEditPlayfield();
|
||||
|
||||
protected override CursorContainer CreateCursor() => null;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
|
13
osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs
Normal file
13
osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Judgements
|
||||
{
|
||||
public class OsuSliderTailJudgement : OsuJudgement
|
||||
{
|
||||
public override bool AffectsCombo => false;
|
||||
protected override int NumericResultFor(HitResult result) => 0;
|
||||
}
|
||||
}
|
@ -1,212 +0,0 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Osu.Replays;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModNoFail : ModNoFail
|
||||
{
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
|
||||
}
|
||||
|
||||
public class OsuModEasy : ModEasy
|
||||
{
|
||||
}
|
||||
|
||||
public class OsuModHidden : ModHidden, IApplicableToDrawableHitObjects
|
||||
{
|
||||
public override string Description => @"Play with no approach circles and fading notes for a slight score advantage.";
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
|
||||
private const double fade_in_duration_multiplier = 0.4;
|
||||
private const double fade_out_duration_multiplier = 0.3;
|
||||
|
||||
private float preEmpt => DrawableOsuHitObject.TIME_PREEMPT;
|
||||
|
||||
public void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables)
|
||||
{
|
||||
foreach (var d in drawables.OfType<DrawableOsuHitObject>())
|
||||
{
|
||||
d.ApplyCustomUpdateState += ApplyHiddenState;
|
||||
d.FadeInDuration = preEmpt * fade_in_duration_multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
protected void ApplyHiddenState(DrawableHitObject drawable, ArmedState state)
|
||||
{
|
||||
if (!(drawable is DrawableOsuHitObject d))
|
||||
return;
|
||||
|
||||
var fadeOutStartTime = d.HitObject.StartTime - preEmpt + d.FadeInDuration;
|
||||
var fadeOutDuration = preEmpt * fade_out_duration_multiplier;
|
||||
|
||||
// new duration from completed fade in to end (before fading out)
|
||||
var longFadeDuration = ((d.HitObject as IHasEndTime)?.EndTime ?? d.HitObject.StartTime) - fadeOutStartTime;
|
||||
|
||||
switch (drawable)
|
||||
{
|
||||
case DrawableHitCircle circle:
|
||||
// we don't want to see the approach circle
|
||||
circle.ApproachCircle.Hide();
|
||||
|
||||
// fade out immediately after fade in.
|
||||
using (drawable.BeginAbsoluteSequence(fadeOutStartTime, true))
|
||||
circle.FadeOut(fadeOutDuration);
|
||||
break;
|
||||
case DrawableSlider slider:
|
||||
using (slider.BeginAbsoluteSequence(fadeOutStartTime, true))
|
||||
{
|
||||
slider.Body.FadeOut(longFadeDuration, Easing.Out);
|
||||
|
||||
// delay a bit less to let the sliderball fade out peacefully instead of having a hard cut
|
||||
using (slider.BeginDelayedSequence(longFadeDuration - fadeOutDuration, true))
|
||||
slider.Ball.FadeOut(fadeOutDuration);
|
||||
}
|
||||
|
||||
break;
|
||||
case DrawableSpinner spinner:
|
||||
// hide elements we don't care about.
|
||||
spinner.Disc.Hide();
|
||||
spinner.Ticks.Hide();
|
||||
spinner.Background.Hide();
|
||||
|
||||
using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true))
|
||||
{
|
||||
spinner.FadeOut(fadeOutDuration);
|
||||
|
||||
// speed up the end sequence accordingly
|
||||
switch (state)
|
||||
{
|
||||
case ArmedState.Hit:
|
||||
spinner.ScaleTo(spinner.Scale * 1.2f, fadeOutDuration * 2, Easing.Out);
|
||||
break;
|
||||
case ArmedState.Miss:
|
||||
spinner.ScaleTo(spinner.Scale * 0.8f, fadeOutDuration * 2, Easing.In);
|
||||
break;
|
||||
}
|
||||
|
||||
spinner.Expire();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class OsuModHardRock : ModHardRock, IApplicableToHitObject<OsuHitObject>
|
||||
{
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToHitObject(OsuHitObject hitObject)
|
||||
{
|
||||
hitObject.Position = new Vector2(hitObject.Position.X, OsuPlayfield.BASE_SIZE.Y - hitObject.Y);
|
||||
|
||||
var slider = hitObject as Slider;
|
||||
if (slider == null)
|
||||
return;
|
||||
|
||||
var newControlPoints = new List<Vector2>();
|
||||
slider.ControlPoints.ForEach(c => newControlPoints.Add(new Vector2(c.X, OsuPlayfield.BASE_SIZE.Y - c.Y)));
|
||||
|
||||
slider.ControlPoints = newControlPoints;
|
||||
slider.Curve?.Calculate(); // Recalculate the slider curve
|
||||
}
|
||||
}
|
||||
|
||||
public class OsuModSuddenDeath : ModSuddenDeath
|
||||
{
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
|
||||
}
|
||||
|
||||
public class OsuModDaycore : ModDaycore
|
||||
{
|
||||
public override double ScoreMultiplier => 0.5;
|
||||
}
|
||||
|
||||
public class OsuModDoubleTime : ModDoubleTime
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
}
|
||||
|
||||
public class OsuModRelax : ModRelax
|
||||
{
|
||||
public override string Description => "You don't need to click.\nGive your clicking/tapping finger a break from the heat of things.";
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
|
||||
}
|
||||
|
||||
public class OsuModHalfTime : ModHalfTime
|
||||
{
|
||||
public override double ScoreMultiplier => 0.5;
|
||||
}
|
||||
|
||||
public class OsuModNightcore : ModNightcore
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
}
|
||||
|
||||
public class OsuModFlashlight : ModFlashlight
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
}
|
||||
|
||||
public class OsuModPerfect : ModPerfect
|
||||
{
|
||||
}
|
||||
|
||||
public class OsuModSpunOut : Mod
|
||||
{
|
||||
public override string Name => "Spun Out";
|
||||
public override string ShortenedName => "SO";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout;
|
||||
public override string Description => @"Spinners will be automatically completed";
|
||||
public override double ScoreMultiplier => 0.9;
|
||||
public override bool Ranked => true;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(OsuModAutopilot) };
|
||||
}
|
||||
|
||||
public class OsuModAutopilot : Mod
|
||||
{
|
||||
public override string Name => "Autopilot";
|
||||
public override string ShortenedName => "AP";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot;
|
||||
public override string Description => @"Automatic cursor movement - just follow the rhythm.";
|
||||
public override double ScoreMultiplier => 0;
|
||||
public override bool Ranked => false;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) };
|
||||
}
|
||||
|
||||
public class OsuModAutoplay : ModAutoplay<OsuHitObject>
|
||||
{
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot), typeof(OsuModSpunOut) }).ToArray();
|
||||
|
||||
protected override Score CreateReplayScore(Beatmap<OsuHitObject> beatmap) => new Score
|
||||
{
|
||||
Replay = new OsuAutoGenerator(beatmap).Generate()
|
||||
};
|
||||
}
|
||||
|
||||
public class OsuModTarget : Mod
|
||||
{
|
||||
public override string Name => "Target";
|
||||
public override string ShortenedName => "TP";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_target;
|
||||
public override string Description => @"";
|
||||
public override double ScoreMultiplier => 1;
|
||||
}
|
||||
}
|
20
osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs
Normal file
20
osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModAutopilot : Mod
|
||||
{
|
||||
public override string Name => "Autopilot";
|
||||
public override string ShortenedName => "AP";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot;
|
||||
public override string Description => @"Automatic cursor movement - just follow the rhythm.";
|
||||
public override double ScoreMultiplier => 0;
|
||||
public override bool Ranked => false;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) };
|
||||
}
|
||||
}
|
26
osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs
Normal file
26
osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Replays;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModAutoplay : ModAutoplay<OsuHitObject>
|
||||
{
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot), typeof(OsuModSpunOut) }).ToArray();
|
||||
|
||||
protected override Score CreateReplayScore(Beatmap<OsuHitObject> beatmap)
|
||||
{
|
||||
return new Score
|
||||
{
|
||||
Replay = new OsuAutoGenerator(beatmap).Generate()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
12
osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs
Normal file
12
osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModDaycore : ModDaycore
|
||||
{
|
||||
public override double ScoreMultiplier => 0.5;
|
||||
}
|
||||
}
|
12
osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs
Normal file
12
osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModDoubleTime : ModDoubleTime
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
}
|
||||
}
|
11
osu.Game.Rulesets.Osu/Mods/OsuModEasy.cs
Normal file
11
osu.Game.Rulesets.Osu/Mods/OsuModEasy.cs
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModEasy : ModEasy
|
||||
{
|
||||
}
|
||||
}
|
12
osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs
Normal file
12
osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModFlashlight : ModFlashlight
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
}
|
||||
}
|
12
osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs
Normal file
12
osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModHalfTime : ModHalfTime
|
||||
{
|
||||
public override double ScoreMultiplier => 0.5;
|
||||
}
|
||||
}
|
32
osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs
Normal file
32
osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModHardRock : ModHardRock, IApplicableToHitObject<OsuHitObject>
|
||||
{
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToHitObject(OsuHitObject hitObject)
|
||||
{
|
||||
hitObject.Position = new Vector2(hitObject.Position.X, OsuPlayfield.BASE_SIZE.Y - hitObject.Y);
|
||||
|
||||
var slider = hitObject as Slider;
|
||||
if (slider == null)
|
||||
return;
|
||||
|
||||
var newControlPoints = new List<Vector2>();
|
||||
slider.ControlPoints.ForEach(c => newControlPoints.Add(new Vector2(c.X, OsuPlayfield.BASE_SIZE.Y - c.Y)));
|
||||
|
||||
slider.ControlPoints = newControlPoints;
|
||||
slider.Curve?.Calculate(); // Recalculate the slider curve
|
||||
}
|
||||
}
|
||||
}
|
77
osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs
Normal file
77
osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModHidden : ModHidden, IApplicableToDrawableHitObjects
|
||||
{
|
||||
public override string Description => @"Play with no approach circles and fading notes for a slight score advantage.";
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
|
||||
private const double fade_in_duration_multiplier = 0.4;
|
||||
private const double fade_out_duration_multiplier = 0.3;
|
||||
|
||||
public void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables)
|
||||
{
|
||||
foreach (var d in drawables.OfType<DrawableOsuHitObject>())
|
||||
{
|
||||
d.ApplyCustomUpdateState += ApplyHiddenState;
|
||||
d.HitObject.TimeFadein = d.HitObject.TimePreempt * fade_in_duration_multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
protected void ApplyHiddenState(DrawableHitObject drawable, ArmedState state)
|
||||
{
|
||||
if (!(drawable is DrawableOsuHitObject d))
|
||||
return;
|
||||
|
||||
var fadeOutStartTime = d.HitObject.StartTime - d.HitObject.TimePreempt + d.HitObject.TimeFadein;
|
||||
var fadeOutDuration = d.HitObject.TimePreempt * fade_out_duration_multiplier;
|
||||
|
||||
// new duration from completed fade in to end (before fading out)
|
||||
var longFadeDuration = ((d.HitObject as IHasEndTime)?.EndTime ?? d.HitObject.StartTime) - fadeOutStartTime;
|
||||
|
||||
switch (drawable)
|
||||
{
|
||||
case DrawableHitCircle circle:
|
||||
// we don't want to see the approach circle
|
||||
circle.ApproachCircle.Hide();
|
||||
|
||||
// fade out immediately after fade in.
|
||||
using (drawable.BeginAbsoluteSequence(fadeOutStartTime, true))
|
||||
{
|
||||
circle.FadeOut(fadeOutDuration);
|
||||
}
|
||||
|
||||
break;
|
||||
case DrawableSlider slider:
|
||||
using (slider.BeginAbsoluteSequence(fadeOutStartTime, true))
|
||||
{
|
||||
slider.Body.FadeOut(longFadeDuration, Easing.Out);
|
||||
}
|
||||
|
||||
break;
|
||||
case DrawableSpinner spinner:
|
||||
// hide elements we don't care about.
|
||||
spinner.Disc.Hide();
|
||||
spinner.Ticks.Hide();
|
||||
spinner.Background.Hide();
|
||||
|
||||
using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true))
|
||||
{
|
||||
spinner.FadeOut(fadeOutDuration);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs
Normal file
12
osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModNightcore : ModNightcore
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
}
|
||||
}
|
14
osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs
Normal file
14
osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModNoFail : ModNoFail
|
||||
{
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
|
||||
}
|
||||
}
|
11
osu.Game.Rulesets.Osu/Mods/OsuModPerfect.cs
Normal file
11
osu.Game.Rulesets.Osu/Mods/OsuModPerfect.cs
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModPerfect : ModPerfect
|
||||
{
|
||||
}
|
||||
}
|
15
osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs
Normal file
15
osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModRelax : ModRelax
|
||||
{
|
||||
public override string Description => "You don't need to click.\nGive your clicking/tapping finger a break from the heat of things.";
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
|
||||
}
|
||||
}
|
20
osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs
Normal file
20
osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModSpunOut : Mod
|
||||
{
|
||||
public override string Name => "Spun Out";
|
||||
public override string ShortenedName => "SO";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout;
|
||||
public override string Description => @"Spinners will be automatically completed";
|
||||
public override double ScoreMultiplier => 0.9;
|
||||
public override bool Ranked => true;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(OsuModAutopilot) };
|
||||
}
|
||||
}
|
14
osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs
Normal file
14
osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModSuddenDeath : ModSuddenDeath
|
||||
{
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
|
||||
}
|
||||
}
|
17
osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs
Normal file
17
osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModTarget : Mod
|
||||
{
|
||||
public override string Name => "Target";
|
||||
public override string ShortenedName => "TP";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_target;
|
||||
public override string Description => @"";
|
||||
public override double ScoreMultiplier => 1;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
@ -96,12 +96,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
|
||||
using (fp.BeginAbsoluteSequence(fadeInTime))
|
||||
{
|
||||
fp.FadeIn(DrawableOsuHitObject.TIME_FADEIN);
|
||||
fp.ScaleTo(1, DrawableOsuHitObject.TIME_FADEIN, Easing.Out);
|
||||
fp.FadeIn(currHitObject.TimeFadein);
|
||||
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);
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
},
|
||||
number = new NumberPiece
|
||||
{
|
||||
Text = (HitObject.ComboIndex + 1).ToString(),
|
||||
Text = (HitObject.IndexInCurrentCombo + 1).ToString(),
|
||||
},
|
||||
ring = new RingPiece(),
|
||||
flash = new FlashPiece(),
|
||||
@ -72,14 +72,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
if (!userTriggered)
|
||||
{
|
||||
if (timeOffset > HitObject.HitWindowFor(HitResult.Meh))
|
||||
if (!HitObject.HitWindows.CanBeHit(timeOffset))
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Miss });
|
||||
return;
|
||||
}
|
||||
|
||||
var result = HitObject.HitWindows.ResultFor(timeOffset);
|
||||
if (result == HitResult.None)
|
||||
return;
|
||||
|
||||
AddJudgement(new OsuJudgement
|
||||
{
|
||||
Result = HitObject.ScoreResultForOffset(Math.Abs(timeOffset)),
|
||||
Result = result,
|
||||
PositionOffset = Vector2.Zero //todo: set to correct value
|
||||
});
|
||||
}
|
||||
@ -88,8 +92,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
base.UpdatePreemptState();
|
||||
|
||||
ApproachCircle.FadeIn(Math.Min(FadeInDuration * 2, TIME_PREEMPT));
|
||||
ApproachCircle.ScaleTo(1.1f, TIME_PREEMPT);
|
||||
ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadein * 2, HitObject.TimePreempt));
|
||||
ApproachCircle.ScaleTo(1.1f, HitObject.TimePreempt);
|
||||
}
|
||||
|
||||
protected override void UpdateCurrentState(ArmedState state)
|
||||
@ -99,12 +103,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
switch (state)
|
||||
{
|
||||
case ArmedState.Idle:
|
||||
this.Delay(TIME_PREEMPT).FadeOut(500);
|
||||
this.Delay(HitObject.TimePreempt).FadeOut(500);
|
||||
|
||||
Expire(true);
|
||||
|
||||
// override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early.
|
||||
LifetimeEnd = HitObject.StartTime + HitObject.HitWindowFor(HitResult.Miss);
|
||||
LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.HalfWindowFor(HitResult.Miss);
|
||||
break;
|
||||
case ArmedState.Miss:
|
||||
ApproachCircle.FadeOut(50);
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.ComponentModel;
|
||||
@ -10,15 +10,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
public class DrawableOsuHitObject : DrawableHitObject<OsuHitObject>
|
||||
{
|
||||
public const float TIME_PREEMPT = 600;
|
||||
public const float TIME_FADEIN = 400;
|
||||
|
||||
/// <summary>
|
||||
/// The number of milliseconds used to fade in.
|
||||
/// </summary>
|
||||
public virtual double FadeInDuration { get; set; } = TIME_FADEIN;
|
||||
|
||||
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)
|
||||
: base(hitObject)
|
||||
@ -29,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
protected sealed override void UpdateState(ArmedState state)
|
||||
{
|
||||
double transformTime = HitObject.StartTime - TIME_PREEMPT;
|
||||
double transformTime = HitObject.StartTime - HitObject.TimePreempt;
|
||||
|
||||
base.ApplyTransformsAt(transformTime, true);
|
||||
base.ClearTransformsAfter(transformTime, true);
|
||||
@ -38,12 +30,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
UpdatePreemptState();
|
||||
|
||||
using (BeginDelayedSequence(TIME_PREEMPT + (Judgements.FirstOrDefault()?.TimeOffset ?? 0), true))
|
||||
using (BeginDelayedSequence(HitObject.TimePreempt + (Judgements.FirstOrDefault()?.TimeOffset ?? 0), true))
|
||||
UpdateCurrentState(state);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void UpdatePreemptState() => this.FadeIn(FadeInDuration);
|
||||
protected virtual void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadein);
|
||||
|
||||
protected virtual void UpdateCurrentState(ArmedState state)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
|
@ -1,7 +1,8 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using OpenTK;
|
||||
@ -11,13 +12,12 @@ using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
public class DrawableRepeatPoint : DrawableOsuHitObject
|
||||
public class DrawableRepeatPoint : DrawableOsuHitObject, ITrackSnaking
|
||||
{
|
||||
private readonly RepeatPoint repeatPoint;
|
||||
private readonly DrawableSlider drawableSlider;
|
||||
|
||||
public double FadeInTime;
|
||||
public double FadeOutTime;
|
||||
private double animDuration;
|
||||
|
||||
public DrawableRepeatPoint(RepeatPoint repeatPoint, DrawableSlider drawableSlider)
|
||||
: base(repeatPoint)
|
||||
@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
this.repeatPoint = repeatPoint;
|
||||
this.drawableSlider = drawableSlider;
|
||||
|
||||
Size = new Vector2(32 * repeatPoint.Scale);
|
||||
Size = new Vector2(45 * repeatPoint.Scale);
|
||||
|
||||
Blending = BlendingMode.Additive;
|
||||
Origin = Anchor.Centre;
|
||||
@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
new SpriteIcon
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Icon = FontAwesome.fa_eercast
|
||||
Icon = FontAwesome.fa_chevron_right
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -48,11 +48,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
protected override void UpdatePreemptState()
|
||||
{
|
||||
var animIn = Math.Min(150, repeatPoint.StartTime - FadeInTime);
|
||||
animDuration = Math.Min(150, repeatPoint.SpanDuration / 2);
|
||||
|
||||
this.FadeIn(animIn).ScaleTo(1.2f, animIn)
|
||||
.Then()
|
||||
.ScaleTo(1, 150, Easing.Out);
|
||||
this.Animate(
|
||||
d => d.FadeIn(animDuration),
|
||||
d => d.ScaleTo(0.5f).ScaleTo(1f, animDuration * 4, Easing.OutElasticHalf)
|
||||
);
|
||||
}
|
||||
|
||||
protected override void UpdateCurrentState(ArmedState state)
|
||||
@ -60,16 +61,40 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
switch (state)
|
||||
{
|
||||
case ArmedState.Idle:
|
||||
this.Delay(FadeOutTime - repeatPoint.StartTime).FadeOut();
|
||||
this.Delay(HitObject.TimePreempt).FadeOut();
|
||||
break;
|
||||
case ArmedState.Miss:
|
||||
this.FadeOut(160);
|
||||
this.FadeOut(animDuration);
|
||||
break;
|
||||
case ArmedState.Hit:
|
||||
this.FadeOut(120, Easing.OutQuint)
|
||||
.ScaleTo(Scale * 1.5f, 120, Easing.OutQuint);
|
||||
this.FadeOut(animDuration, Easing.OutQuint)
|
||||
.ScaleTo(Scale * 1.5f, animDuration, Easing.Out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateSnakingPosition(Vector2 start, Vector2 end)
|
||||
{
|
||||
bool isRepeatAtEnd = repeatPoint.RepeatIndex % 2 == 0;
|
||||
List<Vector2> curve = drawableSlider.Body.CurrentCurve;
|
||||
|
||||
Position = isRepeatAtEnd ? end : start;
|
||||
|
||||
if (curve.Count < 2)
|
||||
return;
|
||||
|
||||
int searchStart = isRepeatAtEnd ? curve.Count - 1 : 0;
|
||||
int direction = isRepeatAtEnd ? -1 : 1;
|
||||
|
||||
// find the next vector2 in the curve which is not equal to our current position to infer a rotation.
|
||||
for (int i = searchStart; i >= 0 && i < curve.Count; i += direction)
|
||||
{
|
||||
if (curve[i] == Position)
|
||||
continue;
|
||||
|
||||
Rotation = MathHelper.RadiansToDegrees((float)Math.Atan2(curve[i].Y - Position.Y, curve[i].X - Position.X));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
@ -10,6 +10,7 @@ using System.Linq;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
@ -17,14 +18,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
public class DrawableSlider : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach
|
||||
{
|
||||
private readonly Slider slider;
|
||||
private readonly List<Drawable> components = new List<Drawable>();
|
||||
|
||||
public readonly DrawableHitCircle InitialCircle;
|
||||
|
||||
private readonly List<ISliderProgress> components = new List<ISliderProgress>();
|
||||
|
||||
private readonly Container<DrawableSliderTick> ticks;
|
||||
private readonly Container<DrawableRepeatPoint> repeatPoints;
|
||||
|
||||
public readonly DrawableHitCircle HeadCircle;
|
||||
public readonly SliderBody Body;
|
||||
public readonly SliderBall Ball;
|
||||
|
||||
@ -33,6 +29,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
slider = s;
|
||||
|
||||
DrawableSliderTail tail;
|
||||
Container<DrawableSliderTick> ticks;
|
||||
Container<DrawableRepeatPoint> repeatPoints;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Body = new SliderBody(s)
|
||||
@ -50,68 +50,46 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0
|
||||
},
|
||||
InitialCircle = new DrawableHitCircle(new HitCircle
|
||||
{
|
||||
StartTime = s.StartTime,
|
||||
Position = s.StackedPosition,
|
||||
ComboIndex = s.ComboIndex,
|
||||
Scale = s.Scale,
|
||||
ComboColour = s.ComboColour,
|
||||
Samples = s.Samples,
|
||||
SampleControlPoint = s.SampleControlPoint
|
||||
})
|
||||
HeadCircle = new DrawableHitCircle(s.HeadCircle),
|
||||
tail = new DrawableSliderTail(s.TailCircle)
|
||||
};
|
||||
|
||||
components.Add(Body);
|
||||
components.Add(Ball);
|
||||
|
||||
AddNested(InitialCircle);
|
||||
AddNested(HeadCircle);
|
||||
|
||||
AddNested(tail);
|
||||
components.Add(tail);
|
||||
|
||||
var repeatDuration = s.Curve.Distance / s.Velocity;
|
||||
foreach (var tick in s.NestedHitObjects.OfType<SliderTick>())
|
||||
{
|
||||
var repeatStartTime = s.StartTime + tick.RepeatIndex * repeatDuration;
|
||||
var fadeInTime = repeatStartTime + (tick.StartTime - repeatStartTime) / 2 - (tick.RepeatIndex == 0 ? FadeInDuration : FadeInDuration / 2);
|
||||
var fadeOutTime = repeatStartTime + repeatDuration;
|
||||
|
||||
var drawableTick = new DrawableSliderTick(tick)
|
||||
{
|
||||
FadeInTime = fadeInTime,
|
||||
FadeOutTime = fadeOutTime,
|
||||
Position = tick.Position,
|
||||
Position = tick.Position
|
||||
};
|
||||
|
||||
ticks.Add(drawableTick);
|
||||
components.Add(drawableTick);
|
||||
AddNested(drawableTick);
|
||||
}
|
||||
|
||||
foreach (var repeatPoint in s.NestedHitObjects.OfType<RepeatPoint>())
|
||||
{
|
||||
var repeatStartTime = s.StartTime + repeatPoint.RepeatIndex * repeatDuration;
|
||||
var fadeInTime = repeatStartTime + (repeatPoint.StartTime - repeatStartTime) / 2 - (repeatPoint.RepeatIndex == 0 ? FadeInDuration : FadeInDuration / 2);
|
||||
var fadeOutTime = repeatStartTime + repeatDuration;
|
||||
|
||||
var drawableRepeatPoint = new DrawableRepeatPoint(repeatPoint, this)
|
||||
{
|
||||
FadeInTime = fadeInTime,
|
||||
FadeOutTime = fadeOutTime,
|
||||
Position = repeatPoint.Position,
|
||||
Position = repeatPoint.Position
|
||||
};
|
||||
|
||||
repeatPoints.Add(drawableRepeatPoint);
|
||||
components.Add(drawableRepeatPoint);
|
||||
AddNested(drawableRepeatPoint);
|
||||
}
|
||||
}
|
||||
|
||||
private int currentRepeat;
|
||||
private int currentSpan;
|
||||
public bool Tracking;
|
||||
|
||||
public override double FadeInDuration
|
||||
{
|
||||
get { return base.FadeInDuration; }
|
||||
set { InitialCircle.FadeInDuration = base.FadeInDuration = value; }
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
@ -120,33 +98,32 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
double progress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
|
||||
|
||||
int repeat = slider.RepeatAt(progress);
|
||||
int span = slider.SpanAt(progress);
|
||||
progress = slider.ProgressAt(progress);
|
||||
|
||||
if (repeat > currentRepeat)
|
||||
currentRepeat = repeat;
|
||||
if (span > currentSpan)
|
||||
currentSpan = span;
|
||||
|
||||
//todo: we probably want to reconsider this before adding scoring, but it looks and feels nice.
|
||||
if (!InitialCircle.Judgements.Any(j => j.IsHit))
|
||||
InitialCircle.Position = slider.Curve.PositionAt(progress);
|
||||
if (!HeadCircle.IsHit)
|
||||
HeadCircle.Position = slider.Curve.PositionAt(progress);
|
||||
|
||||
foreach (var c in components) c.UpdateProgress(progress, repeat);
|
||||
foreach (var t in ticks.Children) t.Tracking = Ball.Tracking;
|
||||
foreach (var c in components.OfType<ISliderProgress>()) c.UpdateProgress(progress, span);
|
||||
foreach (var c in components.OfType<ITrackSnaking>()) c.UpdateSnakingPosition(slider.Curve.PositionAt(Body.SnakedStart ?? 0), slider.Curve.PositionAt(Body.SnakedEnd ?? 0));
|
||||
foreach (var t in components.OfType<IRequireTracking>()) t.Tracking = Ball.Tracking;
|
||||
}
|
||||
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (!userTriggered && Time.Current >= slider.EndTime)
|
||||
{
|
||||
var judgementsCount = ticks.Children.Count + repeatPoints.Children.Count + 1;
|
||||
var judgementsHit = ticks.Children.Count(t => t.Judgements.Any(j => j.IsHit)) + repeatPoints.Children.Count(t => t.Judgements.Any(j => j.IsHit));
|
||||
if (InitialCircle.Judgements.Any(j => j.IsHit))
|
||||
judgementsHit++;
|
||||
var judgementsCount = NestedHitObjects.Count;
|
||||
var judgementsHit = NestedHitObjects.Count(h => h.IsHit);
|
||||
|
||||
var hitFraction = (double)judgementsHit / judgementsCount;
|
||||
if (hitFraction == 1 && InitialCircle.Judgements.Any(j => j.Result == HitResult.Great))
|
||||
if (hitFraction == 1 && HeadCircle.Judgements.Any(j => j.Result == HitResult.Great))
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Great });
|
||||
else if (hitFraction >= 0.5 && InitialCircle.Judgements.Any(j => j.Result >= HitResult.Good))
|
||||
else if (hitFraction >= 0.5 && HeadCircle.Judgements.Any(j => j.Result >= HitResult.Good))
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Good });
|
||||
else if (hitFraction > 0)
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Meh });
|
||||
@ -178,7 +155,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
public Drawable ProxiedLayer => InitialCircle.ApproachCircle;
|
||||
public Drawable ProxiedLayer => HeadCircle.ApproachCircle;
|
||||
|
||||
public override Vector2 SelectionPoint => ToScreenSpace(Body.Position);
|
||||
public override Quad SelectionQuad => Body.PathDrawQuad;
|
||||
|
@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking
|
||||
{
|
||||
/// <summary>
|
||||
/// The judgement text is provided by the <see cref="DrawableSlider"/>.
|
||||
/// </summary>
|
||||
public override bool DisplayJudgement => false;
|
||||
|
||||
public bool Tracking { get; set; }
|
||||
|
||||
public DrawableSliderTail(HitCircle hitCircle)
|
||||
: base(hitCircle)
|
||||
{
|
||||
AlwaysPresent = true;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (!userTriggered && timeOffset >= 0)
|
||||
AddJudgement(new OsuSliderTailJudgement { Result = Tracking ? HitResult.Great : HitResult.Miss });
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using OpenTK;
|
||||
@ -12,21 +11,16 @@ using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
public class DrawableSliderTick : DrawableOsuHitObject
|
||||
public class DrawableSliderTick : DrawableOsuHitObject, IRequireTracking
|
||||
{
|
||||
private readonly SliderTick sliderTick;
|
||||
private const double anim_duration = 150;
|
||||
|
||||
public double FadeInTime;
|
||||
public double FadeOutTime;
|
||||
|
||||
public bool Tracking;
|
||||
public bool Tracking { get; set; }
|
||||
|
||||
public override bool DisplayJudgement => false;
|
||||
|
||||
public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick)
|
||||
{
|
||||
this.sliderTick = sliderTick;
|
||||
|
||||
Size = new Vector2(16) * sliderTick.Scale;
|
||||
|
||||
Masking = true;
|
||||
@ -56,13 +50,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
protected override void UpdatePreemptState()
|
||||
{
|
||||
var animIn = Math.Min(150, sliderTick.StartTime - FadeInTime);
|
||||
|
||||
this.Animate(
|
||||
d => d.FadeIn(animIn),
|
||||
d => d.ScaleTo(0.5f).ScaleTo(1.2f, animIn)
|
||||
).Then(
|
||||
d => d.ScaleTo(1, 150, Easing.Out)
|
||||
d => d.FadeIn(anim_duration),
|
||||
d => d.ScaleTo(0.5f).ScaleTo(1f, anim_duration * 4, Easing.OutElasticHalf)
|
||||
);
|
||||
}
|
||||
|
||||
@ -71,15 +61,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
switch (state)
|
||||
{
|
||||
case ArmedState.Idle:
|
||||
this.Delay(FadeOutTime - sliderTick.StartTime).FadeOut();
|
||||
this.Delay(HitObject.TimePreempt).FadeOut();
|
||||
break;
|
||||
case ArmedState.Miss:
|
||||
this.FadeOut(160)
|
||||
.FadeColour(Color4.Red, 80);
|
||||
this.FadeOut(anim_duration)
|
||||
.FadeColour(Color4.Red, anim_duration / 2);
|
||||
break;
|
||||
case ArmedState.Hit:
|
||||
this.FadeOut(120, Easing.OutQuint)
|
||||
.ScaleTo(Scale * 1.5f, 120, Easing.OutQuint);
|
||||
this.FadeOut(anim_duration, Easing.OutQuint)
|
||||
.ScaleTo(Scale * 1.5f, anim_duration, Easing.Out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
Disc.Tracking = OsuActionInputManager.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton);
|
||||
if (!spmCounter.IsPresent && Disc.Tracking)
|
||||
spmCounter.FadeIn(FadeInDuration);
|
||||
spmCounter.FadeIn(HitObject.TimeFadein);
|
||||
|
||||
base.Update();
|
||||
}
|
||||
@ -191,14 +191,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
base.UpdatePreemptState();
|
||||
|
||||
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);
|
||||
symbol.RotateTo(-720);
|
||||
|
||||
mainContainer
|
||||
.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()
|
||||
.ScaleTo(1, 500, Easing.OutQuint);
|
||||
}
|
||||
|
13
osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs
Normal file
13
osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
public interface IRequireTracking
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether the <see cref="DrawableSlider"/> is currently being tracked by the user.
|
||||
/// </summary>
|
||||
bool Tracking { get; set; }
|
||||
}
|
||||
}
|
15
osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs
Normal file
15
osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
/// <summary>
|
||||
/// A component which tracks the current end snaking position of a slider.
|
||||
/// </summary>
|
||||
public interface ITrackSnaking
|
||||
{
|
||||
void UpdateSnakingPosition(Vector2 start, Vector2 end);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
@ -32,4 +32,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
approachCircle.Texture = textures.Get(@"Play/osu/approachcircle");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
@ -63,4 +63,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
|
||||
public bool OnReleased(OsuAction action) => false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
@ -30,4 +30,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
@ -32,4 +32,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
@ -36,4 +36,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
layer.Texture = textures.Get(@"Play/osu/ring-glow");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
@ -56,4 +56,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
@ -35,4 +35,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
@ -139,7 +139,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateProgress(double progress, int repeat)
|
||||
public void UpdateProgress(double progress, int span)
|
||||
{
|
||||
Position = slider.Curve.PositionAt(progress);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
@ -15,6 +15,7 @@ using OpenTK;
|
||||
using OpenTK.Graphics.ES30;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
@ -88,7 +89,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
// We want the container to have the same size as the slider,
|
||||
// and to be positioned such that the slider head is at (0,0).
|
||||
container.Size = path.Size;
|
||||
container.Position = -path.PositionInBoundingBox(slider.Curve.PositionAt(0) - currentCurve[0]);
|
||||
container.Position = -path.PositionInBoundingBox(slider.Curve.PositionAt(0) - CurrentCurve[0]);
|
||||
|
||||
container.ForceRedraw();
|
||||
}
|
||||
@ -147,7 +148,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
path.Texture = texture;
|
||||
}
|
||||
|
||||
private readonly List<Vector2> currentCurve = new List<Vector2>();
|
||||
public readonly List<Vector2> CurrentCurve = new List<Vector2>();
|
||||
private bool updateSnaking(double p0, double p1)
|
||||
{
|
||||
if (SnakedStart == p0 && SnakedEnd == p1) return false;
|
||||
@ -155,23 +156,23 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
SnakedStart = p0;
|
||||
SnakedEnd = p1;
|
||||
|
||||
slider.Curve.GetPathToProgress(currentCurve, p0, p1);
|
||||
slider.Curve.GetPathToProgress(CurrentCurve, p0, p1);
|
||||
|
||||
path.ClearVertices();
|
||||
foreach (Vector2 p in currentCurve)
|
||||
path.AddVertex(p - currentCurve[0]);
|
||||
foreach (Vector2 p in CurrentCurve)
|
||||
path.AddVertex(p - CurrentCurve[0]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void UpdateProgress(double progress, int repeat)
|
||||
public void UpdateProgress(double progress, int span)
|
||||
{
|
||||
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 (span >= slider.SpanCount() - 1)
|
||||
{
|
||||
if (Math.Min(repeat, slider.RepeatCount - 1) % 2 == 1)
|
||||
if (Math.Min(span, slider.SpanCount() - 1) % 2 == 1)
|
||||
{
|
||||
start = 0;
|
||||
end = snakingOut ? progress : 1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK.Graphics;
|
||||
@ -11,7 +11,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
public class SpinnerBackground : CircularContainer, IHasAccentColour
|
||||
{
|
||||
public override bool HandleInput => false;
|
||||
public override bool HandleKeyboardInput => false;
|
||||
public override bool HandleMouseInput => false;
|
||||
|
||||
protected Box Disc;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
@ -54,4 +54,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
@ -23,4 +23,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
base.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects
|
||||
{
|
||||
public interface ISliderProgress
|
||||
{
|
||||
void UpdateProgress(double progress, int repeat);
|
||||
void UpdateProgress(double progress, int span);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
@ -7,7 +7,6 @@ using OpenTK;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects
|
||||
{
|
||||
@ -15,10 +14,8 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
{
|
||||
public const double OBJECT_RADIUS = 64;
|
||||
|
||||
private const double hittable_range = 300;
|
||||
private const double hit_window_50 = 150;
|
||||
private const double hit_window_100 = 80;
|
||||
private const double hit_window_300 = 30;
|
||||
public double TimePreempt = 600;
|
||||
public double TimeFadein = 400;
|
||||
|
||||
public Vector2 Position { get; set; }
|
||||
public float X => Position.X;
|
||||
@ -40,38 +37,15 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
|
||||
public Color4 ComboColour { get; set; } = Color4.Gray;
|
||||
public virtual bool NewCombo { get; set; }
|
||||
public int ComboIndex { get; set; }
|
||||
|
||||
public double HitWindowFor(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return 300;
|
||||
case HitResult.Meh:
|
||||
return 150;
|
||||
case HitResult.Good:
|
||||
return 80;
|
||||
case HitResult.Great:
|
||||
return 30;
|
||||
}
|
||||
}
|
||||
|
||||
public HitResult ScoreResultForOffset(double offset)
|
||||
{
|
||||
if (offset < HitWindowFor(HitResult.Great))
|
||||
return HitResult.Great;
|
||||
if (offset < HitWindowFor(HitResult.Good))
|
||||
return HitResult.Good;
|
||||
if (offset < HitWindowFor(HitResult.Meh))
|
||||
return HitResult.Meh;
|
||||
return HitResult.Miss;
|
||||
}
|
||||
public int IndexInCurrentCombo { get; set; }
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
TimePreempt = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450);
|
||||
TimeFadein = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1200, 800, 300);
|
||||
|
||||
Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,25 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects
|
||||
{
|
||||
public class RepeatPoint : OsuHitObject
|
||||
{
|
||||
public int RepeatIndex { get; set; }
|
||||
public double SpanDuration { get; set; }
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
// We want to show the first RepeatPoint as the TimePreempt dictates but on short (and possibly fast) sliders
|
||||
// we may need to cut down this time on following RepeatPoints to only show up to two RepeatPoints at any given time.
|
||||
if (RepeatIndex > 0)
|
||||
TimePreempt = Math.Min(SpanDuration * 2, TimePreempt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
@ -20,12 +20,13 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
/// </summary>
|
||||
private const float base_scoring_distance = 100;
|
||||
|
||||
public readonly SliderCurve Curve = new SliderCurve();
|
||||
|
||||
public double EndTime => StartTime + RepeatCount * Curve.Distance / Velocity;
|
||||
public double EndTime => StartTime + this.SpanCount() * Curve.Distance / Velocity;
|
||||
public double Duration => EndTime - StartTime;
|
||||
|
||||
public override Vector2 EndPosition => PositionAt(1);
|
||||
public Vector2 StackedPositionAt(double t) => this.PositionAt(t) + StackOffset;
|
||||
public override Vector2 EndPosition => this.PositionAt(1);
|
||||
|
||||
public SliderCurve Curve { get; } = new SliderCurve();
|
||||
|
||||
public List<Vector2> ControlPoints
|
||||
{
|
||||
@ -58,9 +59,15 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
internal float LazyTravelDistance;
|
||||
|
||||
public List<List<SampleInfo>> RepeatSamples { get; set; } = new List<List<SampleInfo>>();
|
||||
public int RepeatCount { get; set; } = 1;
|
||||
public int RepeatCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The length of one span of this <see cref="Slider"/>.
|
||||
/// </summary>
|
||||
public double SpanDuration => Duration / this.SpanCount();
|
||||
|
||||
private int stackHeight;
|
||||
|
||||
public override int StackHeight
|
||||
{
|
||||
get { return stackHeight; }
|
||||
@ -74,6 +81,9 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
public double Velocity;
|
||||
public double TickDistance;
|
||||
|
||||
public HitCircle HeadCircle;
|
||||
public HitCircle TailCircle;
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
@ -87,40 +97,52 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
TickDistance = scoringDistance / difficulty.SliderTickRate;
|
||||
}
|
||||
|
||||
public Vector2 PositionAt(double progress) => Curve.PositionAt(ProgressAt(progress));
|
||||
|
||||
public double ProgressAt(double progress)
|
||||
{
|
||||
double p = progress * RepeatCount % 1;
|
||||
if (RepeatAt(progress) % 2 == 1)
|
||||
p = 1 - p;
|
||||
return p;
|
||||
}
|
||||
|
||||
public int RepeatAt(double progress) => (int)(progress * RepeatCount);
|
||||
|
||||
protected override void CreateNestedHitObjects()
|
||||
{
|
||||
base.CreateNestedHitObjects();
|
||||
|
||||
createSliderEnds();
|
||||
createTicks();
|
||||
createRepeatPoints();
|
||||
}
|
||||
|
||||
private void createSliderEnds()
|
||||
{
|
||||
HeadCircle = new HitCircle
|
||||
{
|
||||
StartTime = StartTime,
|
||||
Position = StackedPosition,
|
||||
IndexInCurrentCombo = IndexInCurrentCombo,
|
||||
ComboColour = ComboColour,
|
||||
Samples = Samples,
|
||||
SampleControlPoint = SampleControlPoint
|
||||
};
|
||||
|
||||
TailCircle = new HitCircle
|
||||
{
|
||||
StartTime = EndTime,
|
||||
Position = StackedEndPosition,
|
||||
IndexInCurrentCombo = IndexInCurrentCombo,
|
||||
ComboColour = ComboColour
|
||||
};
|
||||
|
||||
AddNested(HeadCircle);
|
||||
AddNested(TailCircle);
|
||||
}
|
||||
|
||||
private void createTicks()
|
||||
{
|
||||
if (TickDistance == 0) return;
|
||||
|
||||
var length = Curve.Distance;
|
||||
var tickDistance = Math.Min(TickDistance, length);
|
||||
var repeatDuration = length / Velocity;
|
||||
|
||||
var minDistanceFromEnd = Velocity * 0.01;
|
||||
|
||||
for (var repeat = 0; repeat < RepeatCount; repeat++)
|
||||
for (var span = 0; span < this.SpanCount(); span++)
|
||||
{
|
||||
var repeatStartTime = StartTime + repeat * repeatDuration;
|
||||
var reversed = repeat % 2 == 1;
|
||||
var spanStartTime = StartTime + span * SpanDuration;
|
||||
var reversed = span % 2 == 1;
|
||||
|
||||
for (var d = tickDistance; d <= length; d += tickDistance)
|
||||
{
|
||||
@ -130,20 +152,27 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
var distanceProgress = d / length;
|
||||
var timeProgress = reversed ? 1 - distanceProgress : distanceProgress;
|
||||
|
||||
var firstSample = Samples.FirstOrDefault(s => s.Name == SampleInfo.HIT_NORMAL) ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933)
|
||||
var sampleList = new List<SampleInfo>();
|
||||
|
||||
if (firstSample != null)
|
||||
sampleList.Add(new SampleInfo
|
||||
{
|
||||
Bank = firstSample.Bank,
|
||||
Volume = firstSample.Volume,
|
||||
Name = @"slidertick",
|
||||
});
|
||||
|
||||
AddNested(new SliderTick
|
||||
{
|
||||
RepeatIndex = repeat,
|
||||
StartTime = repeatStartTime + timeProgress * repeatDuration,
|
||||
SpanIndex = span,
|
||||
SpanStartTime = spanStartTime,
|
||||
StartTime = spanStartTime + timeProgress * SpanDuration,
|
||||
Position = Curve.PositionAt(distanceProgress),
|
||||
StackHeight = StackHeight,
|
||||
Scale = Scale,
|
||||
ComboColour = ComboColour,
|
||||
Samples = new List<SampleInfo>(Samples.Select(s => new SampleInfo
|
||||
{
|
||||
Bank = s.Bank,
|
||||
Name = @"slidertick",
|
||||
Volume = s.Volume
|
||||
}))
|
||||
Samples = sampleList
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -151,21 +180,18 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
|
||||
private void createRepeatPoints()
|
||||
{
|
||||
var repeatDuration = Distance / Velocity;
|
||||
|
||||
for (var repeat = 1; repeat < RepeatCount; repeat++)
|
||||
for (int repeatIndex = 0, repeat = 1; repeatIndex < RepeatCount; repeatIndex++, repeat++)
|
||||
{
|
||||
var repeatStartTime = StartTime + repeat * repeatDuration;
|
||||
|
||||
AddNested(new RepeatPoint
|
||||
{
|
||||
RepeatIndex = repeat,
|
||||
StartTime = repeatStartTime,
|
||||
RepeatIndex = repeatIndex,
|
||||
SpanDuration = SpanDuration,
|
||||
StartTime = StartTime + repeat * SpanDuration,
|
||||
Position = Curve.PositionAt(repeat % 2),
|
||||
StackHeight = StackHeight,
|
||||
Scale = Scale,
|
||||
ComboColour = ComboColour,
|
||||
Samples = new List<SampleInfo>(RepeatSamples[repeat])
|
||||
Samples = new List<SampleInfo>(RepeatSamples[repeatIndex])
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,30 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects
|
||||
{
|
||||
public class SliderTick : OsuHitObject
|
||||
{
|
||||
public int RepeatIndex { get; set; }
|
||||
public int SpanIndex { get; set; }
|
||||
public double SpanStartTime { get; set; }
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
double offset;
|
||||
|
||||
if (SpanIndex > 0)
|
||||
// Adding 200 to include the offset stable used.
|
||||
// This is so on repeats ticks don't appear too late to be visually processed by the player.
|
||||
offset = 200;
|
||||
else
|
||||
offset = TimeFadein * 0.66f;
|
||||
|
||||
TimePreempt = (StartTime - SpanStartTime) / 2 + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
@ -29,8 +29,7 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty
|
||||
|
||||
protected override void PreprocessHitObjects()
|
||||
{
|
||||
foreach (OsuHitObject h in Beatmap.HitObjects)
|
||||
(h as Slider)?.Curve?.Calculate();
|
||||
new OsuBeatmapProcessor().PostProcess(Beatmap);
|
||||
}
|
||||
|
||||
public override double Calculate(Dictionary<string, double> categoryDifficulty = null)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing
|
||||
var computeVertex = new Action<double>(t =>
|
||||
{
|
||||
// ReSharper disable once PossibleInvalidOperationException (bugged in current r# version)
|
||||
var diff = slider.PositionAt(t) - slider.LazyEndPosition.Value;
|
||||
var diff = slider.StackedPositionAt(t) - slider.LazyEndPosition.Value;
|
||||
float dist = diff.Length;
|
||||
|
||||
if (dist > approxFollowCircleRadius)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
@ -145,7 +145,7 @@ namespace osu.Game.Rulesets.Osu
|
||||
|
||||
public override int LegacyID => 0;
|
||||
|
||||
public OsuRuleset(RulesetInfo rulesetInfo)
|
||||
public OsuRuleset(RulesetInfo rulesetInfo = null)
|
||||
: base(rulesetInfo)
|
||||
{
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Graphics;
|
||||
@ -90,20 +89,20 @@ namespace osu.Game.Rulesets.Osu.Replays
|
||||
double endTime = (prev as IHasEndTime)?.EndTime ?? prev.StartTime;
|
||||
|
||||
// Make the cursor stay at a hitObject as long as possible (mainly for autopilot).
|
||||
if (h.StartTime - h.HitWindowFor(HitResult.Miss) > endTime + h.HitWindowFor(HitResult.Meh) + 50)
|
||||
if (h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Miss) > endTime + h.HitWindows.HalfWindowFor(HitResult.Meh) + 50)
|
||||
{
|
||||
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(HitResult.Meh), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(HitResult.Miss), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
|
||||
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindows.HalfWindowFor(HitResult.Meh), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
|
||||
}
|
||||
else if (h.StartTime - h.HitWindowFor(HitResult.Meh) > endTime + h.HitWindowFor(HitResult.Meh) + 50)
|
||||
else if (h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh) > endTime + h.HitWindows.HalfWindowFor(HitResult.Meh) + 50)
|
||||
{
|
||||
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(HitResult.Meh), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(HitResult.Meh), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
|
||||
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindows.HalfWindowFor(HitResult.Meh), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
|
||||
}
|
||||
else if (h.StartTime - h.HitWindowFor(HitResult.Good) > endTime + h.HitWindowFor(HitResult.Good) + 50)
|
||||
else if (h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh) > endTime + h.HitWindows.HalfWindowFor(HitResult.Meh) + 50)
|
||||
{
|
||||
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(HitResult.Good), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(HitResult.Good), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
|
||||
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindows.HalfWindowFor(HitResult.Meh), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,7 +132,7 @@ namespace osu.Game.Rulesets.Osu.Replays
|
||||
// Do some nice easing for cursor movements
|
||||
if (Frames.Count > 0)
|
||||
{
|
||||
moveToHitObject(h.StartTime, startPosition, h.Radius, easing);
|
||||
moveToHitObject(h, startPosition, easing);
|
||||
}
|
||||
|
||||
// Add frames to click the hitobject
|
||||
@ -191,12 +190,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];
|
||||
|
||||
// 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)
|
||||
{
|
||||
lastFrame = new ReplayFrame(waitTime, lastFrame.MouseX, lastFrame.MouseY, lastFrame.ButtonState);
|
||||
@ -205,17 +204,17 @@ namespace osu.Game.Rulesets.Osu.Replays
|
||||
|
||||
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.
|
||||
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.
|
||||
{
|
||||
// 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));
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using NUnit.Framework;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using NUnit.Framework;
|
||||
@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
public class TestCasePerformancePoints : Game.Tests.Visual.TestCasePerformancePoints
|
||||
{
|
||||
public TestCasePerformancePoints()
|
||||
: base(new OsuRuleset(new RulesetInfo()))
|
||||
: base(new OsuRuleset())
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
@ -16,6 +16,10 @@ using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using System.Linq;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
@ -27,7 +31,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
typeof(SliderBall),
|
||||
typeof(SliderBody),
|
||||
typeof(SliderTick),
|
||||
typeof(DrawableSlider),
|
||||
typeof(DrawableSliderTick),
|
||||
typeof(DrawableRepeatPoint),
|
||||
typeof(DrawableOsuHitObject)
|
||||
};
|
||||
@ -63,9 +69,27 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
AddStep("Fast Short Slider", () => testShortHighSpeed());
|
||||
AddStep("Fast Short Slider 1 Repeat", () => testShortHighSpeed(1));
|
||||
AddStep("Fast Short Slider 2 Repeats", () => testShortHighSpeed(2));
|
||||
AddStep("Fast Short Slider 6 Repeats", () => testShortHighSpeed(6));
|
||||
|
||||
AddStep("Perfect Curve", testCurve);
|
||||
// TODO more curve types?
|
||||
AddStep("Perfect Curve", () => testPerfect());
|
||||
AddStep("Perfect Curve 1 Repeat", () => testPerfect(1));
|
||||
AddStep("Perfect Curve 2 Repeats", () => testPerfect(2));
|
||||
|
||||
AddStep("Linear Slider", () => testLinear());
|
||||
AddStep("Linear Slider 1 Repeat", () => testLinear(1));
|
||||
AddStep("Linear Slider 2 Repeats", () => testLinear(2));
|
||||
|
||||
AddStep("Bezier Slider", () => testBezier());
|
||||
AddStep("Bezier Slider 1 Repeat", () => testBezier(1));
|
||||
AddStep("Bezier Slider 2 Repeats", () => testBezier(2));
|
||||
|
||||
AddStep("Linear Overlapping", () => testLinearOverlapping());
|
||||
AddStep("Linear Overlapping 1 Repeat", () => testLinearOverlapping(1));
|
||||
AddStep("Linear Overlapping 2 Repeats", () => testLinearOverlapping(2));
|
||||
|
||||
AddStep("Catmull Slider", () => testCatmull());
|
||||
AddStep("Catmull Slider 1 Repeat", () => testCatmull(1));
|
||||
AddStep("Catmull Slider 2 Repeats", () => testCatmull(2));
|
||||
}
|
||||
|
||||
private void testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats);
|
||||
@ -84,15 +108,6 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
private void createSlider(float circleSize = 2, float distance = 400, int repeats = 0, double speedMultiplier = 2)
|
||||
{
|
||||
repeats++; // The first run through the slider is considered a repeat
|
||||
|
||||
var repeatSamples = new List<List<SampleInfo>>();
|
||||
if (repeats > 1)
|
||||
{
|
||||
for (int i = 0; i < repeats; i++)
|
||||
repeatSamples.Add(new List<SampleInfo>());
|
||||
}
|
||||
|
||||
var slider = new Slider
|
||||
{
|
||||
StartTime = Time.Current + 1000,
|
||||
@ -105,13 +120,13 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
},
|
||||
Distance = distance,
|
||||
RepeatCount = repeats,
|
||||
RepeatSamples = repeatSamples
|
||||
RepeatSamples = createEmptySamples(repeats)
|
||||
};
|
||||
|
||||
addSlider(slider, circleSize, speedMultiplier);
|
||||
}
|
||||
|
||||
private void testCurve()
|
||||
private void testPerfect(int repeats = 0)
|
||||
{
|
||||
var slider = new Slider
|
||||
{
|
||||
@ -124,18 +139,137 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
new Vector2(0, 200),
|
||||
new Vector2(200, 0)
|
||||
},
|
||||
Distance = 600
|
||||
Distance = 600,
|
||||
RepeatCount = repeats,
|
||||
RepeatSamples = createEmptySamples(repeats)
|
||||
};
|
||||
|
||||
addSlider(slider, 2, 3);
|
||||
}
|
||||
|
||||
private void testLinear(int repeats = 0) => createLinear(repeats);
|
||||
|
||||
private void createLinear(int repeats)
|
||||
{
|
||||
var slider = new Slider
|
||||
{
|
||||
CurveType = CurveType.Linear,
|
||||
StartTime = Time.Current + 1000,
|
||||
Position = new Vector2(-200, 0),
|
||||
ComboColour = Color4.LightSeaGreen,
|
||||
ControlPoints = new List<Vector2>
|
||||
{
|
||||
new Vector2(-200, 0),
|
||||
new Vector2(-50, 75),
|
||||
new Vector2(0, 100),
|
||||
new Vector2(100, -200),
|
||||
new Vector2(200, 0),
|
||||
new Vector2(230, 0)
|
||||
},
|
||||
Distance = 793.4417,
|
||||
RepeatCount = repeats,
|
||||
RepeatSamples = createEmptySamples(repeats)
|
||||
};
|
||||
|
||||
addSlider(slider, 2, 3);
|
||||
}
|
||||
|
||||
private void testBezier(int repeats = 0) => createBezier(repeats);
|
||||
|
||||
private void createBezier(int repeats)
|
||||
{
|
||||
var slider = new Slider
|
||||
{
|
||||
CurveType = CurveType.Bezier,
|
||||
StartTime = Time.Current + 1000,
|
||||
Position = new Vector2(-200, 0),
|
||||
ComboColour = Color4.LightSeaGreen,
|
||||
ControlPoints = new List<Vector2>
|
||||
{
|
||||
new Vector2(-200, 0),
|
||||
new Vector2(-50, 75),
|
||||
new Vector2(0, 100),
|
||||
new Vector2(100, -200),
|
||||
new Vector2(230, 0)
|
||||
},
|
||||
Distance = 480,
|
||||
RepeatCount = repeats,
|
||||
RepeatSamples = createEmptySamples(repeats)
|
||||
};
|
||||
|
||||
addSlider(slider, 2, 3);
|
||||
}
|
||||
|
||||
private void testLinearOverlapping(int repeats = 0) => createOverlapping(repeats);
|
||||
|
||||
private void createOverlapping(int repeats)
|
||||
{
|
||||
var slider = new Slider
|
||||
{
|
||||
CurveType = CurveType.Linear,
|
||||
StartTime = Time.Current + 1000,
|
||||
Position = new Vector2(0, 0),
|
||||
ComboColour = Color4.LightSeaGreen,
|
||||
ControlPoints = new List<Vector2>
|
||||
{
|
||||
new Vector2(0, 0),
|
||||
new Vector2(-200, 0),
|
||||
new Vector2(0, 0),
|
||||
new Vector2(0, -200),
|
||||
new Vector2(-200, -200),
|
||||
new Vector2(0, -200)
|
||||
},
|
||||
Distance = 1000,
|
||||
RepeatCount = repeats,
|
||||
RepeatSamples = createEmptySamples(repeats)
|
||||
};
|
||||
|
||||
addSlider(slider, 2, 3);
|
||||
}
|
||||
|
||||
private void testCatmull(int repeats = 0) => createCatmull(repeats);
|
||||
|
||||
private void createCatmull(int repeats = 0)
|
||||
{
|
||||
var repeatSamples = new List<List<SampleInfo>>();
|
||||
for (int i = 0; i < repeats; i++)
|
||||
repeatSamples.Add(new List<SampleInfo>());
|
||||
|
||||
var slider = new Slider
|
||||
{
|
||||
StartTime = Time.Current + 1000,
|
||||
Position = new Vector2(-100, 0),
|
||||
ComboColour = Color4.LightSeaGreen,
|
||||
CurveType = CurveType.Catmull,
|
||||
ControlPoints = new List<Vector2>
|
||||
{
|
||||
new Vector2(-100, 0),
|
||||
new Vector2(-50, -50),
|
||||
new Vector2(50, 50),
|
||||
new Vector2(100, 0)
|
||||
},
|
||||
Distance = 300,
|
||||
RepeatCount = repeats,
|
||||
RepeatSamples = repeatSamples
|
||||
};
|
||||
|
||||
addSlider(slider, 3, 1);
|
||||
}
|
||||
|
||||
private List<List<SampleInfo>> createEmptySamples(int repeats)
|
||||
{
|
||||
var repeatSamples = new List<List<SampleInfo>>();
|
||||
for (int i = 0; i < repeats; i++)
|
||||
repeatSamples.Add(new List<SampleInfo>());
|
||||
return repeatSamples;
|
||||
}
|
||||
|
||||
private void addSlider(Slider slider, float circleSize, double speedMultiplier)
|
||||
{
|
||||
var cpi = new ControlPointInfo();
|
||||
cpi.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = speedMultiplier });
|
||||
|
||||
slider.ApplyDefaults(cpi, new BeatmapDifficulty { CircleSize = circleSize });
|
||||
slider.ApplyDefaults(cpi, new BeatmapDifficulty { CircleSize = circleSize, SliderTickRate = 3 });
|
||||
|
||||
var drawable = new DrawableSlider(slider)
|
||||
{
|
||||
@ -146,7 +280,34 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
foreach (var mod in Mods.OfType<IApplicableToDrawableHitObjects>())
|
||||
mod.ApplyToDrawableHitObjects(new[] { drawable });
|
||||
|
||||
drawable.OnJudgement += onJudgement;
|
||||
|
||||
Add(drawable);
|
||||
}
|
||||
|
||||
private float judgementOffsetDirection = 1;
|
||||
private void onJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||
{
|
||||
var osuObject = judgedObject as DrawableOsuHitObject;
|
||||
if (osuObject == null)
|
||||
return;
|
||||
|
||||
OsuSpriteText text;
|
||||
Add(text = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Text = judgement.IsHit ? "Hit!" : "Miss!",
|
||||
Colour = judgement.IsHit ? Color4.Green : Color4.Red,
|
||||
TextSize = 30,
|
||||
Position = osuObject.HitObject.StackedEndPosition + judgementOffsetDirection * new Vector2(0, 45)
|
||||
});
|
||||
|
||||
text.Delay(150)
|
||||
.Then().FadeOut(200)
|
||||
.Then().Expire();
|
||||
|
||||
judgementOffsetDirection *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
@ -159,5 +159,17 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
ActiveCursor.FadeTo(1, 250, Easing.OutQuint);
|
||||
ActiveCursor.ScaleTo(1, 400, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
ActiveCursor.FadeTo(0, 250, Easing.OutQuint);
|
||||
ActiveCursor.ScaleTo(0.6f, 250, Easing.In);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
@ -12,8 +12,6 @@ using osu.Game.Rulesets.UI;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using osu.Game.Rulesets.Osu.UI.Cursor;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.UI
|
||||
{
|
||||
@ -23,8 +21,6 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
private readonly Container judgementLayer;
|
||||
private readonly ConnectionRenderer<OsuHitObject> connectionLayer;
|
||||
|
||||
public override bool ProvidingUserCursor => true;
|
||||
|
||||
// Todo: This should not be a thing, but is currently required for the editor
|
||||
// https://github.com/ppy/osu-framework/issues/1283
|
||||
protected virtual bool ProxyApproachCircles => true;
|
||||
@ -70,19 +66,12 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
var cursor = CreateCursor();
|
||||
if (cursor != null)
|
||||
AddInternal(cursor);
|
||||
}
|
||||
|
||||
public override void Add(DrawableHitObject h)
|
||||
{
|
||||
h.Depth = (float)h.HitObject.StartTime;
|
||||
|
||||
h.OnJudgement += onJudgement;
|
||||
|
||||
var c = h as IDrawableHitObjectWithProxiedApproach;
|
||||
if (c != null && ProxyApproachCircles)
|
||||
approachCircles.Add(c.ProxiedLayer.CreateProxy());
|
||||
@ -97,7 +86,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
.OrderBy(h => h.StartTime).OfType<OsuHitObject>();
|
||||
}
|
||||
|
||||
public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||
private void onJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||
{
|
||||
var osuJudgement = (OsuJudgement)judgement;
|
||||
var osuObject = (OsuHitObject)judgedObject.HitObject;
|
||||
@ -113,7 +102,5 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
judgementLayer.Add(explosion);
|
||||
}
|
||||
|
||||
protected virtual CursorContainer CreateCursor() => new GameplayCursor();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Input;
|
||||
using OpenTK;
|
||||
using osu.Game.Beatmaps;
|
||||
@ -10,6 +11,7 @@ using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Replays;
|
||||
using osu.Game.Rulesets.Osu.Scoring;
|
||||
using osu.Game.Rulesets.Osu.UI.Cursor;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
@ -49,5 +51,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
protected override FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new OsuReplayInputHandler(replay);
|
||||
|
||||
protected override Vector2 GetPlayfieldAspectAdjust() => new Vector2(0.75f);
|
||||
|
||||
protected override CursorContainer CreateCursor() => new GameplayCursor();
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
|
Reference in New Issue
Block a user