mirror of
https://github.com/ppy/osu.git
synced 2024-11-15 03:47:26 +08:00
Merge branch 'taiko_playfield_2' into taiko_barlines
Conflicts: osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj
This commit is contained in:
commit
4bc038addd
82
osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs
Normal file
82
osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
// 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.MathUtils;
|
||||||
|
using osu.Framework.Screens.Testing;
|
||||||
|
using osu.Game.Modes.Objects.Drawables;
|
||||||
|
using osu.Game.Modes.Taiko.Judgements;
|
||||||
|
using osu.Game.Modes.Taiko.Objects;
|
||||||
|
using osu.Game.Modes.Taiko.UI;
|
||||||
|
|
||||||
|
namespace osu.Desktop.VisualTests.Tests
|
||||||
|
{
|
||||||
|
internal class TestCaseTaikoPlayfield : TestCase
|
||||||
|
{
|
||||||
|
public override string Description => "Taiko playfield";
|
||||||
|
|
||||||
|
private TaikoPlayfield playfield;
|
||||||
|
|
||||||
|
public override void Reset()
|
||||||
|
{
|
||||||
|
base.Reset();
|
||||||
|
|
||||||
|
AddButton("Hit!", addHitJudgement);
|
||||||
|
AddButton("Miss :(", addMissJudgement);
|
||||||
|
|
||||||
|
Add(playfield = new TaikoPlayfield
|
||||||
|
{
|
||||||
|
Y = 200
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addHitJudgement()
|
||||||
|
{
|
||||||
|
TaikoScoreResult score = RNG.Next(2) == 0 ? TaikoScoreResult.Good : TaikoScoreResult.Great;
|
||||||
|
|
||||||
|
playfield.OnJudgement(new DrawableTestHit(new TaikoHitObject())
|
||||||
|
{
|
||||||
|
X = RNG.NextSingle(score == TaikoScoreResult.Good ? -0.1f : -0.05f, score == TaikoScoreResult.Good ? 0.1f : 0.05f),
|
||||||
|
Judgement = new TaikoJudgementInfo
|
||||||
|
{
|
||||||
|
Result = HitResult.Hit,
|
||||||
|
Score = score,
|
||||||
|
TimeOffset = 0,
|
||||||
|
ComboAtHit = 1,
|
||||||
|
SecondHit = RNG.Next(10) == 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMissJudgement()
|
||||||
|
{
|
||||||
|
playfield.OnJudgement(new DrawableTestHit(new TaikoHitObject())
|
||||||
|
{
|
||||||
|
Judgement = new TaikoJudgementInfo
|
||||||
|
{
|
||||||
|
Result = HitResult.Miss,
|
||||||
|
TimeOffset = 0,
|
||||||
|
ComboAtHit = 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DrawableTestHit : DrawableHitObject<TaikoHitObject, TaikoJudgementInfo>
|
||||||
|
{
|
||||||
|
public DrawableTestHit(TaikoHitObject hitObject)
|
||||||
|
: base(hitObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TaikoJudgementInfo CreateJudgementInfo() => new TaikoJudgementInfo();
|
||||||
|
|
||||||
|
protected override void UpdateState(ArmedState state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
// Doesn't move
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -194,6 +194,7 @@
|
|||||||
<Compile Include="Tests\TestCaseReplay.cs" />
|
<Compile Include="Tests\TestCaseReplay.cs" />
|
||||||
<Compile Include="Tests\TestCaseScoreCounter.cs" />
|
<Compile Include="Tests\TestCaseScoreCounter.cs" />
|
||||||
<Compile Include="Tests\TestCaseTabControl.cs" />
|
<Compile Include="Tests\TestCaseTabControl.cs" />
|
||||||
|
<Compile Include="Tests\TestCaseTaikoPlayfield.cs" />
|
||||||
<Compile Include="Tests\TestCaseTextAwesome.cs" />
|
<Compile Include="Tests\TestCaseTextAwesome.cs" />
|
||||||
<Compile Include="Tests\TestCasePlaySongSelect.cs" />
|
<Compile Include="Tests\TestCasePlaySongSelect.cs" />
|
||||||
<Compile Include="Tests\TestCaseTwoLayerButton.cs" />
|
<Compile Include="Tests\TestCaseTwoLayerButton.cs" />
|
||||||
|
@ -7,5 +7,76 @@ namespace osu.Game.Modes.Taiko.Judgements
|
|||||||
{
|
{
|
||||||
public class TaikoJudgementInfo : JudgementInfo
|
public class TaikoJudgementInfo : JudgementInfo
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum score value.
|
||||||
|
/// </summary>
|
||||||
|
public const TaikoScoreResult MAX_SCORE = TaikoScoreResult.Great;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The score value.
|
||||||
|
/// </summary>
|
||||||
|
public TaikoScoreResult Score;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The score value for the combo portion of the score.
|
||||||
|
/// </summary>
|
||||||
|
public int ScoreValue => ScoreToInt(Score);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The score value for the accuracy portion of the score.
|
||||||
|
/// </summary>
|
||||||
|
public int AccuracyScoreValue => AccuracyScoreToInt(Score);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum score value for the combo portion of the score.
|
||||||
|
/// </summary>
|
||||||
|
public int MaxScoreValue => ScoreToInt(MAX_SCORE);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum score value for the accuracy portion of the score.
|
||||||
|
/// </summary>
|
||||||
|
public int MaxAccuracyScoreValue => AccuracyScoreToInt(MAX_SCORE);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this Judgement has a secondary hit in the case of finishers.
|
||||||
|
/// </summary>
|
||||||
|
public bool SecondHit;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computes the score value for the combo portion of the score.
|
||||||
|
/// For the accuracy portion of the score (including accuracy percentage), see <see cref="AccuracyScoreToInt(TaikoScoreResult)"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="result">The result to compute the score value for.</param>
|
||||||
|
/// <returns>The int score value.</returns>
|
||||||
|
protected virtual int ScoreToInt(TaikoScoreResult result)
|
||||||
|
{
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
case TaikoScoreResult.Good:
|
||||||
|
return 100;
|
||||||
|
case TaikoScoreResult.Great:
|
||||||
|
return 300;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computes the score value for the accurac portion of the score.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="result">The result to compute the score value for.</param>
|
||||||
|
/// <returns>The int score value.</returns>
|
||||||
|
protected virtual int AccuracyScoreToInt(TaikoScoreResult result)
|
||||||
|
{
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
case TaikoScoreResult.Good:
|
||||||
|
return 150;
|
||||||
|
case TaikoScoreResult.Great:
|
||||||
|
return 300;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
osu.Game.Modes.Taiko/Judgements/TaikoScoreResult.cs
Normal file
11
osu.Game.Modes.Taiko/Judgements/TaikoScoreResult.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// 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.Modes.Taiko.Judgements
|
||||||
|
{
|
||||||
|
public enum TaikoScoreResult
|
||||||
|
{
|
||||||
|
Good,
|
||||||
|
Great
|
||||||
|
}
|
||||||
|
}
|
116
osu.Game.Modes.Taiko/UI/HitTarget.cs
Normal file
116
osu.Game.Modes.Taiko/UI/HitTarget.cs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Modes.Taiko.Objects;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Taiko.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A component that is displayed at the hit position in the taiko playfield.
|
||||||
|
/// </summary>
|
||||||
|
internal class HitTarget : Container
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Diameter of normal hit object circles.
|
||||||
|
/// </summary>
|
||||||
|
private const float normal_diameter = TaikoHitObject.CIRCLE_RADIUS * 2 * TaikoPlayfield.PLAYFIELD_SCALE;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Diameter of finisher hit object circles.
|
||||||
|
/// </summary>
|
||||||
|
private const float finisher_diameter = normal_diameter * 1.5f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The 1px inner border of the taiko playfield.
|
||||||
|
/// </summary>
|
||||||
|
private const float border_offset = 1;
|
||||||
|
|
||||||
|
public HitTarget()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Name = "Bar Upper",
|
||||||
|
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
|
||||||
|
Y = border_offset,
|
||||||
|
|
||||||
|
Size = new Vector2(3, (TaikoPlayfield.PlayfieldHeight - finisher_diameter) / 2f - border_offset),
|
||||||
|
|
||||||
|
Alpha = 0.1f
|
||||||
|
},
|
||||||
|
new CircularContainer
|
||||||
|
{
|
||||||
|
Name = "Finisher Ring",
|
||||||
|
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
|
||||||
|
Size = new Vector2(finisher_diameter),
|
||||||
|
|
||||||
|
BorderColour = Color4.White,
|
||||||
|
BorderThickness = 2,
|
||||||
|
Alpha = 0.1f,
|
||||||
|
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new CircularContainer
|
||||||
|
{
|
||||||
|
Name = "Normal Ring",
|
||||||
|
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
|
||||||
|
Size = new Vector2(normal_diameter),
|
||||||
|
|
||||||
|
BorderColour = Color4.White,
|
||||||
|
BorderThickness = 2,
|
||||||
|
Alpha = 0.5f,
|
||||||
|
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Name = "Bar Lower",
|
||||||
|
|
||||||
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
|
||||||
|
Y = -border_offset,
|
||||||
|
|
||||||
|
Size = new Vector2(3, (TaikoPlayfield.PlayfieldHeight - finisher_diameter) / 2f - border_offset),
|
||||||
|
|
||||||
|
Alpha = 0.1f
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
154
osu.Game.Modes.Taiko/UI/InputDrum.cs
Normal file
154
osu.Game.Modes.Taiko/UI/InputDrum.cs
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Input;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Framework.Graphics.Transforms;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Taiko.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A component of the playfield that captures input and displays input as a drum.
|
||||||
|
/// </summary>
|
||||||
|
internal class InputDrum : Container
|
||||||
|
{
|
||||||
|
public InputDrum()
|
||||||
|
{
|
||||||
|
Size = new Vector2(TaikoPlayfield.PlayfieldHeight);
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new TaikoHalfDrum(false)
|
||||||
|
{
|
||||||
|
Name = "Left Half",
|
||||||
|
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
|
||||||
|
Keys = new List<Key>(new[] { Key.F, Key.D })
|
||||||
|
},
|
||||||
|
new TaikoHalfDrum(true)
|
||||||
|
{
|
||||||
|
Name = "Right Half",
|
||||||
|
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
|
||||||
|
Position = new Vector2(-1f, 0),
|
||||||
|
|
||||||
|
Keys = new List<Key>(new[] { Key.J, Key.K })
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A half-drum. Contains one centre and one rim hit.
|
||||||
|
/// </summary>
|
||||||
|
private class TaikoHalfDrum : Container
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A list of keys which this half-drum accepts.
|
||||||
|
/// <para>
|
||||||
|
/// [0] => Inner key, [1] => Outer key
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
public List<Key> Keys = new List<Key>();
|
||||||
|
|
||||||
|
private Sprite outer;
|
||||||
|
private Sprite outerHit;
|
||||||
|
private Sprite inner;
|
||||||
|
private Sprite innerHit;
|
||||||
|
|
||||||
|
public TaikoHalfDrum(bool flipped)
|
||||||
|
{
|
||||||
|
Masking = true;
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
outer = new Sprite
|
||||||
|
{
|
||||||
|
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
},
|
||||||
|
outerHit = new Sprite
|
||||||
|
{
|
||||||
|
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
|
||||||
|
Alpha = 0,
|
||||||
|
|
||||||
|
BlendingMode = BlendingMode.Additive
|
||||||
|
},
|
||||||
|
inner = new Sprite
|
||||||
|
{
|
||||||
|
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Size = new Vector2(0.7f)
|
||||||
|
},
|
||||||
|
innerHit = new Sprite
|
||||||
|
{
|
||||||
|
Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Size = new Vector2(0.7f),
|
||||||
|
|
||||||
|
Alpha = 0,
|
||||||
|
|
||||||
|
BlendingMode = BlendingMode.Additive
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(TextureStore textures, OsuColour colours)
|
||||||
|
{
|
||||||
|
outer.Texture = textures.Get(@"Play/Taiko/taiko-drum-outer");
|
||||||
|
outerHit.Texture = textures.Get(@"Play/Taiko/taiko-drum-outer-hit");
|
||||||
|
inner.Texture = textures.Get(@"Play/Taiko/taiko-drum-inner");
|
||||||
|
innerHit.Texture = textures.Get(@"Play/Taiko/taiko-drum-inner-hit");
|
||||||
|
|
||||||
|
outerHit.Colour = colours.Blue;
|
||||||
|
innerHit.Colour = colours.Pink;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (args.Key == Keys[0])
|
||||||
|
{
|
||||||
|
innerHit.FadeIn();
|
||||||
|
innerHit.FadeOut(500, EasingTypes.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.Key == Keys[1])
|
||||||
|
{
|
||||||
|
outerHit.FadeIn();
|
||||||
|
outerHit.FadeOut(500, EasingTypes.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
135
osu.Game.Modes.Taiko/UI/JudgementText.cs
Normal file
135
osu.Game.Modes.Taiko/UI/JudgementText.cs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// 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 osu.Framework.Graphics.Transforms;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
using osu.Game.Modes.Taiko.Judgements;
|
||||||
|
using osu.Game.Modes.Objects.Drawables;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Taiko.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Text that is shown as judgement when a hit object is hit or missed.
|
||||||
|
/// </summary>
|
||||||
|
public class JudgementText : Container
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The Judgement to display.
|
||||||
|
/// </summary>
|
||||||
|
public TaikoJudgementInfo Judgement;
|
||||||
|
|
||||||
|
private Container textContainer;
|
||||||
|
private OsuSpriteText glowText;
|
||||||
|
private OsuSpriteText normalText;
|
||||||
|
|
||||||
|
private int movementDirection;
|
||||||
|
|
||||||
|
public JudgementText()
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
textContainer = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new BufferedContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
|
||||||
|
BlurSigma = new Vector2(10),
|
||||||
|
CacheDrawnFrameBuffer = true,
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Size = new Vector2(3),
|
||||||
|
|
||||||
|
BlendingMode = BlendingMode.Additive,
|
||||||
|
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
glowText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
|
||||||
|
Font = "Venera",
|
||||||
|
TextSize = 22f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
normalText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
|
||||||
|
Font = "Venera",
|
||||||
|
TextSize = 22f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
Color4 judgementColour = Color4.White;
|
||||||
|
string judgementText = string.Empty;
|
||||||
|
|
||||||
|
switch (Judgement.Result)
|
||||||
|
{
|
||||||
|
case HitResult.Miss:
|
||||||
|
judgementColour = colours.Red;
|
||||||
|
judgementText = "MISS";
|
||||||
|
movementDirection = 1;
|
||||||
|
break;
|
||||||
|
case HitResult.Hit:
|
||||||
|
switch (Judgement.Score)
|
||||||
|
{
|
||||||
|
case TaikoScoreResult.Good:
|
||||||
|
judgementColour = colours.Green;
|
||||||
|
judgementText = "GOOD";
|
||||||
|
textContainer.Scale = new Vector2(0.45f);
|
||||||
|
break;
|
||||||
|
case TaikoScoreResult.Great:
|
||||||
|
judgementColour = colours.Blue;
|
||||||
|
judgementText = "GREAT";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
movementDirection = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glowText.Colour = judgementColour;
|
||||||
|
glowText.Text = normalText.Text = judgementText;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
ScaleTo(1.5f, 250, EasingTypes.OutQuint);
|
||||||
|
MoveToY(movementDirection * 100, 500);
|
||||||
|
|
||||||
|
Delay(250);
|
||||||
|
ScaleTo(0.75f, 250);
|
||||||
|
FadeOut(250);
|
||||||
|
|
||||||
|
Expire();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
79
osu.Game.Modes.Taiko/UI/RingExplosion.cs
Normal file
79
osu.Game.Modes.Taiko/UI/RingExplosion.cs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Transforms;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Modes.Taiko.Judgements;
|
||||||
|
using osu.Game.Modes.Taiko.Objects;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Taiko.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A ring that explodes to indicate a judgement has occurred.
|
||||||
|
/// </summary>
|
||||||
|
internal class RingExplosion : CircularContainer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The Judgement to display.
|
||||||
|
/// </summary>
|
||||||
|
public TaikoJudgementInfo Judgement;
|
||||||
|
|
||||||
|
private Box innerFill;
|
||||||
|
|
||||||
|
public RingExplosion()
|
||||||
|
{
|
||||||
|
Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2);
|
||||||
|
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
RelativePositionAxes = Axes.Both;
|
||||||
|
|
||||||
|
BorderColour = Color4.White;
|
||||||
|
BorderThickness = 1;
|
||||||
|
|
||||||
|
Alpha = 0.15f;
|
||||||
|
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
innerFill = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
if (Judgement.SecondHit)
|
||||||
|
Size *= 1.5f;
|
||||||
|
|
||||||
|
switch (Judgement.Score)
|
||||||
|
{
|
||||||
|
case TaikoScoreResult.Good:
|
||||||
|
innerFill.Colour = colours.Green;
|
||||||
|
break;
|
||||||
|
case TaikoScoreResult.Great:
|
||||||
|
innerFill.Colour = colours.Blue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
ScaleTo(5f, 1000, EasingTypes.OutQuint);
|
||||||
|
FadeOut(500);
|
||||||
|
|
||||||
|
Expire();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,38 +4,203 @@
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Graphics.Textures;
|
|
||||||
using osu.Game.Modes.Taiko.Objects;
|
using osu.Game.Modes.Taiko.Objects;
|
||||||
using osu.Game.Modes.UI;
|
using osu.Game.Modes.UI;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Game.Modes.Taiko.Judgements;
|
using osu.Game.Modes.Taiko.Judgements;
|
||||||
|
using osu.Game.Modes.Objects.Drawables;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics.Primitives;
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko.UI
|
namespace osu.Game.Modes.Taiko.UI
|
||||||
{
|
{
|
||||||
public class TaikoPlayfield : Playfield<TaikoHitObject, TaikoJudgementInfo>
|
public class TaikoPlayfield : Playfield<TaikoHitObject, TaikoJudgementInfo>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The default play field height.
|
||||||
|
/// </summary>
|
||||||
|
public const float PLAYFIELD_BASE_HEIGHT = 242;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The play field height scale.
|
||||||
|
/// </summary>
|
||||||
|
public const float PLAYFIELD_SCALE = 0.65f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The play field height after scaling.
|
||||||
|
/// </summary>
|
||||||
|
public static float PlayfieldHeight => PLAYFIELD_BASE_HEIGHT * PLAYFIELD_SCALE;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The offset from <see cref="left_area_size"/> which the center of the hit target lies at.
|
||||||
|
/// </summary>
|
||||||
|
private const float hit_target_offset = 80;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The size of the left area of the playfield. This area contains the input drum.
|
||||||
|
/// </summary>
|
||||||
|
private const float left_area_size = 240;
|
||||||
|
|
||||||
|
protected override Container<Drawable> Content => hitObjectContainer;
|
||||||
|
|
||||||
|
private Container<RingExplosion> ringExplosionContainer;
|
||||||
|
//private Container<DrawableBarLine> barLineContainer;
|
||||||
|
private Container<JudgementText> judgementContainer;
|
||||||
|
|
||||||
|
private Container hitObjectContainer;
|
||||||
|
// ReSharper disable once NotAccessedField.Local
|
||||||
|
private Container topLevelHitContainer;
|
||||||
|
private Container leftBackgroundContainer;
|
||||||
|
private Container rightBackgroundContainer;
|
||||||
|
private Box leftBackground;
|
||||||
|
private Box rightBackground;
|
||||||
|
|
||||||
public TaikoPlayfield()
|
public TaikoPlayfield()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
Size = new Vector2(1, 100);
|
Height = PlayfieldHeight;
|
||||||
Anchor = Anchor.Centre;
|
|
||||||
Origin = Anchor.Centre;
|
AddInternal(new Drawable[]
|
||||||
|
{
|
||||||
|
rightBackgroundContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
BorderThickness = 2,
|
||||||
|
Masking = true,
|
||||||
|
EdgeEffect = new EdgeEffect
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Shadow,
|
||||||
|
Colour = Color4.Black.Opacity(0.2f),
|
||||||
|
Radius = 5,
|
||||||
|
},
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
rightBackground = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0.6f
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Left = left_area_size },
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Padding = new MarginPadding { Left = hit_target_offset },
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
ringExplosionContainer = new Container<RingExplosion>
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2),
|
||||||
|
Scale = new Vector2(PLAYFIELD_SCALE),
|
||||||
|
BlendingMode = BlendingMode.Additive
|
||||||
|
},
|
||||||
|
//barLineContainer = new Container<DrawableBarLine>
|
||||||
|
//{
|
||||||
|
// RelativeSizeAxes = Axes.Both,
|
||||||
|
//},
|
||||||
|
new HitTarget
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
hitObjectContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
judgementContainer = new Container<JudgementText>
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
BlendingMode = BlendingMode.Additive
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
leftBackgroundContainer = new Container
|
||||||
|
{
|
||||||
|
Size = new Vector2(left_area_size, PlayfieldHeight),
|
||||||
|
BorderThickness = 1,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
leftBackground = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
new InputDrum
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
|
||||||
|
RelativePositionAxes = Axes.X,
|
||||||
|
Position = new Vector2(0.10f, 0),
|
||||||
|
|
||||||
|
Scale = new Vector2(0.9f)
|
||||||
|
},
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Width = 10,
|
||||||
|
ColourInfo = Framework.Graphics.Colour.ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.6f), Color4.Black.Opacity(0)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
topLevelHitContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
Add(new Box { RelativeSizeAxes = Axes.Both, Alpha = 0.5f });
|
leftBackgroundContainer.BorderColour = colours.Gray0;
|
||||||
|
leftBackground.Colour = colours.Gray1;
|
||||||
|
|
||||||
Add(new Sprite
|
rightBackgroundContainer.BorderColour = colours.Gray1;
|
||||||
|
rightBackground.Colour = colours.Gray0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Add(DrawableHitObject<TaikoHitObject, TaikoJudgementInfo> h)
|
||||||
|
{
|
||||||
|
h.Depth = (float)h.HitObject.StartTime;
|
||||||
|
|
||||||
|
base.Add(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgementInfo> judgedObject)
|
||||||
|
{
|
||||||
|
if (judgedObject.Judgement.Result == HitResult.Hit)
|
||||||
{
|
{
|
||||||
Texture = textures.Get(@"Menu/logo"),
|
ringExplosionContainer.Add(new RingExplosion
|
||||||
Origin = Anchor.Centre,
|
{
|
||||||
Scale = new Vector2(0.2f),
|
Judgement = judgedObject.Judgement
|
||||||
RelativePositionAxes = Axes.Both,
|
});
|
||||||
Position = new Vector2(0.1f, 0.5f),
|
}
|
||||||
Colour = Color4.Gray
|
|
||||||
|
float judgementOffset = judgedObject.Judgement.Result == HitResult.Hit ? judgedObject.Position.X : 0;
|
||||||
|
|
||||||
|
judgementContainer.Add(new JudgementText
|
||||||
|
{
|
||||||
|
Anchor = judgedObject.Judgement.Result == HitResult.Hit ? Anchor.TopLeft : Anchor.BottomLeft,
|
||||||
|
Origin = judgedObject.Judgement.Result == HitResult.Hit ? Anchor.BottomCentre : Anchor.TopCentre,
|
||||||
|
|
||||||
|
RelativePositionAxes = Axes.X,
|
||||||
|
X = judgementOffset,
|
||||||
|
|
||||||
|
Judgement = judgedObject.Judgement
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,12 +50,17 @@
|
|||||||
<Compile Include="Beatmaps\TaikoBeatmapConverter.cs" />
|
<Compile Include="Beatmaps\TaikoBeatmapConverter.cs" />
|
||||||
<Compile Include="Beatmaps\TaikoBeatmapProcessor.cs" />
|
<Compile Include="Beatmaps\TaikoBeatmapProcessor.cs" />
|
||||||
<Compile Include="Judgements\TaikoJudgementInfo.cs" />
|
<Compile Include="Judgements\TaikoJudgementInfo.cs" />
|
||||||
|
<Compile Include="Judgements\TaikoScoreResult.cs" />
|
||||||
<Compile Include="Objects\BarLine.cs" />
|
<Compile Include="Objects\BarLine.cs" />
|
||||||
<Compile Include="TaikoDifficultyCalculator.cs" />
|
<Compile Include="TaikoDifficultyCalculator.cs" />
|
||||||
<Compile Include="Objects\Drawable\DrawableTaikoHit.cs" />
|
<Compile Include="Objects\Drawable\DrawableTaikoHit.cs" />
|
||||||
<Compile Include="Objects\TaikoHitObject.cs" />
|
<Compile Include="Objects\TaikoHitObject.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="TaikoScoreProcessor.cs" />
|
<Compile Include="TaikoScoreProcessor.cs" />
|
||||||
|
<Compile Include="UI\HitTarget.cs" />
|
||||||
|
<Compile Include="UI\InputDrum.cs" />
|
||||||
|
<Compile Include="UI\JudgementText.cs" />
|
||||||
|
<Compile Include="UI\RingExplosion.cs" />
|
||||||
<Compile Include="UI\TaikoHitRenderer.cs" />
|
<Compile Include="UI\TaikoHitRenderer.cs" />
|
||||||
<Compile Include="UI\TaikoPlayfield.cs" />
|
<Compile Include="UI\TaikoPlayfield.cs" />
|
||||||
<Compile Include="TaikoRuleset.cs" />
|
<Compile Include="TaikoRuleset.cs" />
|
||||||
|
@ -7,6 +7,7 @@ using osu.Game.Modes.Objects;
|
|||||||
using osu.Game.Modes.Objects.Drawables;
|
using osu.Game.Modes.Objects.Drawables;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using osu.Game.Modes.Judgements;
|
using osu.Game.Modes.Judgements;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
|
||||||
namespace osu.Game.Modes.UI
|
namespace osu.Game.Modes.UI
|
||||||
{
|
{
|
||||||
@ -45,10 +46,16 @@ namespace osu.Game.Modes.UI
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Add(HitObjects = new HitObjectContainer<DrawableHitObject<TObject, TJudgement>>
|
HitObjects = new HitObjectContainer<DrawableHitObject<TObject, TJudgement>>
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
});
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
Add(HitObjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
Loading…
Reference in New Issue
Block a user