mirror of
https://github.com/ppy/osu.git
synced 2024-12-16 03:42:58 +08:00
Merge pull request #9421 from ekrctb/catch-coordinate
Standardise osu!catch coordinate system to 0..512
This commit is contained in:
commit
254b8b926c
@ -8,7 +8,6 @@ using NUnit.Framework;
|
|||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Rulesets.Catch.Mods;
|
using osu.Game.Rulesets.Catch.Mods;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Tests.Beatmaps;
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
|
||||||
@ -83,7 +82,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
public float Position
|
public float Position
|
||||||
{
|
{
|
||||||
get => HitObject?.X * CatchPlayfield.BASE_WIDTH ?? position;
|
get => HitObject?.X ?? position;
|
||||||
set => position = value;
|
set => position = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,15 +27,15 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
for (int i = 0; i < 100; i++)
|
for (int i = 0; i < 100; i++)
|
||||||
{
|
{
|
||||||
float width = (i % 10 + 1) / 20f;
|
float width = (i % 10 + 1) / 20f * CatchPlayfield.WIDTH;
|
||||||
|
|
||||||
beatmap.HitObjects.Add(new JuiceStream
|
beatmap.HitObjects.Add(new JuiceStream
|
||||||
{
|
{
|
||||||
X = 0.5f - width / 2,
|
X = CatchPlayfield.CENTER_X - width / 2,
|
||||||
Path = new SliderPath(PathType.Linear, new[]
|
Path = new SliderPath(PathType.Linear, new[]
|
||||||
{
|
{
|
||||||
Vector2.Zero,
|
Vector2.Zero,
|
||||||
new Vector2(width * CatchPlayfield.BASE_WIDTH, 0)
|
new Vector2(width, 0)
|
||||||
}),
|
}),
|
||||||
StartTime = i * 2000,
|
StartTime = i * 2000,
|
||||||
NewCombo = i % 8 == 0
|
NewCombo = i % 8 == 0
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
{
|
{
|
||||||
@ -22,7 +23,14 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < 512; i++)
|
for (int i = 0; i < 512; i++)
|
||||||
beatmap.HitObjects.Add(new Fruit { X = 0.5f + i / 2048f * (i % 10 - 5), StartTime = i * 100, NewCombo = i % 8 == 0 });
|
{
|
||||||
|
beatmap.HitObjects.Add(new Fruit
|
||||||
|
{
|
||||||
|
X = (0.5f + i / 2048f * (i % 10 - 5)) * CatchPlayfield.WIDTH,
|
||||||
|
StartTime = i * 100,
|
||||||
|
NewCombo = i % 8 == 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return beatmap;
|
return beatmap;
|
||||||
}
|
}
|
||||||
|
@ -76,8 +76,8 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Child = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size })
|
Child = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size })
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.TopLeft,
|
Origin = Anchor.TopCentre,
|
||||||
CreateDrawableRepresentation = ((DrawableRuleset<CatchHitObject>)catchRuleset.CreateInstance().CreateDrawableRulesetWith(new CatchBeatmap())).CreateDrawableRepresentation
|
CreateDrawableRepresentation = ((DrawableRuleset<CatchHitObject>)catchRuleset.CreateInstance().CreateDrawableRulesetWith(new CatchBeatmap())).CreateDrawableRepresentation
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -158,8 +158,8 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
private float getXCoords(bool hit)
|
private float getXCoords(bool hit)
|
||||||
{
|
{
|
||||||
const float x_offset = 0.2f;
|
const float x_offset = 0.2f * CatchPlayfield.WIDTH;
|
||||||
float xCoords = drawableRuleset.Playfield.Width / 2;
|
float xCoords = CatchPlayfield.CENTER_X;
|
||||||
|
|
||||||
if (drawableRuleset.Playfield is CatchPlayfield catchPlayfield)
|
if (drawableRuleset.Playfield is CatchPlayfield catchPlayfield)
|
||||||
catchPlayfield.CatcherArea.MovableCatcher.X = xCoords - x_offset;
|
catchPlayfield.CatcherArea.MovableCatcher.X = xCoords - x_offset;
|
||||||
|
@ -47,13 +47,13 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Should produce a hyper-dash (edge case test)
|
// Should produce a hyper-dash (edge case test)
|
||||||
beatmap.HitObjects.Add(new Fruit { StartTime = 1816, X = 56 / 512f, NewCombo = true });
|
beatmap.HitObjects.Add(new Fruit { StartTime = 1816, X = 56, NewCombo = true });
|
||||||
beatmap.HitObjects.Add(new Fruit { StartTime = 2008, X = 308 / 512f, NewCombo = true });
|
beatmap.HitObjects.Add(new Fruit { StartTime = 2008, X = 308, NewCombo = true });
|
||||||
|
|
||||||
double startTime = 3000;
|
double startTime = 3000;
|
||||||
|
|
||||||
const float left_x = 0.02f;
|
const float left_x = 0.02f * CatchPlayfield.WIDTH;
|
||||||
const float right_x = 0.98f;
|
const float right_x = 0.98f * CatchPlayfield.WIDTH;
|
||||||
|
|
||||||
createObjects(() => new Fruit { X = left_x });
|
createObjects(() => new Fruit { X = left_x });
|
||||||
createObjects(() => new TestJuiceStream(right_x), 1);
|
createObjects(() => new TestJuiceStream(right_x), 1);
|
||||||
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -30,7 +31,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
{
|
{
|
||||||
new JuiceStream
|
new JuiceStream
|
||||||
{
|
{
|
||||||
X = 0.5f,
|
X = CatchPlayfield.CENTER_X,
|
||||||
Path = new SliderPath(PathType.Linear, new[]
|
Path = new SliderPath(PathType.Linear, new[]
|
||||||
{
|
{
|
||||||
Vector2.Zero,
|
Vector2.Zero,
|
||||||
@ -40,7 +41,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
},
|
},
|
||||||
new Banana
|
new Banana
|
||||||
{
|
{
|
||||||
X = 0.5f,
|
X = CatchPlayfield.CENTER_X,
|
||||||
StartTime = 1000,
|
StartTime = 1000,
|
||||||
NewCombo = true
|
NewCombo = true
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
@ -36,7 +35,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
Path = curveData.Path,
|
Path = curveData.Path,
|
||||||
NodeSamples = curveData.NodeSamples,
|
NodeSamples = curveData.NodeSamples,
|
||||||
RepeatCount = curveData.RepeatCount,
|
RepeatCount = curveData.RepeatCount,
|
||||||
X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH,
|
X = positionData?.X ?? 0,
|
||||||
NewCombo = comboData?.NewCombo ?? false,
|
NewCombo = comboData?.NewCombo ?? false,
|
||||||
ComboOffset = comboData?.ComboOffset ?? 0,
|
ComboOffset = comboData?.ComboOffset ?? 0,
|
||||||
LegacyLastTickOffset = (obj as IHasLegacyLastTickOffset)?.LegacyLastTickOffset ?? 0
|
LegacyLastTickOffset = (obj as IHasLegacyLastTickOffset)?.LegacyLastTickOffset ?? 0
|
||||||
@ -59,7 +58,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
Samples = obj.Samples,
|
Samples = obj.Samples,
|
||||||
NewCombo = comboData?.NewCombo ?? false,
|
NewCombo = comboData?.NewCombo ?? false,
|
||||||
ComboOffset = comboData?.ComboOffset ?? 0,
|
ComboOffset = comboData?.ComboOffset ?? 0,
|
||||||
X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH
|
X = positionData?.X ?? 0
|
||||||
}.Yield();
|
}.Yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
case BananaShower bananaShower:
|
case BananaShower bananaShower:
|
||||||
foreach (var banana in bananaShower.NestedHitObjects.OfType<Banana>())
|
foreach (var banana in bananaShower.NestedHitObjects.OfType<Banana>())
|
||||||
{
|
{
|
||||||
banana.XOffset = (float)rng.NextDouble();
|
banana.XOffset = (float)(rng.NextDouble() * CatchPlayfield.WIDTH);
|
||||||
rng.Next(); // osu!stable retrieved a random banana type
|
rng.Next(); // osu!stable retrieved a random banana type
|
||||||
rng.Next(); // osu!stable retrieved a random banana rotation
|
rng.Next(); // osu!stable retrieved a random banana rotation
|
||||||
rng.Next(); // osu!stable retrieved a random banana colour
|
rng.Next(); // osu!stable retrieved a random banana colour
|
||||||
@ -75,7 +75,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
|
|
||||||
case JuiceStream juiceStream:
|
case JuiceStream juiceStream:
|
||||||
// Todo: BUG!! Stable used the last control point as the final position of the path, but it should use the computed path instead.
|
// Todo: BUG!! Stable used the last control point as the final position of the path, but it should use the computed path instead.
|
||||||
lastPosition = juiceStream.X + juiceStream.Path.ControlPoints[^1].Position.Value.X / CatchPlayfield.BASE_WIDTH;
|
lastPosition = juiceStream.X + juiceStream.Path.ControlPoints[^1].Position.Value.X;
|
||||||
|
|
||||||
// Todo: BUG!! Stable attempted to use the end time of the stream, but referenced it too early in execution and used the start time instead.
|
// Todo: BUG!! Stable attempted to use the end time of the stream, but referenced it too early in execution and used the start time instead.
|
||||||
lastStartTime = juiceStream.StartTime;
|
lastStartTime = juiceStream.StartTime;
|
||||||
@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
catchObject.XOffset = 0;
|
catchObject.XOffset = 0;
|
||||||
|
|
||||||
if (catchObject is TinyDroplet)
|
if (catchObject is TinyDroplet)
|
||||||
catchObject.XOffset = Math.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X);
|
catchObject.XOffset = Math.Clamp(rng.Next(-20, 20), -catchObject.X, CatchPlayfield.WIDTH - catchObject.X);
|
||||||
else if (catchObject is Droplet)
|
else if (catchObject is Droplet)
|
||||||
rng.Next(); // osu!stable retrieved a random droplet rotation
|
rng.Next(); // osu!stable retrieved a random droplet rotation
|
||||||
}
|
}
|
||||||
@ -131,7 +131,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReSharper disable once PossibleLossOfFraction
|
// ReSharper disable once PossibleLossOfFraction
|
||||||
if (Math.Abs(positionDiff * CatchPlayfield.BASE_WIDTH) < timeDiff / 3)
|
if (Math.Abs(positionDiff) < timeDiff / 3)
|
||||||
applyOffset(ref offsetPosition, positionDiff);
|
applyOffset(ref offsetPosition, positionDiff);
|
||||||
|
|
||||||
hitObject.XOffset = offsetPosition - hitObject.X;
|
hitObject.XOffset = offsetPosition - hitObject.X;
|
||||||
@ -149,12 +149,12 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
private static void applyRandomOffset(ref float position, double maxOffset, FastRandom rng)
|
private static void applyRandomOffset(ref float position, double maxOffset, FastRandom rng)
|
||||||
{
|
{
|
||||||
bool right = rng.NextBool();
|
bool right = rng.NextBool();
|
||||||
float rand = Math.Min(20, (float)rng.Next(0, Math.Max(0, maxOffset))) / CatchPlayfield.BASE_WIDTH;
|
float rand = Math.Min(20, (float)rng.Next(0, Math.Max(0, maxOffset)));
|
||||||
|
|
||||||
if (right)
|
if (right)
|
||||||
{
|
{
|
||||||
// Clamp to the right bound
|
// Clamp to the right bound
|
||||||
if (position + rand <= 1)
|
if (position + rand <= CatchPlayfield.WIDTH)
|
||||||
position += rand;
|
position += rand;
|
||||||
else
|
else
|
||||||
position -= rand;
|
position -= rand;
|
||||||
@ -211,7 +211,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
|
|
||||||
objectWithDroplets.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime));
|
objectWithDroplets.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime));
|
||||||
|
|
||||||
double halfCatcherWidth = CatcherArea.GetCatcherSize(beatmap.BeatmapInfo.BaseDifficulty) / 2;
|
double halfCatcherWidth = Catcher.CalculateCatchWidth(beatmap.BeatmapInfo.BaseDifficulty) / 2;
|
||||||
int lastDirection = 0;
|
int lastDirection = 0;
|
||||||
double lastExcess = halfCatcherWidth;
|
double lastExcess = halfCatcherWidth;
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
|
||||||
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
|
|
||||||
@ -33,8 +32,8 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing
|
|||||||
// We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps.
|
// We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps.
|
||||||
var scalingFactor = normalized_hitobject_radius / halfCatcherWidth;
|
var scalingFactor = normalized_hitobject_radius / halfCatcherWidth;
|
||||||
|
|
||||||
NormalizedPosition = BaseObject.X * CatchPlayfield.BASE_WIDTH * scalingFactor;
|
NormalizedPosition = BaseObject.X * scalingFactor;
|
||||||
LastNormalizedPosition = LastObject.X * CatchPlayfield.BASE_WIDTH * scalingFactor;
|
LastNormalizedPosition = LastObject.X * scalingFactor;
|
||||||
|
|
||||||
// Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure
|
// Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure
|
||||||
StrainTime = Math.Max(40, DeltaTime);
|
StrainTime = Math.Max(40, DeltaTime);
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Game.Rulesets.Catch.Difficulty.Preprocessing;
|
using osu.Game.Rulesets.Catch.Difficulty.Preprocessing;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
|
||||||
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||||
using osu.Game.Rulesets.Difficulty.Skills;
|
using osu.Game.Rulesets.Difficulty.Skills;
|
||||||
|
|
||||||
@ -68,7 +67,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bonus for edge dashes.
|
// Bonus for edge dashes.
|
||||||
if (catchCurrent.LastObject.DistanceToHyperDash <= 20.0f / CatchPlayfield.BASE_WIDTH)
|
if (catchCurrent.LastObject.DistanceToHyperDash <= 20.0f)
|
||||||
{
|
{
|
||||||
if (!catchCurrent.LastObject.HyperDash)
|
if (!catchCurrent.LastObject.HyperDash)
|
||||||
edgeDashBonus += 5.7;
|
edgeDashBonus += 5.7;
|
||||||
@ -78,7 +77,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
|
|||||||
playerPosition = catchCurrent.NormalizedPosition;
|
playerPosition = catchCurrent.NormalizedPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
distanceAddition *= 1.0 + edgeDashBonus * ((20 - catchCurrent.LastObject.DistanceToHyperDash * CatchPlayfield.BASE_WIDTH) / 20) * Math.Pow((Math.Min(catchCurrent.StrainTime * catchCurrent.ClockRate, 265) / 265), 1.5); // Edge Dashes are easier at lower ms values
|
distanceAddition *= 1.0 + edgeDashBonus * ((20 - catchCurrent.LastObject.DistanceToHyperDash) / 20) * Math.Pow((Math.Min(catchCurrent.StrainTime * catchCurrent.ClockRate, 265) / 265), 1.5); // Edge Dashes are easier at lower ms values
|
||||||
}
|
}
|
||||||
|
|
||||||
lastPlayerPosition = playerPosition;
|
lastPlayerPosition = playerPosition;
|
||||||
|
@ -5,6 +5,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Catch.Beatmaps;
|
using osu.Game.Rulesets.Catch.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
@ -17,6 +18,9 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
|
|
||||||
private float x;
|
private float x;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The horizontal position of the fruit between 0 and <see cref="CatchPlayfield.WIDTH"/>.
|
||||||
|
/// </summary>
|
||||||
public float X
|
public float X
|
||||||
{
|
{
|
||||||
get => x + XOffset;
|
get => x + XOffset;
|
||||||
|
@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -70,12 +71,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
|||||||
|
|
||||||
public float DisplayRadius => DrawSize.X / 2 * Scale.X * HitObject.Scale;
|
public float DisplayRadius => DrawSize.X / 2 * Scale.X * HitObject.Scale;
|
||||||
|
|
||||||
protected override float SamplePlaybackPosition => HitObject.X;
|
protected override float SamplePlaybackPosition => HitObject.X / CatchPlayfield.WIDTH;
|
||||||
|
|
||||||
protected DrawableCatchHitObject(CatchHitObject hitObject)
|
protected DrawableCatchHitObject(CatchHitObject hitObject)
|
||||||
: base(hitObject)
|
: base(hitObject)
|
||||||
{
|
{
|
||||||
RelativePositionAxes = Axes.X;
|
|
||||||
X = hitObject.X;
|
X = hitObject.X;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ using System.Threading;
|
|||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
@ -80,7 +79,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
{
|
{
|
||||||
StartTime = t + lastEvent.Value.Time,
|
StartTime = t + lastEvent.Value.Time,
|
||||||
X = X + Path.PositionAt(
|
X = X + Path.PositionAt(
|
||||||
lastEvent.Value.PathProgress + (t / sinceLastTick) * (e.PathProgress - lastEvent.Value.PathProgress)).X / CatchPlayfield.BASE_WIDTH,
|
lastEvent.Value.PathProgress + (t / sinceLastTick) * (e.PathProgress - lastEvent.Value.PathProgress)).X,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,7 +96,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
{
|
{
|
||||||
Samples = dropletSamples,
|
Samples = dropletSamples,
|
||||||
StartTime = e.Time,
|
StartTime = e.Time,
|
||||||
X = X + Path.PositionAt(e.PathProgress).X / CatchPlayfield.BASE_WIDTH,
|
X = X + Path.PositionAt(e.PathProgress).X,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -108,14 +107,14 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
{
|
{
|
||||||
Samples = Samples,
|
Samples = Samples,
|
||||||
StartTime = e.Time,
|
StartTime = e.Time,
|
||||||
X = X + Path.PositionAt(e.PathProgress).X / CatchPlayfield.BASE_WIDTH,
|
X = X + Path.PositionAt(e.PathProgress).X,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float EndX => X + this.CurvePositionAt(1).X / CatchPlayfield.BASE_WIDTH;
|
public float EndX => X + this.CurvePositionAt(1).X;
|
||||||
|
|
||||||
public double Duration
|
public double Duration
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Catch.Replays
|
|||||||
// todo: add support for HT DT
|
// todo: add support for HT DT
|
||||||
const double dash_speed = Catcher.BASE_SPEED;
|
const double dash_speed = Catcher.BASE_SPEED;
|
||||||
const double movement_speed = dash_speed / 2;
|
const double movement_speed = dash_speed / 2;
|
||||||
float lastPosition = 0.5f;
|
float lastPosition = CatchPlayfield.CENTER_X;
|
||||||
double lastTime = 0;
|
double lastTime = 0;
|
||||||
|
|
||||||
void moveToNext(CatchHitObject h)
|
void moveToNext(CatchHitObject h)
|
||||||
@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Catch.Replays
|
|||||||
bool impossibleJump = speedRequired > movement_speed * 2;
|
bool impossibleJump = speedRequired > movement_speed * 2;
|
||||||
|
|
||||||
// todo: get correct catcher size, based on difficulty CS.
|
// todo: get correct catcher size, based on difficulty CS.
|
||||||
const float catcher_width_half = CatcherArea.CATCHER_SIZE / CatchPlayfield.BASE_WIDTH * 0.3f * 0.5f;
|
const float catcher_width_half = CatcherArea.CATCHER_SIZE * 0.3f * 0.5f;
|
||||||
|
|
||||||
if (lastPosition - catcher_width_half < h.X && lastPosition + catcher_width_half > h.X)
|
if (lastPosition - catcher_width_half < h.X && lastPosition + catcher_width_half > h.X)
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Replays.Legacy;
|
using osu.Game.Replays.Legacy;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
|
||||||
using osu.Game.Rulesets.Replays;
|
using osu.Game.Rulesets.Replays;
|
||||||
using osu.Game.Rulesets.Replays.Types;
|
using osu.Game.Rulesets.Replays.Types;
|
||||||
|
|
||||||
@ -41,7 +40,7 @@ namespace osu.Game.Rulesets.Catch.Replays
|
|||||||
|
|
||||||
public void FromLegacy(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null)
|
public void FromLegacy(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null)
|
||||||
{
|
{
|
||||||
Position = currentFrame.Position.X / CatchPlayfield.BASE_WIDTH;
|
Position = currentFrame.Position.X;
|
||||||
Dashing = currentFrame.ButtonState == ReplayButtonState.Left1;
|
Dashing = currentFrame.ButtonState == ReplayButtonState.Left1;
|
||||||
|
|
||||||
if (Dashing)
|
if (Dashing)
|
||||||
@ -63,7 +62,7 @@ namespace osu.Game.Rulesets.Catch.Replays
|
|||||||
|
|
||||||
if (Actions.Contains(CatchAction.Dash)) state |= ReplayButtonState.Left1;
|
if (Actions.Contains(CatchAction.Dash)) state |= ReplayButtonState.Left1;
|
||||||
|
|
||||||
return new LegacyReplayFrame(Time, Position * CatchPlayfield.BASE_WIDTH, null, state);
|
return new LegacyReplayFrame(Time, Position, null, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,16 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
public class CatchPlayfield : ScrollingPlayfield
|
public class CatchPlayfield : ScrollingPlayfield
|
||||||
{
|
{
|
||||||
public const float BASE_WIDTH = 512;
|
/// <summary>
|
||||||
|
/// The width of the playfield.
|
||||||
|
/// The horizontal movement of the catcher is confined in the area of this width.
|
||||||
|
/// </summary>
|
||||||
|
public const float WIDTH = 512;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The center position of the playfield.
|
||||||
|
/// </summary>
|
||||||
|
public const float CENTER_X = WIDTH / 2;
|
||||||
|
|
||||||
internal readonly CatcherArea CatcherArea;
|
internal readonly CatcherArea CatcherArea;
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
Scale = new Vector2(Parent.ChildSize.X / CatchPlayfield.BASE_WIDTH);
|
Scale = new Vector2(Parent.ChildSize.X / CatchPlayfield.WIDTH);
|
||||||
Size = Vector2.Divide(Vector2.One, Scale);
|
Size = Vector2.Divide(Vector2.One, Scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The relative space to cover in 1 millisecond. based on 1 game pixel per millisecond as in osu-stable.
|
/// The relative space to cover in 1 millisecond. based on 1 game pixel per millisecond as in osu-stable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const double BASE_SPEED = 1.0 / 512;
|
public const double BASE_SPEED = 1.0;
|
||||||
|
|
||||||
public Container ExplodingFruitTarget;
|
public Container ExplodingFruitTarget;
|
||||||
|
|
||||||
@ -104,9 +104,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
this.trailsTarget = trailsTarget;
|
this.trailsTarget = trailsTarget;
|
||||||
|
|
||||||
RelativePositionAxes = Axes.X;
|
|
||||||
X = 0.5f;
|
|
||||||
|
|
||||||
Origin = Anchor.TopCentre;
|
Origin = Anchor.TopCentre;
|
||||||
|
|
||||||
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
||||||
@ -209,8 +206,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
var halfCatchWidth = catchWidth * 0.5f;
|
var halfCatchWidth = catchWidth * 0.5f;
|
||||||
|
|
||||||
// this stuff wil disappear once we move fruit to non-relative coordinate space in the future.
|
// this stuff wil disappear once we move fruit to non-relative coordinate space in the future.
|
||||||
var catchObjectPosition = fruit.X * CatchPlayfield.BASE_WIDTH;
|
var catchObjectPosition = fruit.X;
|
||||||
var catcherPosition = Position.X * CatchPlayfield.BASE_WIDTH;
|
var catcherPosition = Position.X;
|
||||||
|
|
||||||
var validCatch =
|
var validCatch =
|
||||||
catchObjectPosition >= catcherPosition - halfCatchWidth &&
|
catchObjectPosition >= catcherPosition - halfCatchWidth &&
|
||||||
@ -224,7 +221,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
var target = fruit.HyperDashTarget;
|
var target = fruit.HyperDashTarget;
|
||||||
var timeDifference = target.StartTime - fruit.StartTime;
|
var timeDifference = target.StartTime - fruit.StartTime;
|
||||||
double positionDifference = target.X * CatchPlayfield.BASE_WIDTH - catcherPosition;
|
double positionDifference = target.X - catcherPosition;
|
||||||
var velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0);
|
var velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0);
|
||||||
|
|
||||||
SetHyperDashState(Math.Abs(velocity), target.X);
|
SetHyperDashState(Math.Abs(velocity), target.X);
|
||||||
@ -331,7 +328,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
public void UpdatePosition(float position)
|
public void UpdatePosition(float position)
|
||||||
{
|
{
|
||||||
position = Math.Clamp(position, 0, 1);
|
position = Math.Clamp(position, 0, CatchPlayfield.WIDTH);
|
||||||
|
|
||||||
if (position == X)
|
if (position == X)
|
||||||
return;
|
return;
|
||||||
|
@ -31,14 +31,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
public CatcherArea(BeatmapDifficulty difficulty = null)
|
public CatcherArea(BeatmapDifficulty difficulty = null)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
Size = new Vector2(CatchPlayfield.WIDTH, CATCHER_SIZE);
|
||||||
Height = CATCHER_SIZE;
|
Child = MovableCatcher = new Catcher(this, difficulty) { X = CatchPlayfield.CENTER_X };
|
||||||
Child = MovableCatcher = new Catcher(this, difficulty);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float GetCatcherSize(BeatmapDifficulty difficulty)
|
|
||||||
{
|
|
||||||
return CATCHER_SIZE / CatchPlayfield.BASE_WIDTH * (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnResult(DrawableCatchHitObject fruit, JudgementResult result)
|
public void OnResult(DrawableCatchHitObject fruit, JudgementResult result)
|
||||||
|
@ -218,7 +218,7 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
position.X = ((IHasXPosition)hitObject).X * 512;
|
position.X = ((IHasXPosition)hitObject).X;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
|
Loading…
Reference in New Issue
Block a user