mirror of
https://github.com/osukey/osukey.git
synced 2025-08-02 22:26:41 +09:00
Merge pull request #17622 from frenzibyte/taiko-target-classic-position
Replicate osu!(stable)'s hit target position with "Classic" mod
This commit is contained in:
@ -0,0 +1,19 @@
|
||||
// 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 osu.Game.Rulesets.Taiko.Mods;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
public class TestSceneTaikoPlayerLegacySkin : LegacySkinPlayerTestScene
|
||||
{
|
||||
protected override Ruleset CreatePlayerRuleset() => new TaikoRuleset();
|
||||
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
SelectedMods.Value = new[] { new TaikoModClassic() };
|
||||
return base.CreatePlayer(ruleset);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,6 +18,9 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
{
|
||||
drawableTaikoRuleset = (DrawableTaikoRuleset)drawableRuleset;
|
||||
drawableTaikoRuleset.LockPlayfieldAspect.Value = false;
|
||||
|
||||
var playfield = (TaikoPlayfield)drawableRuleset.Playfield;
|
||||
playfield.ClassicHitTargetPosition.Value = true;
|
||||
}
|
||||
|
||||
public void Update(Playfield playfield)
|
||||
|
@ -22,13 +22,14 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
/// </summary>
|
||||
internal class LegacyInputDrum : Container
|
||||
{
|
||||
private Container content;
|
||||
private LegacyHalfDrum left;
|
||||
private LegacyHalfDrum right;
|
||||
private Container content;
|
||||
|
||||
public LegacyInputDrum()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
AutoSizeAxes = Axes.X;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
@ -14,6 +14,7 @@ using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
@ -33,7 +34,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
sampleTriggerSource = new DrumSampleTriggerSource(hitObjectContainer);
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
AutoSizeAxes = Axes.X;
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -41,12 +43,32 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.InputDrum), _ => new Container
|
||||
new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.InputDrum), _ => new DefaultInputDrum())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
AutoSizeAxes = Axes.X,
|
||||
},
|
||||
sampleTriggerSource
|
||||
};
|
||||
}
|
||||
|
||||
private class DefaultInputDrum : AspectContainer
|
||||
{
|
||||
public DefaultInputDrum()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChild = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit,
|
||||
Scale = new Vector2(0.9f),
|
||||
Children = new Drawable[]
|
||||
Children = new[]
|
||||
{
|
||||
new TaikoHalfDrum(false)
|
||||
{
|
||||
@ -71,131 +93,130 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
CentreAction = TaikoAction.RightCentre
|
||||
}
|
||||
}
|
||||
}),
|
||||
sampleTriggerSource
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A half-drum. Contains one centre and one rim hit.
|
||||
/// </summary>
|
||||
private class TaikoHalfDrum : Container, IKeyBindingHandler<TaikoAction>
|
||||
{
|
||||
/// <summary>
|
||||
/// The key to be used for the rim of the half-drum.
|
||||
/// </summary>
|
||||
public TaikoAction RimAction;
|
||||
|
||||
/// <summary>
|
||||
/// The key to be used for the centre of the half-drum.
|
||||
/// </summary>
|
||||
public TaikoAction CentreAction;
|
||||
|
||||
private readonly Sprite rim;
|
||||
private readonly Sprite rimHit;
|
||||
private readonly Sprite centre;
|
||||
private readonly Sprite centreHit;
|
||||
|
||||
[Resolved]
|
||||
private DrumSampleTriggerSource sampleTriggerSource { get; set; }
|
||||
|
||||
public TaikoHalfDrum(bool flipped)
|
||||
{
|
||||
Masking = true;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
rim = new Sprite
|
||||
{
|
||||
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
rimHit = new Sprite
|
||||
{
|
||||
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
Blending = BlendingParameters.Additive,
|
||||
},
|
||||
centre = new Sprite
|
||||
{
|
||||
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(0.7f)
|
||||
},
|
||||
centreHit = new Sprite
|
||||
{
|
||||
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(0.7f),
|
||||
Alpha = 0,
|
||||
Blending = BlendingParameters.Additive
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures, OsuColour colours)
|
||||
/// <summary>
|
||||
/// A half-drum. Contains one centre and one rim hit.
|
||||
/// </summary>
|
||||
private class TaikoHalfDrum : Container, IKeyBindingHandler<TaikoAction>
|
||||
{
|
||||
rim.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer");
|
||||
rimHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer-hit");
|
||||
centre.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner");
|
||||
centreHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner-hit");
|
||||
/// <summary>
|
||||
/// The key to be used for the rim of the half-drum.
|
||||
/// </summary>
|
||||
public TaikoAction RimAction;
|
||||
|
||||
rimHit.Colour = colours.Blue;
|
||||
centreHit.Colour = colours.Pink;
|
||||
}
|
||||
/// <summary>
|
||||
/// The key to be used for the centre of the half-drum.
|
||||
/// </summary>
|
||||
public TaikoAction CentreAction;
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<TaikoAction> e)
|
||||
{
|
||||
Drawable target = null;
|
||||
Drawable back = null;
|
||||
private readonly Sprite rim;
|
||||
private readonly Sprite rimHit;
|
||||
private readonly Sprite centre;
|
||||
private readonly Sprite centreHit;
|
||||
|
||||
if (e.Action == CentreAction)
|
||||
[Resolved]
|
||||
private DrumSampleTriggerSource sampleTriggerSource { get; set; }
|
||||
|
||||
public TaikoHalfDrum(bool flipped)
|
||||
{
|
||||
target = centreHit;
|
||||
back = centre;
|
||||
Masking = true;
|
||||
|
||||
sampleTriggerSource.Play(HitType.Centre);
|
||||
}
|
||||
else if (e.Action == RimAction)
|
||||
{
|
||||
target = rimHit;
|
||||
back = rim;
|
||||
|
||||
sampleTriggerSource.Play(HitType.Rim);
|
||||
Children = new Drawable[]
|
||||
{
|
||||
rim = new Sprite
|
||||
{
|
||||
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
rimHit = new Sprite
|
||||
{
|
||||
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
Blending = BlendingParameters.Additive,
|
||||
},
|
||||
centre = new Sprite
|
||||
{
|
||||
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(0.7f)
|
||||
},
|
||||
centreHit = new Sprite
|
||||
{
|
||||
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(0.7f),
|
||||
Alpha = 0,
|
||||
Blending = BlendingParameters.Additive
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (target != null)
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures, OsuColour colours)
|
||||
{
|
||||
const float scale_amount = 0.05f;
|
||||
const float alpha_amount = 0.5f;
|
||||
rim.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer");
|
||||
rimHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer-hit");
|
||||
centre.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner");
|
||||
centreHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner-hit");
|
||||
|
||||
const float down_time = 40;
|
||||
const float up_time = 1000;
|
||||
|
||||
back.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint)
|
||||
.Then()
|
||||
.ScaleTo(1, up_time, Easing.OutQuint);
|
||||
|
||||
target.Animate(
|
||||
t => t.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint),
|
||||
t => t.FadeTo(Math.Min(target.Alpha + alpha_amount, 1), down_time, Easing.OutQuint)
|
||||
).Then(
|
||||
t => t.ScaleTo(1, up_time, Easing.OutQuint),
|
||||
t => t.FadeOut(up_time, Easing.OutQuint)
|
||||
);
|
||||
rimHit.Colour = colours.Blue;
|
||||
centreHit.Colour = colours.Pink;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
public bool OnPressed(KeyBindingPressEvent<TaikoAction> e)
|
||||
{
|
||||
Drawable target = null;
|
||||
Drawable back = null;
|
||||
|
||||
public void OnReleased(KeyBindingReleaseEvent<TaikoAction> e)
|
||||
{
|
||||
if (e.Action == CentreAction)
|
||||
{
|
||||
target = centreHit;
|
||||
back = centre;
|
||||
|
||||
sampleTriggerSource.Play(HitType.Centre);
|
||||
}
|
||||
else if (e.Action == RimAction)
|
||||
{
|
||||
target = rimHit;
|
||||
back = rim;
|
||||
|
||||
sampleTriggerSource.Play(HitType.Rim);
|
||||
}
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
const float scale_amount = 0.05f;
|
||||
const float alpha_amount = 0.5f;
|
||||
|
||||
const float down_time = 40;
|
||||
const float up_time = 1000;
|
||||
|
||||
back.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint)
|
||||
.Then()
|
||||
.ScaleTo(1, up_time, Easing.OutQuint);
|
||||
|
||||
target.Animate(
|
||||
t => t.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint),
|
||||
t => t.FadeTo(Math.Min(target.Alpha + alpha_amount, 1), down_time, Easing.OutQuint)
|
||||
).Then(
|
||||
t => t.ScaleTo(1, up_time, Easing.OutQuint),
|
||||
t => t.FadeOut(up_time, Easing.OutQuint)
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(KeyBindingReleaseEvent<TaikoAction> e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
@ -34,6 +35,11 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
/// </summary>
|
||||
public const float DEFAULT_HEIGHT = 200;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the hit target should be nudged further towards the left area, matching the stable "classic" position.
|
||||
/// </summary>
|
||||
public Bindable<bool> ClassicHitTargetPosition = new BindableBool();
|
||||
|
||||
private Container<HitExplosion> hitExplosionContainer;
|
||||
private Container<KiaiHitExplosion> kiaiExplosionContainer;
|
||||
private JudgementContainer<DrawableTaikoJudgement> judgementContainer;
|
||||
@ -45,8 +51,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
private readonly IDictionary<HitResult, HitExplosionPool> explosionPools = new Dictionary<HitResult, HitExplosionPool>();
|
||||
|
||||
private ProxyContainer topLevelHitContainer;
|
||||
private InputDrum inputDrum;
|
||||
private Container rightArea;
|
||||
private Container leftArea;
|
||||
|
||||
/// <remarks>
|
||||
/// <see cref="Playfield.AddNested"/> is purposefully not called on this to prevent i.e. being able to interact
|
||||
@ -54,14 +60,43 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
/// </remarks>
|
||||
private BarLinePlayfield barLinePlayfield;
|
||||
|
||||
private Container hitTargetOffsetContent;
|
||||
private Container playfieldContent;
|
||||
private Container playfieldOverlay;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
inputDrum = new InputDrum(HitObjectContainer)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
AutoSizeAxes = Axes.X,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
};
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.PlayfieldBackgroundRight), _ => new PlayfieldBackgroundRight()),
|
||||
new Container
|
||||
{
|
||||
Name = "Left overlay",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit,
|
||||
BorderColour = colours.Gray0,
|
||||
Children = new[]
|
||||
{
|
||||
new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.PlayfieldBackgroundLeft), _ => new PlayfieldBackgroundLeft()),
|
||||
inputDrum.CreateProxy(),
|
||||
}
|
||||
},
|
||||
mascot = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.Mascot), _ => Empty())
|
||||
{
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.TopLeft,
|
||||
RelativePositionAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Y = 0.2f
|
||||
},
|
||||
rightArea = new Container
|
||||
{
|
||||
Name = "Right area",
|
||||
@ -71,7 +106,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
new Container
|
||||
{
|
||||
Name = "Masked elements before hit objects",
|
||||
Name = "Elements before hit objects",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit,
|
||||
Children = new[]
|
||||
@ -86,22 +121,28 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
}
|
||||
}
|
||||
},
|
||||
hitTargetOffsetContent = new Container
|
||||
new Container
|
||||
{
|
||||
Name = "Masked hit objects content",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
Child = playfieldContent = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
barLinePlayfield = new BarLinePlayfield(),
|
||||
HitObjectContainer,
|
||||
}
|
||||
}
|
||||
},
|
||||
playfieldOverlay = new Container
|
||||
{
|
||||
Name = "Elements after hit objects",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
barLinePlayfield = new BarLinePlayfield(),
|
||||
new Container
|
||||
{
|
||||
Name = "Hit objects",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
HitObjectContainer,
|
||||
drumRollHitContainer = new DrumRollHitContainer()
|
||||
}
|
||||
},
|
||||
drumRollHitContainer = new DrumRollHitContainer(),
|
||||
kiaiExplosionContainer = new Container<KiaiHitExplosion>
|
||||
{
|
||||
Name = "Kiai hit explosions",
|
||||
@ -117,36 +158,15 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
},
|
||||
}
|
||||
},
|
||||
leftArea = new Container
|
||||
{
|
||||
Name = "Left overlay",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit,
|
||||
BorderColour = colours.Gray0,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.PlayfieldBackgroundLeft), _ => new PlayfieldBackgroundLeft()),
|
||||
new InputDrum(HitObjectContainer)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
},
|
||||
}
|
||||
},
|
||||
mascot = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.Mascot), _ => Empty())
|
||||
{
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.TopLeft,
|
||||
RelativePositionAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Y = 0.2f
|
||||
},
|
||||
topLevelHitContainer = new ProxyContainer
|
||||
{
|
||||
Name = "Top level hit objects",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
drumRollHitContainer.CreateProxy(),
|
||||
// this is added at the end of the hierarchy to receive input before taiko objects.
|
||||
// but is proxied below everything to not cover visual effects such as hit explosions.
|
||||
inputDrum,
|
||||
};
|
||||
|
||||
RegisterPool<Hit, DrawableHit>(50);
|
||||
@ -193,8 +213,9 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
// Padding is required to be updated for elements which are based on "absolute" X sized elements.
|
||||
// This is basically allowing for correct alignment as relative pieces move around them.
|
||||
rightArea.Padding = new MarginPadding { Left = leftArea.DrawWidth };
|
||||
hitTargetOffsetContent.Padding = new MarginPadding { Left = HitTarget.DrawWidth / 2 };
|
||||
rightArea.Padding = new MarginPadding { Left = inputDrum.Width };
|
||||
playfieldContent.Padding = new MarginPadding { Left = HitTarget.DrawWidth / 2 };
|
||||
playfieldOverlay.Padding = new MarginPadding { Left = HitTarget.DrawWidth / 2 };
|
||||
|
||||
mascot.Scale = new Vector2(DrawHeight / DEFAULT_HEIGHT);
|
||||
}
|
||||
|
Reference in New Issue
Block a user