mirror of
https://github.com/osukey/osukey.git
synced 2025-08-06 16:13:57 +09:00
Merge pull request #13934 from ekrctb/catcher-area-catcher
Move `Catcher` from `CatcherArea` to `CatchPlayfield`
This commit is contained in:
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -24,16 +23,12 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
{
|
{
|
||||||
public class TestSceneCatchSkinConfiguration : OsuTestScene
|
public class TestSceneCatchSkinConfiguration : OsuTestScene
|
||||||
{
|
{
|
||||||
[Cached]
|
|
||||||
private readonly DroppedObjectContainer droppedObjectContainer;
|
|
||||||
|
|
||||||
private Catcher catcher;
|
private Catcher catcher;
|
||||||
|
|
||||||
private readonly Container container;
|
private readonly Container container;
|
||||||
|
|
||||||
public TestSceneCatchSkinConfiguration()
|
public TestSceneCatchSkinConfiguration()
|
||||||
{
|
{
|
||||||
Add(droppedObjectContainer = new DroppedObjectContainer());
|
|
||||||
Add(container = new Container { RelativeSizeAxes = Axes.Both });
|
Add(container = new Container { RelativeSizeAxes = Axes.Both });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +41,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
var skin = new TestSkin { FlipCatcherPlate = flip };
|
var skin = new TestSkin { FlipCatcherPlate = flip };
|
||||||
container.Child = new SkinProvidingContainer(skin)
|
container.Child = new SkinProvidingContainer(skin)
|
||||||
{
|
{
|
||||||
Child = catcher = new Catcher(new Container())
|
Child = catcher = new Catcher(new Container(), new DroppedObjectContainer())
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre
|
Anchor = Anchor.Centre
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,12 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuConfigManager config { get; set; }
|
private OsuConfigManager config { get; set; }
|
||||||
|
|
||||||
private TestCatcher catcher;
|
private Container trailContainer;
|
||||||
|
|
||||||
private DroppedObjectContainer droppedObjectContainer;
|
private DroppedObjectContainer droppedObjectContainer;
|
||||||
|
|
||||||
|
private TestCatcher catcher;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() => Schedule(() =>
|
public void SetUp() => Schedule(() =>
|
||||||
{
|
{
|
||||||
@ -43,24 +45,18 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
CircleSize = 0,
|
CircleSize = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
var trailContainer = new Container
|
trailContainer = new Container();
|
||||||
|
droppedObjectContainer = new DroppedObjectContainer();
|
||||||
|
|
||||||
|
Child = new Container
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
};
|
|
||||||
droppedObjectContainer = new DroppedObjectContainer();
|
|
||||||
Child = new DependencyProvidingContainer
|
|
||||||
{
|
|
||||||
CachedDependencies = new (Type, object)[]
|
|
||||||
{
|
|
||||||
(typeof(DroppedObjectContainer), droppedObjectContainer),
|
|
||||||
},
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
droppedObjectContainer,
|
droppedObjectContainer,
|
||||||
catcher = new TestCatcher(trailContainer, difficulty),
|
catcher = new TestCatcher(trailContainer, droppedObjectContainer, difficulty),
|
||||||
trailContainer
|
trailContainer,
|
||||||
},
|
}
|
||||||
Anchor = Anchor.Centre
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -298,8 +294,8 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
{
|
{
|
||||||
public IEnumerable<CaughtObject> CaughtObjects => this.ChildrenOfType<CaughtObject>();
|
public IEnumerable<CaughtObject> CaughtObjects => this.ChildrenOfType<CaughtObject>();
|
||||||
|
|
||||||
public TestCatcher(Container trailsTarget, BeatmapDifficulty difficulty)
|
public TestCatcher(Container trailsTarget, DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty)
|
||||||
: base(trailsTarget, difficulty)
|
: base(trailsTarget, droppedObjectTarget, difficulty)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
{
|
{
|
||||||
area.OnNewResult(drawable, new CatchJudgementResult(fruit, new CatchJudgement())
|
area.OnNewResult(drawable, new CatchJudgementResult(fruit, new CatchJudgement())
|
||||||
{
|
{
|
||||||
Type = area.MovableCatcher.CanCatch(fruit) ? HitResult.Great : HitResult.Miss
|
Type = area.Catcher.CanCatch(fruit) ? HitResult.Great : HitResult.Miss
|
||||||
});
|
});
|
||||||
|
|
||||||
drawable.Expire();
|
drawable.Expire();
|
||||||
@ -119,16 +119,19 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
private class TestCatcherArea : CatcherArea
|
private class TestCatcherArea : CatcherArea
|
||||||
{
|
{
|
||||||
[Cached]
|
|
||||||
private readonly DroppedObjectContainer droppedObjectContainer;
|
|
||||||
|
|
||||||
public TestCatcherArea(BeatmapDifficulty beatmapDifficulty)
|
public TestCatcherArea(BeatmapDifficulty beatmapDifficulty)
|
||||||
: base(beatmapDifficulty)
|
|
||||||
{
|
{
|
||||||
AddInternal(droppedObjectContainer = new DroppedObjectContainer());
|
var droppedObjectContainer = new DroppedObjectContainer();
|
||||||
|
|
||||||
|
Add(droppedObjectContainer);
|
||||||
|
|
||||||
|
Catcher = new Catcher(this, droppedObjectContainer, beatmapDifficulty)
|
||||||
|
{
|
||||||
|
X = CatchPlayfield.CENTER_X
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ToggleHyperDash(bool status) => MovableCatcher.SetHyperDashState(status ? 2 : 1);
|
public void ToggleHyperDash(bool status) => Catcher.SetHyperDashState(status ? 2 : 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
private bool playfieldIsEmpty => !((CatchPlayfield)drawableRuleset.Playfield).AllHitObjects.Any(h => h.IsAlive);
|
private bool playfieldIsEmpty => !((CatchPlayfield)drawableRuleset.Playfield).AllHitObjects.Any(h => h.IsAlive);
|
||||||
|
|
||||||
private CatcherAnimationState catcherState => ((CatchPlayfield)drawableRuleset.Playfield).CatcherArea.MovableCatcher.CurrentState;
|
private CatcherAnimationState catcherState => ((CatchPlayfield)drawableRuleset.Playfield).Catcher.CurrentState;
|
||||||
|
|
||||||
private void spawnFruits(bool hit = false)
|
private void spawnFruits(bool hit = false)
|
||||||
{
|
{
|
||||||
@ -162,7 +162,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
float xCoords = CatchPlayfield.CENTER_X;
|
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.Catcher.X = xCoords - x_offset;
|
||||||
|
|
||||||
if (hit)
|
if (hit)
|
||||||
xCoords -= x_offset;
|
xCoords -= x_offset;
|
||||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
// this needs to be done within the frame stable context due to how quickly hyperdash state changes occur.
|
// this needs to be done within the frame stable context due to how quickly hyperdash state changes occur.
|
||||||
Player.DrawableRuleset.FrameStableComponents.OnUpdate += d =>
|
Player.DrawableRuleset.FrameStableComponents.OnUpdate += d =>
|
||||||
{
|
{
|
||||||
var catcher = Player.ChildrenOfType<CatcherArea>().FirstOrDefault()?.MovableCatcher;
|
var catcher = Player.ChildrenOfType<Catcher>().FirstOrDefault();
|
||||||
|
|
||||||
if (catcher == null)
|
if (catcher == null)
|
||||||
return;
|
return;
|
||||||
|
@ -113,36 +113,45 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
private void checkHyperDashCatcherColour(ISkin skin, Color4 expectedCatcherColour, Color4? expectedEndGlowColour = null)
|
private void checkHyperDashCatcherColour(ISkin skin, Color4 expectedCatcherColour, Color4? expectedEndGlowColour = null)
|
||||||
{
|
{
|
||||||
CatcherArea catcherArea = null;
|
Container trailsContainer = null;
|
||||||
|
Catcher catcher = null;
|
||||||
CatcherTrailDisplay trails = null;
|
CatcherTrailDisplay trails = null;
|
||||||
|
|
||||||
AddStep("create hyper-dashing catcher", () =>
|
AddStep("create hyper-dashing catcher", () =>
|
||||||
{
|
{
|
||||||
Child = setupSkinHierarchy(catcherArea = new TestCatcherArea
|
trailsContainer = new Container();
|
||||||
|
Child = setupSkinHierarchy(new Container
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
catcher = new Catcher(trailsContainer, new DroppedObjectContainer())
|
||||||
|
{
|
||||||
|
Scale = new Vector2(4)
|
||||||
|
},
|
||||||
|
trailsContainer
|
||||||
|
}
|
||||||
}, skin);
|
}, skin);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("get trails container", () =>
|
AddStep("get trails container", () =>
|
||||||
{
|
{
|
||||||
trails = catcherArea.OfType<CatcherTrailDisplay>().Single();
|
trails = trailsContainer.OfType<CatcherTrailDisplay>().Single();
|
||||||
catcherArea.MovableCatcher.SetHyperDashState(2);
|
catcher.SetHyperDashState(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("catcher colour is correct", () => catcherArea.MovableCatcher.Colour == expectedCatcherColour);
|
AddUntilStep("catcher colour is correct", () => catcher.Colour == expectedCatcherColour);
|
||||||
|
|
||||||
AddAssert("catcher trails colours are correct", () => trails.HyperDashTrailsColour == expectedCatcherColour);
|
AddAssert("catcher trails colours are correct", () => trails.HyperDashTrailsColour == expectedCatcherColour);
|
||||||
AddAssert("catcher end-glow colours are correct", () => trails.EndGlowSpritesColour == (expectedEndGlowColour ?? expectedCatcherColour));
|
AddAssert("catcher end-glow colours are correct", () => trails.EndGlowSpritesColour == (expectedEndGlowColour ?? expectedCatcherColour));
|
||||||
|
|
||||||
AddStep("finish hyper-dashing", () =>
|
AddStep("finish hyper-dashing", () =>
|
||||||
{
|
{
|
||||||
catcherArea.MovableCatcher.SetHyperDashState();
|
catcher.SetHyperDashState();
|
||||||
catcherArea.MovableCatcher.FinishTransforms();
|
catcher.FinishTransforms();
|
||||||
});
|
});
|
||||||
|
|
||||||
AddAssert("catcher colour returned to white", () => catcherArea.MovableCatcher.Colour == Color4.White);
|
AddAssert("catcher colour returned to white", () => catcher.Colour == Color4.White);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkHyperDashFruitColour(ISkin skin, Color4 expectedColour)
|
private void checkHyperDashFruitColour(ISkin skin, Color4 expectedColour)
|
||||||
@ -205,18 +214,5 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestCatcherArea : CatcherArea
|
|
||||||
{
|
|
||||||
[Cached]
|
|
||||||
private readonly DroppedObjectContainer droppedObjectContainer;
|
|
||||||
|
|
||||||
public TestCatcherArea()
|
|
||||||
{
|
|
||||||
Scale = new Vector2(4f);
|
|
||||||
|
|
||||||
AddInternal(droppedObjectContainer = new DroppedObjectContainer());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Catch.Edit
|
|||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
// TODO: honor "hit animation" setting?
|
// TODO: honor "hit animation" setting?
|
||||||
CatcherArea.MovableCatcher.CatchFruitOnPlate = false;
|
Catcher.CatchFruitOnPlate = false;
|
||||||
|
|
||||||
// TODO: disable hit lighting as well
|
// TODO: disable hit lighting as well
|
||||||
}
|
}
|
||||||
|
@ -41,9 +41,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
|||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
var catcherArea = playfield.CatcherArea;
|
FlashlightPosition = playfield.CatcherArea.ToSpaceOfOtherDrawable(playfield.Catcher.DrawPosition, this);
|
||||||
|
|
||||||
FlashlightPosition = catcherArea.ToSpaceOfOtherDrawable(catcherArea.MovableCatcher.DrawPosition, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getSizeFor(int combo)
|
private float getSizeFor(int combo)
|
||||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
|||||||
var drawableCatchRuleset = (DrawableCatchRuleset)drawableRuleset;
|
var drawableCatchRuleset = (DrawableCatchRuleset)drawableRuleset;
|
||||||
var catchPlayfield = (CatchPlayfield)drawableCatchRuleset.Playfield;
|
var catchPlayfield = (CatchPlayfield)drawableCatchRuleset.Playfield;
|
||||||
|
|
||||||
catchPlayfield.CatcherArea.MovableCatcher.CatchFruitOnPlate = false;
|
catchPlayfield.Catcher.CatchFruitOnPlate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||||
|
@ -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 * 0.3f * 0.5f;
|
const float catcher_width_half = Catcher.BASE_SIZE * 0.3f * 0.5f;
|
||||||
|
|
||||||
if (lastPosition - catcher_width_half < h.EffectiveX && lastPosition + catcher_width_half > h.EffectiveX)
|
if (lastPosition - catcher_width_half < h.EffectiveX && lastPosition + catcher_width_half > h.EffectiveX)
|
||||||
{
|
{
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
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.Objects.Drawables;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
@ -26,38 +27,53 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const float CENTER_X = WIDTH / 2;
|
public const float CENTER_X = WIDTH / 2;
|
||||||
|
|
||||||
[Cached]
|
|
||||||
private readonly DroppedObjectContainer droppedObjectContainer;
|
|
||||||
|
|
||||||
internal readonly CatcherArea CatcherArea;
|
|
||||||
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
|
||||||
// only check the X position; handle all vertical space.
|
// only check the X position; handle all vertical space.
|
||||||
base.ReceivePositionalInputAt(new Vector2(screenSpacePos.X, ScreenSpaceDrawQuad.Centre.Y));
|
base.ReceivePositionalInputAt(new Vector2(screenSpacePos.X, ScreenSpaceDrawQuad.Centre.Y));
|
||||||
|
|
||||||
|
internal Catcher Catcher { get; private set; }
|
||||||
|
|
||||||
|
internal CatcherArea CatcherArea { get; private set; }
|
||||||
|
|
||||||
|
private readonly BeatmapDifficulty difficulty;
|
||||||
|
|
||||||
public CatchPlayfield(BeatmapDifficulty difficulty)
|
public CatchPlayfield(BeatmapDifficulty difficulty)
|
||||||
{
|
{
|
||||||
CatcherArea = new CatcherArea(difficulty)
|
this.difficulty = difficulty;
|
||||||
{
|
|
||||||
Anchor = Anchor.BottomLeft,
|
|
||||||
Origin = Anchor.TopLeft,
|
|
||||||
};
|
|
||||||
|
|
||||||
InternalChildren = new[]
|
|
||||||
{
|
|
||||||
droppedObjectContainer = new DroppedObjectContainer(),
|
|
||||||
CatcherArea.MovableCatcher.CreateProxiedContent(),
|
|
||||||
HitObjectContainer.CreateProxy(),
|
|
||||||
// This ordering (`CatcherArea` before `HitObjectContainer`) is important to
|
|
||||||
// make sure the up-to-date catcher position is used for the catcher catching logic of hit objects.
|
|
||||||
CatcherArea,
|
|
||||||
HitObjectContainer,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
|
var trailContainer = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.TopLeft
|
||||||
|
};
|
||||||
|
var droppedObjectContainer = new DroppedObjectContainer();
|
||||||
|
|
||||||
|
Catcher = new Catcher(trailContainer, droppedObjectContainer, difficulty)
|
||||||
|
{
|
||||||
|
X = CENTER_X
|
||||||
|
};
|
||||||
|
|
||||||
|
AddRangeInternal(new[]
|
||||||
|
{
|
||||||
|
droppedObjectContainer,
|
||||||
|
Catcher.CreateProxiedContent(),
|
||||||
|
HitObjectContainer.CreateProxy(),
|
||||||
|
// This ordering (`CatcherArea` before `HitObjectContainer`) is important to
|
||||||
|
// make sure the up-to-date catcher position is used for the catcher catching logic of hit objects.
|
||||||
|
CatcherArea = new CatcherArea
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.TopLeft,
|
||||||
|
Catcher = Catcher,
|
||||||
|
},
|
||||||
|
trailContainer,
|
||||||
|
HitObjectContainer,
|
||||||
|
});
|
||||||
|
|
||||||
RegisterPool<Droplet, DrawableDroplet>(50);
|
RegisterPool<Droplet, DrawableDroplet>(50);
|
||||||
RegisterPool<TinyDroplet, DrawableTinyDroplet>(50);
|
RegisterPool<TinyDroplet, DrawableTinyDroplet>(50);
|
||||||
RegisterPool<Fruit, DrawableFruit>(100);
|
RegisterPool<Fruit, DrawableFruit>(100);
|
||||||
@ -80,7 +96,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
((DrawableCatchHitObject)d).CheckPosition = checkIfWeCanCatch;
|
((DrawableCatchHitObject)d).CheckPosition = checkIfWeCanCatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool checkIfWeCanCatch(CatchHitObject obj) => CatcherArea.MovableCatcher.CanCatch(obj);
|
private bool checkIfWeCanCatch(CatchHitObject obj) => Catcher.CanCatch(obj);
|
||||||
|
|
||||||
private void onNewResult(DrawableHitObject judgedObject, JudgementResult result)
|
private void onNewResult(DrawableHitObject judgedObject, JudgementResult result)
|
||||||
=> CatcherArea.OnNewResult((DrawableCatchHitObject)judgedObject, result);
|
=> CatcherArea.OnNewResult((DrawableCatchHitObject)judgedObject, result);
|
||||||
|
@ -21,6 +21,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override ReplayFrame HandleFrame(Vector2 mousePosition, List<CatchAction> actions, ReplayFrame previousFrame)
|
protected override ReplayFrame HandleFrame(Vector2 mousePosition, List<CatchAction> actions, ReplayFrame previousFrame)
|
||||||
=> new CatchReplayFrame(Time.Current, playfield.CatcherArea.MovableCatcher.X, actions.Contains(CatchAction.Dash), previousFrame as CatchReplayFrame);
|
=> new CatchReplayFrame(Time.Current, playfield.Catcher.X, actions.Contains(CatchAction.Dash), previousFrame as CatchReplayFrame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,16 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
public class Catcher : SkinReloadableDrawable
|
public class Catcher : SkinReloadableDrawable
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The size of the catcher at 1x scale.
|
||||||
|
/// </summary>
|
||||||
|
public const float BASE_SIZE = 106.75f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The width of the catcher which can receive fruit. Equivalent to "catchMargin" in osu-stable.
|
||||||
|
/// </summary>
|
||||||
|
public const float ALLOWED_CATCH_RANGE = 0.8f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default colour used to tint hyper-dash fruit, along with the moving catcher, its trail
|
/// The default colour used to tint hyper-dash fruit, along with the moving catcher, its trail
|
||||||
/// and end glow/after-image during a hyper-dash.
|
/// and end glow/after-image during a hyper-dash.
|
||||||
@ -74,8 +84,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains objects dropped from the plate.
|
/// Contains objects dropped from the plate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Resolved]
|
private readonly DroppedObjectContainer droppedObjectTarget;
|
||||||
private DroppedObjectContainer droppedObjectTarget { get; set; }
|
|
||||||
|
|
||||||
public CatcherAnimationState CurrentState
|
public CatcherAnimationState CurrentState
|
||||||
{
|
{
|
||||||
@ -83,11 +92,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
private set => Body.AnimationState.Value = value;
|
private set => Body.AnimationState.Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The width of the catcher which can receive fruit. Equivalent to "catchMargin" in osu-stable.
|
|
||||||
/// </summary>
|
|
||||||
public const float ALLOWED_CATCH_RANGE = 0.8f;
|
|
||||||
|
|
||||||
private bool dashing;
|
private bool dashing;
|
||||||
|
|
||||||
public bool Dashing
|
public bool Dashing
|
||||||
@ -134,13 +138,14 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
private readonly DrawablePool<CaughtBanana> caughtBananaPool;
|
private readonly DrawablePool<CaughtBanana> caughtBananaPool;
|
||||||
private readonly DrawablePool<CaughtDroplet> caughtDropletPool;
|
private readonly DrawablePool<CaughtDroplet> caughtDropletPool;
|
||||||
|
|
||||||
public Catcher([NotNull] Container trailsTarget, BeatmapDifficulty difficulty = null)
|
public Catcher([NotNull] Container trailsTarget, [NotNull] DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty = null)
|
||||||
{
|
{
|
||||||
this.trailsTarget = trailsTarget;
|
this.trailsTarget = trailsTarget;
|
||||||
|
this.droppedObjectTarget = droppedObjectTarget;
|
||||||
|
|
||||||
Origin = Anchor.TopCentre;
|
Origin = Anchor.TopCentre;
|
||||||
|
|
||||||
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
Size = new Vector2(BASE_SIZE);
|
||||||
if (difficulty != null)
|
if (difficulty != null)
|
||||||
Scale = calculateScale(difficulty);
|
Scale = calculateScale(difficulty);
|
||||||
|
|
||||||
@ -197,7 +202,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
/// Calculates the width of the area used for attempting catches in gameplay.
|
/// Calculates the width of the area used for attempting catches in gameplay.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="scale">The scale of the catcher.</param>
|
/// <param name="scale">The scale of the catcher.</param>
|
||||||
public static float CalculateCatchWidth(Vector2 scale) => CatcherArea.CATCHER_SIZE * Math.Abs(scale.X) * ALLOWED_CATCH_RANGE;
|
public static float CalculateCatchWidth(Vector2 scale) => BASE_SIZE * Math.Abs(scale.X) * ALLOWED_CATCH_RANGE;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates the width of the area used for attempting catches in gameplay.
|
/// Calculates the width of the area used for attempting catches in gameplay.
|
||||||
|
@ -5,7 +5,6 @@ using System;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Rulesets.Catch.Judgements;
|
using osu.Game.Rulesets.Catch.Judgements;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Catch.Replays;
|
using osu.Game.Rulesets.Catch.Replays;
|
||||||
@ -16,13 +15,29 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.UI
|
namespace osu.Game.Rulesets.Catch.UI
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The horizontal band at the bottom of the playfield the catcher is moving on.
|
||||||
|
/// It holds a <see cref="Catcher"/> as a child and translates input to the catcher movement.
|
||||||
|
/// It also holds a combo display that is above the catcher, and judgment results are translated to the catcher and the combo display.
|
||||||
|
/// </summary>
|
||||||
public class CatcherArea : Container, IKeyBindingHandler<CatchAction>
|
public class CatcherArea : Container, IKeyBindingHandler<CatchAction>
|
||||||
{
|
{
|
||||||
public const float CATCHER_SIZE = 106.75f;
|
public Catcher Catcher
|
||||||
|
{
|
||||||
|
get => catcher;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (catcher != null)
|
||||||
|
Remove(catcher);
|
||||||
|
|
||||||
|
Add(catcher = value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public readonly Catcher MovableCatcher;
|
|
||||||
private readonly CatchComboDisplay comboDisplay;
|
private readonly CatchComboDisplay comboDisplay;
|
||||||
|
|
||||||
|
private Catcher catcher;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <c>-1</c> when only left button is pressed.
|
/// <c>-1</c> when only left button is pressed.
|
||||||
/// <c>1</c> when only right button is pressed.
|
/// <c>1</c> when only right button is pressed.
|
||||||
@ -30,27 +45,26 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private int currentDirection;
|
private int currentDirection;
|
||||||
|
|
||||||
public CatcherArea(BeatmapDifficulty difficulty = null)
|
/// <remarks>
|
||||||
|
/// <see cref="Catcher"/> must be set before loading.
|
||||||
|
/// </remarks>
|
||||||
|
public CatcherArea()
|
||||||
{
|
{
|
||||||
Size = new Vector2(CatchPlayfield.WIDTH, CATCHER_SIZE);
|
Size = new Vector2(CatchPlayfield.WIDTH, Catcher.BASE_SIZE);
|
||||||
Children = new Drawable[]
|
Child = comboDisplay = new CatchComboDisplay
|
||||||
{
|
{
|
||||||
comboDisplay = new CatchComboDisplay
|
RelativeSizeAxes = Axes.None,
|
||||||
{
|
AutoSizeAxes = Axes.Both,
|
||||||
RelativeSizeAxes = Axes.None,
|
Anchor = Anchor.TopLeft,
|
||||||
AutoSizeAxes = Axes.Both,
|
Origin = Anchor.Centre,
|
||||||
Anchor = Anchor.TopLeft,
|
Margin = new MarginPadding { Bottom = 350f },
|
||||||
Origin = Anchor.Centre,
|
X = CatchPlayfield.CENTER_X
|
||||||
Margin = new MarginPadding { Bottom = 350f },
|
|
||||||
X = CatchPlayfield.CENTER_X
|
|
||||||
},
|
|
||||||
MovableCatcher = new Catcher(this, difficulty) { X = CatchPlayfield.CENTER_X },
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnNewResult(DrawableCatchHitObject hitObject, JudgementResult result)
|
public void OnNewResult(DrawableCatchHitObject hitObject, JudgementResult result)
|
||||||
{
|
{
|
||||||
MovableCatcher.OnNewResult(hitObject, result);
|
Catcher.OnNewResult(hitObject, result);
|
||||||
|
|
||||||
if (!result.Type.IsScorable())
|
if (!result.Type.IsScorable())
|
||||||
return;
|
return;
|
||||||
@ -58,9 +72,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
if (hitObject.HitObject.LastInCombo)
|
if (hitObject.HitObject.LastInCombo)
|
||||||
{
|
{
|
||||||
if (result.Judgement is CatchJudgement catchJudgement && catchJudgement.ShouldExplodeFor(result))
|
if (result.Judgement is CatchJudgement catchJudgement && catchJudgement.ShouldExplodeFor(result))
|
||||||
MovableCatcher.Explode();
|
Catcher.Explode();
|
||||||
else
|
else
|
||||||
MovableCatcher.Drop();
|
Catcher.Drop();
|
||||||
}
|
}
|
||||||
|
|
||||||
comboDisplay.OnNewResult(hitObject, result);
|
comboDisplay.OnNewResult(hitObject, result);
|
||||||
@ -69,7 +83,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
public void OnRevertResult(DrawableCatchHitObject hitObject, JudgementResult result)
|
public void OnRevertResult(DrawableCatchHitObject hitObject, JudgementResult result)
|
||||||
{
|
{
|
||||||
comboDisplay.OnRevertResult(hitObject, result);
|
comboDisplay.OnRevertResult(hitObject, result);
|
||||||
MovableCatcher.OnRevertResult(hitObject, result);
|
Catcher.OnRevertResult(hitObject, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
@ -80,27 +94,27 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
SetCatcherPosition(
|
SetCatcherPosition(
|
||||||
replayState?.CatcherX ??
|
replayState?.CatcherX ??
|
||||||
(float)(MovableCatcher.X + MovableCatcher.Speed * currentDirection * Clock.ElapsedFrameTime));
|
(float)(Catcher.X + Catcher.Speed * currentDirection * Clock.ElapsedFrameTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateAfterChildren()
|
protected override void UpdateAfterChildren()
|
||||||
{
|
{
|
||||||
base.UpdateAfterChildren();
|
base.UpdateAfterChildren();
|
||||||
|
|
||||||
comboDisplay.X = MovableCatcher.X;
|
comboDisplay.X = Catcher.X;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetCatcherPosition(float X)
|
public void SetCatcherPosition(float X)
|
||||||
{
|
{
|
||||||
float lastPosition = MovableCatcher.X;
|
float lastPosition = Catcher.X;
|
||||||
float newPosition = Math.Clamp(X, 0, CatchPlayfield.WIDTH);
|
float newPosition = Math.Clamp(X, 0, CatchPlayfield.WIDTH);
|
||||||
|
|
||||||
MovableCatcher.X = newPosition;
|
Catcher.X = newPosition;
|
||||||
|
|
||||||
if (lastPosition < newPosition)
|
if (lastPosition < newPosition)
|
||||||
MovableCatcher.VisualDirection = Direction.Right;
|
Catcher.VisualDirection = Direction.Right;
|
||||||
else if (lastPosition > newPosition)
|
else if (lastPosition > newPosition)
|
||||||
MovableCatcher.VisualDirection = Direction.Left;
|
Catcher.VisualDirection = Direction.Left;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OnPressed(CatchAction action)
|
public bool OnPressed(CatchAction action)
|
||||||
@ -116,7 +130,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case CatchAction.Dash:
|
case CatchAction.Dash:
|
||||||
MovableCatcher.Dashing = true;
|
Catcher.Dashing = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +150,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CatchAction.Dash:
|
case CatchAction.Dash:
|
||||||
MovableCatcher.Dashing = false;
|
Catcher.Dashing = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
public CatcherTrail()
|
public CatcherTrail()
|
||||||
{
|
{
|
||||||
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
Size = new Vector2(Catcher.BASE_SIZE);
|
||||||
Origin = Anchor.TopCentre;
|
Origin = Anchor.TopCentre;
|
||||||
Blending = BlendingParameters.Additive;
|
Blending = BlendingParameters.Additive;
|
||||||
InternalChild = body = new SkinnableCatcher
|
InternalChild = body = new SkinnableCatcher
|
||||||
|
@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre;
|
Anchor = Anchor.TopCentre;
|
||||||
// Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling.
|
// Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling.
|
||||||
OriginPosition = new Vector2(0.5f, 0.06f) * CatcherArea.CATCHER_SIZE;
|
OriginPosition = new Vector2(0.5f, 0.06f) * Catcher.BASE_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AssignedValueIsNeverUsed/@EntryIndexedValue">HINT</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AssignedValueIsNeverUsed/@EntryIndexedValue">HINT</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AssignmentIsFullyDiscarded/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AssignmentIsFullyDiscarded/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AssignNullToNotNullAttribute/@EntryIndexedValue">WARNING</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AssignNullToNotNullAttribute/@EntryIndexedValue">WARNING</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AutoPropertyCanBeMadeGetOnly_002EGlobal/@EntryIndexedValue">WARNING</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AutoPropertyCanBeMadeGetOnly_002EGlobal/@EntryIndexedValue">HINT</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AutoPropertyCanBeMadeGetOnly_002ELocal/@EntryIndexedValue">WARNING</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AutoPropertyCanBeMadeGetOnly_002ELocal/@EntryIndexedValue">HINT</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadAttributeBracketsSpaces/@EntryIndexedValue">WARNING</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadAttributeBracketsSpaces/@EntryIndexedValue">WARNING</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadBracesSpaces/@EntryIndexedValue">WARNING</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadBracesSpaces/@EntryIndexedValue">WARNING</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadChildStatementIndent/@EntryIndexedValue">WARNING</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadChildStatementIndent/@EntryIndexedValue">WARNING</s:String>
|
||||||
|
Reference in New Issue
Block a user