mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 04:02:57 +08:00
Merge pull request #1355 from peppy/catch-improvements
Add (mostly correct) droplets
This commit is contained in:
commit
7aab21e407
@ -5,9 +5,9 @@ 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;
|
using System;
|
||||||
|
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.Game.Rulesets.Osu.UI;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Beatmaps
|
namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||||
{
|
{
|
||||||
@ -17,14 +17,37 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
|
|
||||||
protected override IEnumerable<CatchBaseHit> ConvertHitObject(HitObject obj, Beatmap beatmap)
|
protected override IEnumerable<CatchBaseHit> ConvertHitObject(HitObject obj, Beatmap beatmap)
|
||||||
{
|
{
|
||||||
if (!(obj is IHasXPosition))
|
var curveData = obj as IHasCurve;
|
||||||
|
var positionData = obj as IHasPosition;
|
||||||
|
var comboData = obj as IHasCombo;
|
||||||
|
|
||||||
|
if (positionData == null)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
|
if (curveData != null)
|
||||||
|
{
|
||||||
|
yield return new JuiceStream
|
||||||
|
{
|
||||||
|
StartTime = obj.StartTime,
|
||||||
|
Samples = obj.Samples,
|
||||||
|
ControlPoints = curveData.ControlPoints,
|
||||||
|
CurveType = curveData.CurveType,
|
||||||
|
Distance = curveData.Distance,
|
||||||
|
RepeatSamples = curveData.RepeatSamples,
|
||||||
|
RepeatCount = curveData.RepeatCount,
|
||||||
|
X = positionData.X / CatchPlayfield.BASE_WIDTH,
|
||||||
|
NewCombo = comboData?.NewCombo ?? false
|
||||||
|
};
|
||||||
|
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
yield return new Fruit
|
yield return new Fruit
|
||||||
{
|
{
|
||||||
StartTime = obj.StartTime,
|
StartTime = obj.StartTime,
|
||||||
NewCombo = (obj as IHasCombo)?.NewCombo ?? false,
|
Samples = obj.Samples,
|
||||||
X = ((IHasXPosition)obj).X / OsuPlayfield.BASE_SIZE.X
|
NewCombo = comboData?.NewCombo ?? false,
|
||||||
|
X = positionData.X / CatchPlayfield.BASE_WIDTH
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
// Copyright (c) 2007-2017 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.Judgements;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||||
|
{
|
||||||
|
public abstract class DrawableCatchHitObject<TObject> : DrawableCatchHitObject
|
||||||
|
where TObject : CatchBaseHit
|
||||||
|
{
|
||||||
|
public new TObject HitObject;
|
||||||
|
|
||||||
|
protected DrawableCatchHitObject(TObject hitObject)
|
||||||
|
: base(hitObject)
|
||||||
|
{
|
||||||
|
HitObject = hitObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class DrawableCatchHitObject : DrawableScrollingHitObject<CatchBaseHit>
|
||||||
|
{
|
||||||
|
protected DrawableCatchHitObject(CatchBaseHit hitObject)
|
||||||
|
: base(hitObject)
|
||||||
|
{
|
||||||
|
RelativePositionAxes = Axes.Both;
|
||||||
|
X = hitObject.X;
|
||||||
|
Y = (float)HitObject.StartTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Func<CatchBaseHit, bool> CheckPosition;
|
||||||
|
|
||||||
|
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||||
|
{
|
||||||
|
if (timeOffset > 0)
|
||||||
|
AddJudgement(new Judgement { Result = CheckPosition?.Invoke(HitObject) ?? false ? HitResult.Perfect : HitResult.Miss });
|
||||||
|
}
|
||||||
|
|
||||||
|
private const float preempt = 1000;
|
||||||
|
|
||||||
|
protected override void UpdateState(ArmedState state)
|
||||||
|
{
|
||||||
|
using (BeginAbsoluteSequence(HitObject.StartTime - preempt))
|
||||||
|
{
|
||||||
|
// animation
|
||||||
|
this.FadeIn(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case ArmedState.Miss:
|
||||||
|
using (BeginAbsoluteSequence(HitObject.StartTime, true))
|
||||||
|
this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs
Normal file
34
osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// 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.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||||
|
{
|
||||||
|
public class DrawableDroplet : DrawableCatchHitObject<Droplet>
|
||||||
|
{
|
||||||
|
public DrawableDroplet(Droplet h)
|
||||||
|
: base(h)
|
||||||
|
{
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
Size = new Vector2(Pulp.PULP_SIZE);
|
||||||
|
|
||||||
|
AccentColour = h.ComboColour;
|
||||||
|
Masking = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
Child = new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = AccentColour,
|
||||||
|
Scale = new Vector2(0.8f),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,72 +1,29 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.MathUtils;
|
using osu.Framework.MathUtils;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
|
||||||
using osu.Game.Rulesets.Judgements;
|
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||||
{
|
{
|
||||||
public class DrawableFruit : DrawableScrollingHitObject<CatchBaseHit>
|
public class DrawableFruit : DrawableCatchHitObject<Fruit>
|
||||||
{
|
{
|
||||||
private const float pulp_size = 20;
|
public DrawableFruit(Fruit h)
|
||||||
|
|
||||||
private class Pulp : Circle, IHasAccentColour
|
|
||||||
{
|
|
||||||
public Pulp()
|
|
||||||
{
|
|
||||||
Size = new Vector2(pulp_size);
|
|
||||||
|
|
||||||
Blending = BlendingMode.Additive;
|
|
||||||
Colour = Color4.White.Opacity(0.9f);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Color4 accentColour;
|
|
||||||
public Color4 AccentColour
|
|
||||||
{
|
|
||||||
get { return accentColour; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
accentColour = value;
|
|
||||||
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Glow,
|
|
||||||
Radius = 5,
|
|
||||||
Colour = accentColour.Lighten(100),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public DrawableFruit(CatchBaseHit h)
|
|
||||||
: base(h)
|
: base(h)
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
Size = new Vector2(pulp_size * 2.2f, pulp_size * 2.8f);
|
|
||||||
|
|
||||||
RelativePositionAxes = Axes.Both;
|
|
||||||
X = h.X;
|
|
||||||
|
|
||||||
|
Size = new Vector2(Pulp.PULP_SIZE * 2.2f, Pulp.PULP_SIZE * 2.8f);
|
||||||
AccentColour = HitObject.ComboColour;
|
AccentColour = HitObject.ComboColour;
|
||||||
|
|
||||||
Masking = false;
|
Masking = false;
|
||||||
|
|
||||||
Rotation = (float)(RNG.NextDouble() - 0.5f) * 40;
|
Rotation = (float)(RNG.NextDouble() - 0.5f) * 40;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<CatchBaseHit, bool> CheckPosition;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
@ -114,30 +71,5 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private const float preempt = 1000;
|
|
||||||
|
|
||||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
|
||||||
{
|
|
||||||
if (timeOffset > 0)
|
|
||||||
AddJudgement(new Judgement { Result = CheckPosition?.Invoke(HitObject) ?? false ? HitResult.Perfect : HitResult.Miss });
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void UpdateState(ArmedState state)
|
|
||||||
{
|
|
||||||
using (BeginAbsoluteSequence(HitObject.StartTime - preempt))
|
|
||||||
{
|
|
||||||
// animation
|
|
||||||
this.FadeIn(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case ArmedState.Miss:
|
|
||||||
using (BeginAbsoluteSequence(HitObject.StartTime, true))
|
|
||||||
this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
// 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.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||||
|
{
|
||||||
|
public class DrawableJuiceStream : DrawableCatchHitObject<JuiceStream>
|
||||||
|
{
|
||||||
|
private readonly Container dropletContainer;
|
||||||
|
|
||||||
|
public DrawableJuiceStream(JuiceStream s) : base(s)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Height = (float)HitObject.Duration;
|
||||||
|
X = 0;
|
||||||
|
|
||||||
|
Child = dropletContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime),
|
||||||
|
RelativeChildSize = new Vector2(1, (float)HitObject.Duration)
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (CatchBaseHit tick in s.Ticks)
|
||||||
|
{
|
||||||
|
TinyDroplet tiny = tick as TinyDroplet;
|
||||||
|
if (tiny != null)
|
||||||
|
{
|
||||||
|
AddNested(new DrawableDroplet(tiny) { Scale = new Vector2(0.5f) });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Droplet droplet = tick as Droplet;
|
||||||
|
if (droplet != null)
|
||||||
|
AddNested(new DrawableDroplet(droplet));
|
||||||
|
|
||||||
|
Fruit fruit = tick as Fruit;
|
||||||
|
if (fruit != null)
|
||||||
|
AddNested(new DrawableFruit(fruit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AddNested(DrawableHitObject<CatchBaseHit> h)
|
||||||
|
{
|
||||||
|
((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false;
|
||||||
|
dropletContainer.Add(h);
|
||||||
|
base.AddNested(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs
Normal file
43
osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// 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.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces
|
||||||
|
{
|
||||||
|
public class Pulp : Circle, IHasAccentColour
|
||||||
|
{
|
||||||
|
public const float PULP_SIZE = 20;
|
||||||
|
|
||||||
|
public Pulp()
|
||||||
|
{
|
||||||
|
Size = new Vector2(PULP_SIZE);
|
||||||
|
|
||||||
|
Blending = BlendingMode.Additive;
|
||||||
|
Colour = Color4.White.Opacity(0.9f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color4 accentColour;
|
||||||
|
public Color4 AccentColour
|
||||||
|
{
|
||||||
|
get { return accentColour; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
accentColour = value;
|
||||||
|
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Radius = 5,
|
||||||
|
Colour = accentColour.Lighten(100),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
169
osu.Game.Rulesets.Catch/Objects/JuiceStream.cs
Normal file
169
osu.Game.Rulesets.Catch/Objects/JuiceStream.cs
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
// Copyright (c) 2007-2017 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 System.Linq;
|
||||||
|
using osu.Game.Audio;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Lists;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects
|
||||||
|
{
|
||||||
|
public class JuiceStream : CatchBaseHit, IHasCurve
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Positional distance that results in a duration of one second, before any speed adjustments.
|
||||||
|
/// </summary>
|
||||||
|
private const float base_scoring_distance = 100;
|
||||||
|
|
||||||
|
public readonly SliderCurve Curve = new SliderCurve();
|
||||||
|
|
||||||
|
public int RepeatCount { get; set; } = 1;
|
||||||
|
|
||||||
|
public double Velocity;
|
||||||
|
public double TickDistance;
|
||||||
|
|
||||||
|
public override void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||||
|
{
|
||||||
|
base.ApplyDefaults(controlPointInfo, difficulty);
|
||||||
|
|
||||||
|
TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime);
|
||||||
|
DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(StartTime);
|
||||||
|
|
||||||
|
double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier;
|
||||||
|
|
||||||
|
Velocity = scoringDistance / timingPoint.BeatLength;
|
||||||
|
TickDistance = scoringDistance / difficulty.SliderTickRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<CatchBaseHit> Ticks
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
SortedList<CatchBaseHit> ticks = new SortedList<CatchBaseHit>((a, b) => a.StartTime.CompareTo(b.StartTime));
|
||||||
|
|
||||||
|
if (TickDistance == 0)
|
||||||
|
return ticks;
|
||||||
|
|
||||||
|
var length = Curve.Distance;
|
||||||
|
var tickDistance = Math.Min(TickDistance, length);
|
||||||
|
var repeatDuration = length / Velocity;
|
||||||
|
|
||||||
|
var minDistanceFromEnd = Velocity * 0.01;
|
||||||
|
|
||||||
|
ticks.Add(new Fruit
|
||||||
|
{
|
||||||
|
Samples = Samples,
|
||||||
|
ComboColour = ComboColour,
|
||||||
|
StartTime = StartTime,
|
||||||
|
X = X
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var repeat = 0; repeat < RepeatCount; repeat++)
|
||||||
|
{
|
||||||
|
var repeatStartTime = StartTime + repeat * repeatDuration;
|
||||||
|
var reversed = repeat % 2 == 1;
|
||||||
|
|
||||||
|
for (var d = tickDistance; d <= length; d += tickDistance)
|
||||||
|
{
|
||||||
|
if (d > length - minDistanceFromEnd)
|
||||||
|
break;
|
||||||
|
|
||||||
|
var timeProgress = d / length;
|
||||||
|
var distanceProgress = reversed ? 1 - timeProgress : timeProgress;
|
||||||
|
|
||||||
|
var lastTickTime = repeatStartTime + timeProgress * repeatDuration;
|
||||||
|
ticks.Add(new Droplet
|
||||||
|
{
|
||||||
|
StartTime = lastTickTime,
|
||||||
|
ComboColour = ComboColour,
|
||||||
|
X = Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH,
|
||||||
|
Samples = new SampleInfoList(Samples.Select(s => new SampleInfo
|
||||||
|
{
|
||||||
|
Bank = s.Bank,
|
||||||
|
Name = @"slidertick",
|
||||||
|
Volume = s.Volume
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
double tinyTickInterval = tickDistance / length * repeatDuration;
|
||||||
|
while (tinyTickInterval > 100)
|
||||||
|
tinyTickInterval /= 2;
|
||||||
|
|
||||||
|
for (double t = 0; t < repeatDuration; t += tinyTickInterval)
|
||||||
|
{
|
||||||
|
double progress = reversed ? 1 - t / repeatDuration : t / repeatDuration;
|
||||||
|
|
||||||
|
ticks.Add(new TinyDroplet
|
||||||
|
{
|
||||||
|
StartTime = repeatStartTime + t,
|
||||||
|
ComboColour = ComboColour,
|
||||||
|
X = Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH,
|
||||||
|
Samples = new SampleInfoList(Samples.Select(s => new SampleInfo
|
||||||
|
{
|
||||||
|
Bank = s.Bank,
|
||||||
|
Name = @"slidertick",
|
||||||
|
Volume = s.Volume
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ticks.Add(new Fruit
|
||||||
|
{
|
||||||
|
Samples = Samples,
|
||||||
|
ComboColour = ComboColour,
|
||||||
|
StartTime = repeatStartTime + repeatDuration,
|
||||||
|
X = Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ticks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double EndTime => StartTime + RepeatCount * Curve.Distance / Velocity;
|
||||||
|
|
||||||
|
public float EndX => Curve.PositionAt(ProgressAt(1)).X / CatchPlayfield.BASE_WIDTH;
|
||||||
|
|
||||||
|
public double Duration => EndTime - StartTime;
|
||||||
|
|
||||||
|
public double Distance
|
||||||
|
{
|
||||||
|
get { return Curve.Distance; }
|
||||||
|
set { Curve.Distance = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Vector2> ControlPoints
|
||||||
|
{
|
||||||
|
get { return Curve.ControlPoints; }
|
||||||
|
set { Curve.ControlPoints = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SampleInfoList> RepeatSamples { get; set; } = new List<SampleInfoList>();
|
||||||
|
|
||||||
|
public CurveType CurveType
|
||||||
|
{
|
||||||
|
get { return Curve.CurveType; }
|
||||||
|
set { Curve.CurveType = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
9
osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs
Normal file
9
osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects
|
||||||
|
{
|
||||||
|
public class TinyDroplet : Droplet
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -21,6 +21,19 @@ namespace osu.Game.Rulesets.Catch.Scoring
|
|||||||
{
|
{
|
||||||
foreach (var obj in beatmap.HitObjects)
|
foreach (var obj in beatmap.HitObjects)
|
||||||
{
|
{
|
||||||
|
var stream = obj as JuiceStream;
|
||||||
|
|
||||||
|
if (stream != null)
|
||||||
|
{
|
||||||
|
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
|
||||||
|
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
|
||||||
|
|
||||||
|
foreach (var unused in stream.Ticks)
|
||||||
|
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var fruit = obj as Fruit;
|
var fruit = obj as Fruit;
|
||||||
|
|
||||||
if (fruit != null)
|
if (fruit != null)
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
{
|
{
|
||||||
@ -13,15 +11,5 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
public TestCaseCatchPlayer() : base(typeof(CatchRuleset))
|
public TestCaseCatchPlayer() : base(typeof(CatchRuleset))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Beatmap CreateBeatmap()
|
|
||||||
{
|
|
||||||
var beatmap = new Beatmap();
|
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++)
|
|
||||||
beatmap.HitObjects.Add(new Fruit { X = 0.5f, StartTime = i * 100, NewCombo = i % 8 == 0 });
|
|
||||||
|
|
||||||
return beatmap;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
osu.Game.Rulesets.Catch/Tests/TestCaseCatchStacker.cs
Normal file
27
osu.Game.Rulesets.Catch/Tests/TestCaseCatchStacker.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestCaseCatchStacker : Game.Tests.Visual.TestCasePlayer
|
||||||
|
{
|
||||||
|
public TestCaseCatchStacker() : base(typeof(CatchRuleset))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Beatmap CreateBeatmap()
|
||||||
|
{
|
||||||
|
var beatmap = new Beatmap();
|
||||||
|
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
beatmap.HitObjects.Add(new Fruit { X = 0.5f, StartTime = i * 100, NewCombo = i % 8 == 0 });
|
||||||
|
|
||||||
|
return beatmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
public class CatchPlayfield : ScrollingPlayfield
|
public class CatchPlayfield : ScrollingPlayfield
|
||||||
{
|
{
|
||||||
|
public static readonly float BASE_WIDTH = 512;
|
||||||
|
|
||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
private readonly Container<Drawable> content;
|
private readonly Container<Drawable> content;
|
||||||
|
|
||||||
@ -28,8 +30,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
Reversed.Value = true;
|
Reversed.Value = true;
|
||||||
|
|
||||||
Size = new Vector2(1);
|
|
||||||
|
|
||||||
Anchor = Anchor.TopCentre;
|
Anchor = Anchor.TopCentre;
|
||||||
Origin = Anchor.TopCentre;
|
Origin = Anchor.TopCentre;
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
base.Add(h);
|
base.Add(h);
|
||||||
|
|
||||||
var fruit = (DrawableFruit)h;
|
var fruit = (DrawableCatchHitObject)h;
|
||||||
fruit.CheckPosition = CheckIfWeCanCatch;
|
fruit.CheckPosition = CheckIfWeCanCatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,11 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
if (judgement.IsHit)
|
if (judgement.IsHit)
|
||||||
{
|
{
|
||||||
Vector2 screenPosition = judgedObject.ScreenSpaceDrawQuad.Centre;
|
Vector2 screenPosition = judgedObject.ScreenSpaceDrawQuad.Centre;
|
||||||
Remove(judgedObject);
|
|
||||||
|
// todo: don't do this
|
||||||
|
(judgedObject.Parent as Container<DrawableHitObject>)?.Remove(judgedObject);
|
||||||
|
(judgedObject.Parent as Container)?.Remove(judgedObject);
|
||||||
|
|
||||||
catcher.Add(judgedObject, screenPosition);
|
catcher.Add(judgedObject, screenPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,13 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
protected override DrawableHitObject<CatchBaseHit> GetVisualRepresentation(CatchBaseHit h)
|
protected override DrawableHitObject<CatchBaseHit> GetVisualRepresentation(CatchBaseHit h)
|
||||||
{
|
{
|
||||||
if (h is Fruit)
|
var fruit = h as Fruit;
|
||||||
return new DrawableFruit(h);
|
if (fruit != null)
|
||||||
|
return new DrawableFruit(fruit);
|
||||||
|
|
||||||
|
var stream = h as JuiceStream;
|
||||||
|
if (stream != null)
|
||||||
|
return new DrawableJuiceStream(stream);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -50,14 +50,21 @@
|
|||||||
<Compile Include="Beatmaps\CatchBeatmapProcessor.cs" />
|
<Compile Include="Beatmaps\CatchBeatmapProcessor.cs" />
|
||||||
<Compile Include="CatchDifficultyCalculator.cs" />
|
<Compile Include="CatchDifficultyCalculator.cs" />
|
||||||
<Compile Include="CatchInputManager.cs" />
|
<Compile Include="CatchInputManager.cs" />
|
||||||
|
<Compile Include="Objects\Drawable\DrawableCatchHitObject.cs" />
|
||||||
|
<Compile Include="Objects\Drawable\DrawableDroplet.cs" />
|
||||||
|
<Compile Include="Objects\Drawable\DrawableJuiceStream.cs" />
|
||||||
|
<Compile Include="Objects\Drawable\Pieces\Pulp.cs" />
|
||||||
|
<Compile Include="Objects\JuiceStream.cs" />
|
||||||
<Compile Include="Scoring\CatchScoreProcessor.cs" />
|
<Compile Include="Scoring\CatchScoreProcessor.cs" />
|
||||||
<Compile Include="Judgements\CatchJudgement.cs" />
|
<Compile Include="Judgements\CatchJudgement.cs" />
|
||||||
<Compile Include="Objects\CatchBaseHit.cs" />
|
<Compile Include="Objects\CatchBaseHit.cs" />
|
||||||
<Compile Include="Objects\Drawable\DrawableFruit.cs" />
|
<Compile Include="Objects\Drawable\DrawableFruit.cs" />
|
||||||
<Compile Include="Objects\Droplet.cs" />
|
<Compile Include="Objects\Droplet.cs" />
|
||||||
<Compile Include="Objects\Fruit.cs" />
|
<Compile Include="Objects\Fruit.cs" />
|
||||||
|
<Compile Include="Objects\TinyDroplet.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Tests\TestCaseCatcher.cs" />
|
<Compile Include="Tests\TestCaseCatcher.cs" />
|
||||||
|
<Compile Include="Tests\TestCaseCatchStacker.cs" />
|
||||||
<Compile Include="Tests\TestCaseCatchPlayer.cs" />
|
<Compile Include="Tests\TestCaseCatchPlayer.cs" />
|
||||||
<Compile Include="UI\Catcher.cs" />
|
<Compile Include="UI\Catcher.cs" />
|
||||||
<Compile Include="UI\CatchRulesetContainer.cs" />
|
<Compile Include="UI\CatchRulesetContainer.cs" />
|
||||||
@ -79,11 +86,6 @@
|
|||||||
<Name>osu.Framework</Name>
|
<Name>osu.Framework</Name>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj">
|
|
||||||
<Project>{C92A607B-1FDD-4954-9F92-03FF547D9080}</Project>
|
|
||||||
<Name>osu.Game.Rulesets.Osu</Name>
|
|
||||||
<Private>False</Private>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
|
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
|
||||||
<Project>{2a66dd92-adb1-4994-89e2-c94e04acda0d}</Project>
|
<Project>{2a66dd92-adb1-4994-89e2-c94e04acda0d}</Project>
|
||||||
<Name>osu.Game</Name>
|
<Name>osu.Game</Name>
|
||||||
|
@ -200,4 +200,4 @@ namespace osu.Game.Rulesets.Objects
|
|||||||
return interpolateVertices(indexOfDistance(d), d) + Offset;
|
return interpolateVertices(indexOfDistance(d), d) + Offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user