mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 15:07:44 +08:00
Merge pull request #10956 from ekrctb/palpable-catch-hit-object
Move some members from `CatchHitObject` to `PalpableCatchHitObject` to make it more specific
This commit is contained in:
commit
5889b74eba
@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
hitObject.Scale = 1.5f;
|
||||
|
||||
if (hyperdash)
|
||||
hitObject.HyperDashTarget = new Banana();
|
||||
((PalpableCatchHitObject)hitObject).HyperDashTarget = new Banana();
|
||||
|
||||
d.Anchor = Anchor.Centre;
|
||||
d.RelativePositionAxes = Axes.None;
|
||||
|
@ -5,11 +5,11 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.MathUtils;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Catch.MathUtils;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||
{
|
||||
@ -192,24 +192,24 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||
|
||||
private static void initialiseHyperDash(IBeatmap beatmap)
|
||||
{
|
||||
List<CatchHitObject> objectWithDroplets = new List<CatchHitObject>();
|
||||
List<PalpableCatchHitObject> palpableObjects = new List<PalpableCatchHitObject>();
|
||||
|
||||
foreach (var currentObject in beatmap.HitObjects)
|
||||
{
|
||||
if (currentObject is Fruit fruitObject)
|
||||
objectWithDroplets.Add(fruitObject);
|
||||
palpableObjects.Add(fruitObject);
|
||||
|
||||
if (currentObject is JuiceStream)
|
||||
{
|
||||
foreach (var currentJuiceElement in currentObject.NestedHitObjects)
|
||||
foreach (var juice in currentObject.NestedHitObjects)
|
||||
{
|
||||
if (!(currentJuiceElement is TinyDroplet))
|
||||
objectWithDroplets.Add((CatchHitObject)currentJuiceElement);
|
||||
if (juice is PalpableCatchHitObject palpableObject && !(juice is TinyDroplet))
|
||||
palpableObjects.Add(palpableObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
objectWithDroplets.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime));
|
||||
palpableObjects.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime));
|
||||
|
||||
double halfCatcherWidth = Catcher.CalculateCatchWidth(beatmap.BeatmapInfo.BaseDifficulty) / 2;
|
||||
|
||||
@ -221,10 +221,10 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||
int lastDirection = 0;
|
||||
double lastExcess = halfCatcherWidth;
|
||||
|
||||
for (int i = 0; i < objectWithDroplets.Count - 1; i++)
|
||||
for (int i = 0; i < palpableObjects.Count - 1; i++)
|
||||
{
|
||||
CatchHitObject currentObject = objectWithDroplets[i];
|
||||
CatchHitObject nextObject = objectWithDroplets[i + 1];
|
||||
var currentObject = palpableObjects[i];
|
||||
var nextObject = palpableObjects[i + 1];
|
||||
|
||||
// Reset variables in-case values have changed (e.g. after applying HR)
|
||||
currentObject.HyperDashTarget = null;
|
||||
|
@ -12,9 +12,9 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing
|
||||
{
|
||||
private const float normalized_hitobject_radius = 41.0f;
|
||||
|
||||
public new CatchHitObject BaseObject => (CatchHitObject)base.BaseObject;
|
||||
public new PalpableCatchHitObject BaseObject => (PalpableCatchHitObject)base.BaseObject;
|
||||
|
||||
public new CatchHitObject LastObject => (CatchHitObject)base.LastObject;
|
||||
public new PalpableCatchHitObject LastObject => (PalpableCatchHitObject)base.LastObject;
|
||||
|
||||
public readonly float NormalizedPosition;
|
||||
public readonly float LastNormalizedPosition;
|
||||
|
@ -27,11 +27,6 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
set => x = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether this object can be placed on the catcher's plate.
|
||||
/// </summary>
|
||||
public virtual bool CanBePlated => false;
|
||||
|
||||
/// <summary>
|
||||
/// A random offset applied to <see cref="X"/>, set by the <see cref="CatchBeatmapProcessor"/>.
|
||||
/// </summary>
|
||||
@ -63,13 +58,6 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
set => ComboIndexBindable.Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Difference between the distance to the next object
|
||||
/// and the distance that would have triggered a hyper dash.
|
||||
/// A value close to 0 indicates a difficult jump (for difficulty calculation).
|
||||
/// </summary>
|
||||
public float DistanceToHyperDash { get; set; }
|
||||
|
||||
public Bindable<bool> LastInComboBindable { get; } = new Bindable<bool>();
|
||||
|
||||
/// <summary>
|
||||
@ -83,16 +71,6 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
|
||||
public float Scale { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this fruit can initiate a hyperdash.
|
||||
/// </summary>
|
||||
public bool HyperDash => HyperDashTarget != null;
|
||||
|
||||
/// <summary>
|
||||
/// The target fruit if we are to initiate a hyperdash.
|
||||
/// </summary>
|
||||
public CatchHitObject HyperDashTarget;
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
@ -105,14 +83,6 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single object that can be caught by the catcher.
|
||||
/// </summary>
|
||||
public abstract class PalpableCatchHitObject : CatchHitObject
|
||||
{
|
||||
public override bool CanBePlated => true;
|
||||
}
|
||||
|
||||
public enum FruitVisualRepresentation
|
||||
{
|
||||
Pear,
|
||||
|
@ -2,55 +2,16 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
{
|
||||
public abstract class PalpableDrawableCatchHitObject : DrawableCatchHitObject
|
||||
{
|
||||
protected Container ScaleContainer { get; private set; }
|
||||
|
||||
protected PalpableDrawableCatchHitObject(CatchHitObject hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
Origin = Anchor.Centre;
|
||||
Size = new Vector2(CatchHitObject.OBJECT_RADIUS * 2);
|
||||
Masking = false;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
ScaleContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
}
|
||||
});
|
||||
|
||||
ScaleContainer.Scale = new Vector2(HitObject.Scale);
|
||||
}
|
||||
|
||||
protected override Color4 GetComboColour(IReadOnlyList<Color4> comboColours) =>
|
||||
comboColours[(HitObject.IndexInBeatmap + 1) % comboColours.Count];
|
||||
}
|
||||
|
||||
public abstract class DrawableCatchHitObject : DrawableHitObject<CatchHitObject>
|
||||
{
|
||||
protected override double InitialLifetimeOffset => HitObject.TimePreempt;
|
||||
|
||||
public virtual bool StaysOnPlate => HitObject.CanBePlated;
|
||||
|
||||
public float DisplayRadius => DrawSize.X / 2 * Scale.X * HitObject.Scale;
|
||||
|
||||
protected override float SamplePlaybackPosition => HitObject.X / CatchPlayfield.WIDTH;
|
||||
|
@ -8,7 +8,7 @@ using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
{
|
||||
public class DrawableDroplet : PalpableDrawableCatchHitObject
|
||||
public class DrawableDroplet : DrawablePalpableCatchHitObject
|
||||
{
|
||||
public override bool StaysOnPlate => false;
|
||||
|
||||
|
@ -8,7 +8,7 @@ using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
{
|
||||
public class DrawableFruit : PalpableDrawableCatchHitObject
|
||||
public class DrawableFruit : DrawablePalpableCatchHitObject
|
||||
{
|
||||
public DrawableFruit(CatchHitObject h)
|
||||
: base(h)
|
||||
|
@ -0,0 +1,47 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
{
|
||||
public abstract class DrawablePalpableCatchHitObject : DrawableCatchHitObject
|
||||
{
|
||||
public new PalpableCatchHitObject HitObject => (PalpableCatchHitObject)base.HitObject;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this hit object should stay on the catcher plate when the object is caught by the catcher.
|
||||
/// </summary>
|
||||
public virtual bool StaysOnPlate => true;
|
||||
|
||||
protected readonly Container ScaleContainer;
|
||||
|
||||
protected DrawablePalpableCatchHitObject(CatchHitObject h)
|
||||
: base(h)
|
||||
{
|
||||
Origin = Anchor.Centre;
|
||||
Size = new Vector2(CatchHitObject.OBJECT_RADIUS * 2);
|
||||
|
||||
AddInternal(ScaleContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
});
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
ScaleContainer.Scale = new Vector2(HitObject.Scale);
|
||||
}
|
||||
|
||||
protected override Color4 GetComboColour(IReadOnlyList<Color4> comboColours) =>
|
||||
comboColours[(HitObject.IndexInBeatmap + 1) % comboColours.Count];
|
||||
}
|
||||
}
|
@ -22,8 +22,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(DrawableHitObject drawableObject)
|
||||
{
|
||||
DrawableCatchHitObject drawableCatchObject = (DrawableCatchHitObject)drawableObject;
|
||||
var hitObject = drawableCatchObject.HitObject;
|
||||
var drawableCatchObject = (DrawablePalpableCatchHitObject)drawableObject;
|
||||
|
||||
InternalChild = new Pulp
|
||||
{
|
||||
@ -31,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
AccentColour = { BindTarget = drawableObject.AccentColour }
|
||||
};
|
||||
|
||||
if (hitObject.HyperDash)
|
||||
if (drawableCatchObject.HitObject.HyperDash)
|
||||
{
|
||||
AddInternal(new Container
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
public const float RADIUS_ADJUST = 1.1f;
|
||||
|
||||
private Circle border;
|
||||
private CatchHitObject hitObject;
|
||||
private PalpableCatchHitObject hitObject;
|
||||
|
||||
public FruitPiece()
|
||||
{
|
||||
@ -30,12 +30,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(DrawableHitObject drawableObject)
|
||||
{
|
||||
DrawableCatchHitObject drawableCatchObject = (DrawableCatchHitObject)drawableObject;
|
||||
var drawableCatchObject = (DrawablePalpableCatchHitObject)drawableObject;
|
||||
hitObject = drawableCatchObject.HitObject;
|
||||
|
||||
AddRangeInternal(new[]
|
||||
{
|
||||
getFruitFor(drawableCatchObject.HitObject.VisualRepresentation),
|
||||
getFruitFor(hitObject.VisualRepresentation),
|
||||
border = new Circle
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
|
29
osu.Game.Rulesets.Catch/Objects/PalpableCatchHitObject.cs
Normal file
29
osu.Game.Rulesets.Catch/Objects/PalpableCatchHitObject.cs
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single object that can be caught by the catcher.
|
||||
/// This includes normal fruits, droplets, and bananas but excludes objects that act only as a container of nested hit objects.
|
||||
/// </summary>
|
||||
public abstract class PalpableCatchHitObject : CatchHitObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Difference between the distance to the next object
|
||||
/// and the distance that would have triggered a hyper dash.
|
||||
/// A value close to 0 indicates a difficult jump (for difficulty calculation).
|
||||
/// </summary>
|
||||
public float DistanceToHyperDash { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this fruit can initiate a hyperdash.
|
||||
/// </summary>
|
||||
public bool HyperDash => HyperDashTarget != null;
|
||||
|
||||
/// <summary>
|
||||
/// The target fruit if we are to initiate a hyperdash.
|
||||
/// </summary>
|
||||
public CatchHitObject HyperDashTarget;
|
||||
}
|
||||
}
|
@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Catch.Replays
|
||||
float lastPosition = CatchPlayfield.CENTER_X;
|
||||
double lastTime = 0;
|
||||
|
||||
void moveToNext(CatchHitObject h)
|
||||
void moveToNext(PalpableCatchHitObject h)
|
||||
{
|
||||
float positionChange = Math.Abs(lastPosition - h.X);
|
||||
double timeAvailable = h.StartTime - lastTime;
|
||||
@ -101,23 +101,16 @@ namespace osu.Game.Rulesets.Catch.Replays
|
||||
|
||||
foreach (var obj in Beatmap.HitObjects)
|
||||
{
|
||||
switch (obj)
|
||||
if (obj is PalpableCatchHitObject palpableObject)
|
||||
{
|
||||
case Fruit _:
|
||||
moveToNext(obj);
|
||||
break;
|
||||
moveToNext(palpableObject);
|
||||
}
|
||||
|
||||
foreach (var nestedObj in obj.NestedHitObjects.Cast<CatchHitObject>())
|
||||
{
|
||||
switch (nestedObj)
|
||||
if (nestedObj is PalpableCatchHitObject palpableNestedObject)
|
||||
{
|
||||
case Banana _:
|
||||
case TinyDroplet _:
|
||||
case Droplet _:
|
||||
case Fruit _:
|
||||
moveToNext(nestedObj);
|
||||
break;
|
||||
moveToNext(palpableNestedObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Catch.Skinning
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(DrawableHitObject drawableObject, ISkinSource skin)
|
||||
{
|
||||
DrawableCatchHitObject drawableCatchObject = (DrawableCatchHitObject)drawableObject;
|
||||
var drawableCatchObject = (DrawablePalpableCatchHitObject)drawableObject;
|
||||
|
||||
accentColour.BindTo(drawableCatchObject.AccentColour);
|
||||
|
||||
|
@ -220,11 +220,11 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
/// <summary>
|
||||
/// Let the catcher attempt to catch a fruit.
|
||||
/// </summary>
|
||||
/// <param name="fruit">The fruit to catch.</param>
|
||||
/// <param name="hitObject">The fruit to catch.</param>
|
||||
/// <returns>Whether the catch is possible.</returns>
|
||||
public bool AttemptCatch(CatchHitObject fruit)
|
||||
public bool AttemptCatch(CatchHitObject hitObject)
|
||||
{
|
||||
if (!fruit.CanBePlated)
|
||||
if (!(hitObject is PalpableCatchHitObject fruit))
|
||||
return false;
|
||||
|
||||
var halfCatchWidth = catchWidth * 0.5f;
|
||||
|
@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
};
|
||||
}
|
||||
|
||||
public void OnNewResult(DrawableCatchHitObject fruit, JudgementResult result)
|
||||
public void OnNewResult(DrawableCatchHitObject hitObject, JudgementResult result)
|
||||
{
|
||||
if (!result.Type.IsScorable())
|
||||
return;
|
||||
@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
lastPlateableFruit.OnLoadComplete += _ => action();
|
||||
}
|
||||
|
||||
if (result.IsHit && fruit.HitObject.CanBePlated)
|
||||
if (result.IsHit && hitObject is DrawablePalpableCatchHitObject fruit)
|
||||
{
|
||||
// create a new (cloned) fruit to stay on the plate. the original is faded out immediately.
|
||||
var caughtFruit = (DrawableCatchHitObject)CreateDrawableRepresentation?.Invoke(fruit.HitObject);
|
||||
@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
if (caughtFruit == null) return;
|
||||
|
||||
caughtFruit.RelativePositionAxes = Axes.None;
|
||||
caughtFruit.Position = new Vector2(MovableCatcher.ToLocalSpace(fruit.ScreenSpaceDrawQuad.Centre).X - MovableCatcher.DrawSize.X / 2, 0);
|
||||
caughtFruit.Position = new Vector2(MovableCatcher.ToLocalSpace(hitObject.ScreenSpaceDrawQuad.Centre).X - MovableCatcher.DrawSize.X / 2, 0);
|
||||
caughtFruit.IsOnPlate = true;
|
||||
|
||||
caughtFruit.Anchor = Anchor.TopCentre;
|
||||
@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
runAfterLoaded(() => MovableCatcher.Explode(caughtFruit));
|
||||
}
|
||||
|
||||
if (fruit.HitObject.LastInCombo)
|
||||
if (hitObject.HitObject.LastInCombo)
|
||||
{
|
||||
if (result.Judgement is CatchJudgement catchJudgement && catchJudgement.ShouldExplodeFor(result))
|
||||
runAfterLoaded(() => MovableCatcher.Explode());
|
||||
@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
MovableCatcher.Drop();
|
||||
}
|
||||
|
||||
comboDisplay.OnNewResult(fruit, result);
|
||||
comboDisplay.OnNewResult(hitObject, result);
|
||||
}
|
||||
|
||||
public void OnRevertResult(DrawableCatchHitObject fruit, JudgementResult result)
|
||||
|
Loading…
Reference in New Issue
Block a user