mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 07:06:35 +09:00
Merge branch 'master' into mod-muted
This commit is contained in:
@ -3,7 +3,6 @@
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||
@ -45,14 +44,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var trailContainer = new Container
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.TopLeft
|
||||
};
|
||||
var droppedObjectContainer = new DroppedObjectContainer();
|
||||
|
||||
Catcher = new Catcher(trailContainer, droppedObjectContainer, difficulty)
|
||||
Catcher = new Catcher(droppedObjectContainer, difficulty)
|
||||
{
|
||||
X = CENTER_X
|
||||
};
|
||||
@ -70,7 +64,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
Origin = Anchor.TopLeft,
|
||||
Catcher = Catcher,
|
||||
},
|
||||
trailContainer,
|
||||
HitObjectContainer,
|
||||
});
|
||||
|
||||
|
@ -36,8 +36,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
public const float ALLOWED_CATCH_RANGE = 0.8f;
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// The default colour used to tint hyper-dash fruit, along with the moving catcher, its trail and after-image during a hyper-dash.
|
||||
/// </summary>
|
||||
public static readonly Color4 DEFAULT_HYPER_DASH_COLOUR = Color4.Red;
|
||||
|
||||
@ -71,11 +70,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
/// </summary>
|
||||
private const float caught_fruit_scale_adjust = 0.5f;
|
||||
|
||||
[NotNull]
|
||||
private readonly Container trailsTarget;
|
||||
|
||||
private CatcherTrailDisplay trails;
|
||||
|
||||
/// <summary>
|
||||
/// Contains caught objects on the plate.
|
||||
/// </summary>
|
||||
@ -88,30 +82,22 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
public CatcherAnimationState CurrentState
|
||||
{
|
||||
get => Body.AnimationState.Value;
|
||||
private set => Body.AnimationState.Value = value;
|
||||
get => body.AnimationState.Value;
|
||||
private set => body.AnimationState.Value = value;
|
||||
}
|
||||
|
||||
private bool dashing;
|
||||
|
||||
public bool Dashing
|
||||
{
|
||||
get => dashing;
|
||||
set
|
||||
{
|
||||
if (value == dashing) return;
|
||||
|
||||
dashing = value;
|
||||
|
||||
updateTrailVisibility();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Whether the catcher is currently dashing.
|
||||
/// </summary>
|
||||
public bool Dashing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The currently facing direction.
|
||||
/// </summary>
|
||||
public Direction VisualDirection { get; set; } = Direction.Right;
|
||||
|
||||
public Vector2 BodyScale => Scale * body.Scale;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the contents of the catcher plate should be visually flipped when the catcher direction is changed.
|
||||
/// </summary>
|
||||
@ -122,10 +108,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
/// </summary>
|
||||
private readonly float catchWidth;
|
||||
|
||||
internal readonly SkinnableCatcher Body;
|
||||
private readonly SkinnableCatcher body;
|
||||
|
||||
private Color4 hyperDashColour = DEFAULT_HYPER_DASH_COLOUR;
|
||||
private Color4 hyperDashEndGlowColour = DEFAULT_HYPER_DASH_COLOUR;
|
||||
|
||||
private double hyperDashModifier = 1;
|
||||
private int hyperDashDirection;
|
||||
@ -138,9 +123,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
private readonly DrawablePool<CaughtBanana> caughtBananaPool;
|
||||
private readonly DrawablePool<CaughtDroplet> caughtDropletPool;
|
||||
|
||||
public Catcher([NotNull] Container trailsTarget, [NotNull] DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty = null)
|
||||
public Catcher([NotNull] DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty = null)
|
||||
{
|
||||
this.trailsTarget = trailsTarget;
|
||||
this.droppedObjectTarget = droppedObjectTarget;
|
||||
|
||||
Origin = Anchor.TopCentre;
|
||||
@ -164,7 +148,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
// offset fruit vertically to better place "above" the plate.
|
||||
Y = -5
|
||||
},
|
||||
Body = new SkinnableCatcher(),
|
||||
body = new SkinnableCatcher(),
|
||||
hitExplosionContainer = new HitExplosionContainer
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
@ -177,15 +161,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
private void load(OsuConfigManager config)
|
||||
{
|
||||
hitLighting = config.GetBindable<bool>(OsuSetting.HitLighting);
|
||||
trails = new CatcherTrailDisplay(this);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
// don't add in above load as we may potentially modify a parent in an unsafe manner.
|
||||
trailsTarget.Add(trails);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -307,10 +282,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
hyperDashTargetPosition = targetPosition;
|
||||
|
||||
if (!wasHyperDashing)
|
||||
{
|
||||
trails.DisplayEndGlow();
|
||||
runHyperDashStateTransition(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,13 +298,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
private void runHyperDashStateTransition(bool hyperDashing)
|
||||
{
|
||||
updateTrailVisibility();
|
||||
|
||||
this.FadeColour(hyperDashing ? hyperDashColour : Color4.White, HYPER_DASH_TRANSITION_DURATION, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void updateTrailVisibility() => trails.DisplayTrail = Dashing || HyperDashing;
|
||||
|
||||
protected override void SkinChanged(ISkinSource skin)
|
||||
{
|
||||
base.SkinChanged(skin);
|
||||
@ -341,13 +309,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDash)?.Value ??
|
||||
DEFAULT_HYPER_DASH_COLOUR;
|
||||
|
||||
hyperDashEndGlowColour =
|
||||
skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDashAfterImage)?.Value ??
|
||||
hyperDashColour;
|
||||
|
||||
trails.HyperDashTrailsColour = hyperDashColour;
|
||||
trails.EndGlowSpritesColour = hyperDashEndGlowColour;
|
||||
|
||||
flipCatcherPlate = skin.GetConfig<CatchSkinConfiguration, bool>(CatchSkinConfiguration.FlipCatcherPlate)?.Value ?? true;
|
||||
|
||||
runHyperDashStateTransition(HyperDashing);
|
||||
@ -358,7 +319,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
base.Update();
|
||||
|
||||
var scaleFromDirection = new Vector2((int)VisualDirection, 1);
|
||||
Body.Scale = scaleFromDirection;
|
||||
body.Scale = scaleFromDirection;
|
||||
caughtObjectContainer.Scale = hitExplosionContainer.Scale = flipCatcherPlate ? scaleFromDirection : Vector2.One;
|
||||
|
||||
// Correct overshooting.
|
||||
|
@ -25,17 +25,15 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
public Catcher Catcher
|
||||
{
|
||||
get => catcher;
|
||||
set
|
||||
{
|
||||
if (catcher != null)
|
||||
Remove(catcher);
|
||||
|
||||
Add(catcher = value);
|
||||
}
|
||||
set => catcherContainer.Child = catcher = value;
|
||||
}
|
||||
|
||||
private readonly Container<Catcher> catcherContainer;
|
||||
|
||||
private readonly CatchComboDisplay comboDisplay;
|
||||
|
||||
private readonly CatcherTrailDisplay catcherTrails;
|
||||
|
||||
private Catcher catcher;
|
||||
|
||||
/// <summary>
|
||||
@ -45,20 +43,28 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
/// </summary>
|
||||
private int currentDirection;
|
||||
|
||||
// TODO: support replay rewind
|
||||
private bool lastHyperDashState;
|
||||
|
||||
/// <remarks>
|
||||
/// <see cref="Catcher"/> must be set before loading.
|
||||
/// </remarks>
|
||||
public CatcherArea()
|
||||
{
|
||||
Size = new Vector2(CatchPlayfield.WIDTH, Catcher.BASE_SIZE);
|
||||
Child = comboDisplay = new CatchComboDisplay
|
||||
Children = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.None,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.Centre,
|
||||
Margin = new MarginPadding { Bottom = 350f },
|
||||
X = CatchPlayfield.CENTER_X
|
||||
catcherContainer = new Container<Catcher> { RelativeSizeAxes = Axes.Both },
|
||||
catcherTrails = new CatcherTrailDisplay(),
|
||||
comboDisplay = new CatchComboDisplay
|
||||
{
|
||||
RelativeSizeAxes = Axes.None,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.Centre,
|
||||
Margin = new MarginPadding { Bottom = 350f },
|
||||
X = CatchPlayfield.CENTER_X
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -102,6 +108,19 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
base.UpdateAfterChildren();
|
||||
|
||||
comboDisplay.X = Catcher.X;
|
||||
|
||||
if (!lastHyperDashState && Catcher.HyperDashing && Time.Elapsed > 0)
|
||||
catcherTrails.DisplayHyperDashAfterImage(Catcher.CurrentState, Catcher.X, Catcher.BodyScale);
|
||||
|
||||
if (Catcher.Dashing || Catcher.HyperDashing)
|
||||
{
|
||||
double generationInterval = Catcher.HyperDashing ? 25 : 50;
|
||||
|
||||
if (Time.Current - catcherTrails.LastDashTrailTime >= generationInterval)
|
||||
catcherTrails.DisplayDashTrail(Catcher.CurrentState, Catcher.X, Catcher.BodyScale, Catcher.HyperDashing);
|
||||
}
|
||||
|
||||
lastHyperDashState = Catcher.HyperDashing;
|
||||
}
|
||||
|
||||
public void SetCatcherPosition(float X)
|
||||
|
@ -2,10 +2,11 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Game.Rulesets.Catch.Skinning;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -15,70 +16,27 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
/// Represents a component responsible for displaying
|
||||
/// the appropriate catcher trails when requested to.
|
||||
/// </summary>
|
||||
public class CatcherTrailDisplay : CompositeDrawable
|
||||
public class CatcherTrailDisplay : SkinReloadableDrawable
|
||||
{
|
||||
private readonly Catcher catcher;
|
||||
/// <summary>
|
||||
/// The most recent time a dash trail was added to this container.
|
||||
/// Only alive (not faded out) trails are considered.
|
||||
/// Returns <see cref="double.NegativeInfinity"/> if no dash trail is alive.
|
||||
/// </summary>
|
||||
public double LastDashTrailTime => getLastDashTrailTime();
|
||||
|
||||
public Color4 HyperDashTrailsColour => hyperDashTrails.Colour;
|
||||
|
||||
public Color4 HyperDashAfterImageColour => hyperDashAfterImages.Colour;
|
||||
|
||||
private readonly DrawablePool<CatcherTrail> trailPool;
|
||||
|
||||
private readonly Container<CatcherTrail> dashTrails;
|
||||
private readonly Container<CatcherTrail> hyperDashTrails;
|
||||
private readonly Container<CatcherTrail> endGlowSprites;
|
||||
private readonly Container<CatcherTrail> hyperDashAfterImages;
|
||||
|
||||
private Color4 hyperDashTrailsColour = Catcher.DEFAULT_HYPER_DASH_COLOUR;
|
||||
|
||||
public Color4 HyperDashTrailsColour
|
||||
public CatcherTrailDisplay()
|
||||
{
|
||||
get => hyperDashTrailsColour;
|
||||
set
|
||||
{
|
||||
if (hyperDashTrailsColour == value)
|
||||
return;
|
||||
|
||||
hyperDashTrailsColour = value;
|
||||
hyperDashTrails.Colour = hyperDashTrailsColour;
|
||||
}
|
||||
}
|
||||
|
||||
private Color4 endGlowSpritesColour = Catcher.DEFAULT_HYPER_DASH_COLOUR;
|
||||
|
||||
public Color4 EndGlowSpritesColour
|
||||
{
|
||||
get => endGlowSpritesColour;
|
||||
set
|
||||
{
|
||||
if (endGlowSpritesColour == value)
|
||||
return;
|
||||
|
||||
endGlowSpritesColour = value;
|
||||
endGlowSprites.Colour = endGlowSpritesColour;
|
||||
}
|
||||
}
|
||||
|
||||
private bool trail;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to start displaying trails following the catcher.
|
||||
/// </summary>
|
||||
public bool DisplayTrail
|
||||
{
|
||||
get => trail;
|
||||
set
|
||||
{
|
||||
if (trail == value)
|
||||
return;
|
||||
|
||||
trail = value;
|
||||
|
||||
if (trail)
|
||||
displayTrail();
|
||||
}
|
||||
}
|
||||
|
||||
public CatcherTrailDisplay([NotNull] Catcher catcher)
|
||||
{
|
||||
this.catcher = catcher ?? throw new ArgumentNullException(nameof(catcher));
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
@ -86,47 +44,68 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
trailPool = new DrawablePool<CatcherTrail>(30),
|
||||
dashTrails = new Container<CatcherTrail> { RelativeSizeAxes = Axes.Both },
|
||||
hyperDashTrails = new Container<CatcherTrail> { RelativeSizeAxes = Axes.Both, Colour = Catcher.DEFAULT_HYPER_DASH_COLOUR },
|
||||
endGlowSprites = new Container<CatcherTrail> { RelativeSizeAxes = Axes.Both, Colour = Catcher.DEFAULT_HYPER_DASH_COLOUR },
|
||||
hyperDashAfterImages = new Container<CatcherTrail> { RelativeSizeAxes = Axes.Both, Colour = Catcher.DEFAULT_HYPER_DASH_COLOUR },
|
||||
};
|
||||
}
|
||||
|
||||
protected override void SkinChanged(ISkinSource skin)
|
||||
{
|
||||
base.SkinChanged(skin);
|
||||
|
||||
hyperDashTrails.Colour = skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDash)?.Value ?? Catcher.DEFAULT_HYPER_DASH_COLOUR;
|
||||
hyperDashAfterImages.Colour = skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDashAfterImage)?.Value ?? hyperDashTrails.Colour;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays a single end-glow catcher sprite.
|
||||
/// Displays a hyper-dash after-image of the catcher.
|
||||
/// </summary>
|
||||
public void DisplayEndGlow()
|
||||
public void DisplayHyperDashAfterImage(CatcherAnimationState animationState, float x, Vector2 scale)
|
||||
{
|
||||
var endGlow = createTrailSprite(endGlowSprites);
|
||||
var trail = createTrail(animationState, x, scale);
|
||||
|
||||
endGlow.MoveToOffset(new Vector2(0, -10), 1200, Easing.In);
|
||||
endGlow.ScaleTo(endGlow.Scale * 0.95f).ScaleTo(endGlow.Scale * 1.2f, 1200, Easing.In);
|
||||
endGlow.FadeOut(1200);
|
||||
endGlow.Expire(true);
|
||||
hyperDashAfterImages.Add(trail);
|
||||
|
||||
trail.MoveToOffset(new Vector2(0, -10), 1200, Easing.In);
|
||||
trail.ScaleTo(trail.Scale * 0.95f).ScaleTo(trail.Scale * 1.2f, 1200, Easing.In);
|
||||
trail.FadeOut(1200);
|
||||
trail.Expire(true);
|
||||
}
|
||||
|
||||
private void displayTrail()
|
||||
public void DisplayDashTrail(CatcherAnimationState animationState, float x, Vector2 scale, bool hyperDashing)
|
||||
{
|
||||
if (!DisplayTrail)
|
||||
return;
|
||||
var trail = createTrail(animationState, x, scale);
|
||||
|
||||
var sprite = createTrailSprite(catcher.HyperDashing ? hyperDashTrails : dashTrails);
|
||||
if (hyperDashing)
|
||||
hyperDashTrails.Add(trail);
|
||||
else
|
||||
dashTrails.Add(trail);
|
||||
|
||||
sprite.FadeTo(0.4f).FadeOut(800, Easing.OutQuint);
|
||||
sprite.Expire(true);
|
||||
|
||||
Scheduler.AddDelayed(displayTrail, catcher.HyperDashing ? 25 : 50);
|
||||
trail.FadeTo(0.4f).FadeOut(800, Easing.OutQuint);
|
||||
trail.Expire(true);
|
||||
}
|
||||
|
||||
private CatcherTrail createTrailSprite(Container<CatcherTrail> target)
|
||||
private CatcherTrail createTrail(CatcherAnimationState animationState, float x, Vector2 scale)
|
||||
{
|
||||
CatcherTrail sprite = trailPool.Get();
|
||||
CatcherTrail trail = trailPool.Get();
|
||||
|
||||
sprite.AnimationState = catcher.CurrentState;
|
||||
sprite.Scale = catcher.Scale * catcher.Body.Scale;
|
||||
sprite.Position = catcher.Position;
|
||||
trail.AnimationState = animationState;
|
||||
trail.Scale = scale;
|
||||
trail.Position = new Vector2(x, 0);
|
||||
|
||||
target.Add(sprite);
|
||||
return trail;
|
||||
}
|
||||
|
||||
return sprite;
|
||||
private double getLastDashTrailTime()
|
||||
{
|
||||
double maxTime = double.NegativeInfinity;
|
||||
|
||||
foreach (var trail in dashTrails)
|
||||
maxTime = Math.Max(maxTime, trail.LifetimeStart);
|
||||
|
||||
foreach (var trail in hyperDashTrails)
|
||||
maxTime = Math.Max(maxTime, trail.LifetimeStart);
|
||||
|
||||
return maxTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user