Merge pull request #826 from smoogipooo/mania-input-base

Add basic framework required to implement mania note input
This commit is contained in:
Dean Herbert 2017-05-22 19:54:59 +09:00 committed by GitHub
commit 2e730c6840
13 changed files with 130 additions and 26 deletions

View File

@ -140,6 +140,26 @@ namespace osu.Game.Rulesets.Mania.Judgements
Miss = BeatmapDifficulty.DifficultyRange(difficulty, miss_max, miss_mid, miss_min); Miss = BeatmapDifficulty.DifficultyRange(difficulty, miss_max, miss_mid, miss_min);
} }
/// <summary>
/// Retrieves the hit result for a time offset.
/// </summary>
/// <param name="hitOffset">The time offset.</param>
/// <returns>The hit result, or null if the time offset results in a miss.</returns>
public ManiaHitResult? ResultFor(double hitOffset)
{
if (hitOffset <= Perfect / 2)
return ManiaHitResult.Perfect;
if (hitOffset <= Great / 2)
return ManiaHitResult.Great;
if (hitOffset <= Good / 2)
return ManiaHitResult.Good;
if (hitOffset <= Ok / 2)
return ManiaHitResult.Ok;
if (hitOffset <= Bad / 2)
return ManiaHitResult.Bad;
return null;
}
/// <summary> /// <summary>
/// Constructs new hit windows which have been multiplied by a value. /// Constructs new hit windows which have been multiplied by a value.
/// </summary> /// </summary>

View File

@ -0,0 +1,21 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.ComponentModel;
namespace osu.Game.Rulesets.Mania.Judgements
{
public enum ManiaHitResult
{
[Description("PERFECT")]
Perfect,
[Description("GREAT")]
Great,
[Description("GOOD")]
Good,
[Description("OK")]
Ok,
[Description("BAD")]
Bad
}
}

View File

@ -10,5 +10,10 @@ namespace osu.Game.Rulesets.Mania.Judgements
public override string ResultString => string.Empty; public override string ResultString => string.Empty;
public override string MaxResultString => string.Empty; public override string MaxResultString => string.Empty;
/// <summary>
/// The hit result.
/// </summary>
public ManiaHitResult ManiaResult;
} }
} }

View File

@ -5,6 +5,8 @@ using osu.Game.Rulesets.Objects.Drawables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework.Configuration;
using OpenTK.Input;
namespace osu.Game.Rulesets.Mania.Objects.Drawables namespace osu.Game.Rulesets.Mania.Objects.Drawables
{ {
@ -14,8 +16,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
private readonly BodyPiece bodyPiece; private readonly BodyPiece bodyPiece;
private readonly NotePiece tailPiece; private readonly NotePiece tailPiece;
public DrawableHoldNote(HoldNote hitObject) public DrawableHoldNote(HoldNote hitObject, Bindable<Key> key = null)
: base(hitObject) : base(hitObject, key)
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Height = (float)HitObject.Duration; Height = (float)HitObject.Duration;

View File

@ -2,6 +2,8 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK.Graphics; using OpenTK.Graphics;
using OpenTK.Input;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Judgements;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
@ -11,13 +13,21 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
public abstract class DrawableManiaHitObject<TObject> : DrawableHitObject<ManiaHitObject, ManiaJudgement> public abstract class DrawableManiaHitObject<TObject> : DrawableHitObject<ManiaHitObject, ManiaJudgement>
where TObject : ManiaHitObject where TObject : ManiaHitObject
{ {
/// <summary>
/// The key that will trigger input for this hit object.
/// </summary>
protected Bindable<Key> Key { get; private set; } = new Bindable<Key>();
public new TObject HitObject; public new TObject HitObject;
protected DrawableManiaHitObject(TObject hitObject) protected DrawableManiaHitObject(TObject hitObject, Bindable<Key> key = null)
: base(hitObject) : base(hitObject)
{ {
HitObject = hitObject; HitObject = hitObject;
if (key != null)
Key.BindTo(key);
RelativePositionAxes = Axes.Y; RelativePositionAxes = Axes.Y;
Y = (float)HitObject.StartTime; Y = (float)HitObject.StartTime;
} }

View File

@ -2,6 +2,8 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK.Graphics; using OpenTK.Graphics;
using OpenTK.Input;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
@ -12,8 +14,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
{ {
private readonly NotePiece headPiece; private readonly NotePiece headPiece;
public DrawableNote(Note hitObject) public DrawableNote(Note hitObject, Bindable<Key> key = null)
: base(hitObject) : base(hitObject, key)
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Height = 100; Height = 100;

View File

@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Mania.Objects
/// <summary> /// <summary>
/// The key-release hit windows for this hold note. /// The key-release hit windows for this hold note.
/// </summary> /// </summary>
protected HitWindows ReleaseHitWindows = new HitWindows(); public HitWindows ReleaseHitWindows { get; protected set; } = new HitWindows();
public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty) public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty)
{ {

View File

@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Objects
/// <summary> /// <summary>
/// The key-press hit window for this note. /// The key-press hit window for this note.
/// </summary> /// </summary>
protected HitWindows HitWindows = new HitWindows(); public HitWindows HitWindows { get; protected set; } = new HitWindows();
public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty) public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty)
{ {

View File

@ -22,5 +22,12 @@ namespace osu.Game.Rulesets.Mania.Scoring
protected override void OnNewJudgement(ManiaJudgement judgement) protected override void OnNewJudgement(ManiaJudgement judgement)
{ {
} }
protected override void Reset()
{
base.Reset();
Health.Value = 1;
}
} }
} }

View File

@ -18,6 +18,8 @@ using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Judgements;
using osu.Game.Beatmaps.Timing; using osu.Game.Beatmaps.Timing;
using System;
using osu.Framework.Configuration;
namespace osu.Game.Rulesets.Mania.UI namespace osu.Game.Rulesets.Mania.UI
{ {
@ -33,7 +35,10 @@ namespace osu.Game.Rulesets.Mania.UI
private const float column_width = 45; private const float column_width = 45;
private const float special_column_width = 70; private const float special_column_width = 70;
public Key Key; /// <summary>
/// The key that will trigger input actions for this column and hit objects contained inside it.
/// </summary>
public Bindable<Key> Key = new Bindable<Key>();
private readonly Box background; private readonly Box background;
private readonly Container hitTargetBar; private readonly Container hitTargetBar;
@ -95,6 +100,12 @@ namespace osu.Game.Rulesets.Mania.UI
Name = "Hit objects", Name = "Hit objects",
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
}, },
// For column lighting, we need to capture input events before the notes
new InputTarget
{
KeyDown = onKeyDown,
KeyUp = onKeyUp
}
} }
}, },
new Container new Container
@ -178,12 +189,9 @@ namespace osu.Game.Rulesets.Mania.UI
} }
} }
public void Add(DrawableHitObject<ManiaHitObject, ManiaJudgement> hitObject) public void Add(DrawableHitObject<ManiaHitObject, ManiaJudgement> hitObject) => ControlPointContainer.Add(hitObject);
{
ControlPointContainer.Add(hitObject);
}
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) private bool onKeyDown(InputState state, KeyDownEventArgs args)
{ {
if (args.Repeat) if (args.Repeat)
return false; return false;
@ -197,7 +205,7 @@ namespace osu.Game.Rulesets.Mania.UI
return false; return false;
} }
protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) private bool onKeyUp(InputState state, KeyUpEventArgs args)
{ {
if (args.Key == Key) if (args.Key == Key)
{ {
@ -207,5 +215,24 @@ namespace osu.Game.Rulesets.Mania.UI
return false; return false;
} }
/// <summary>
/// This is a simple container which delegates various input events that have to be captured before the notes.
/// </summary>
private class InputTarget : Container
{
public Func<InputState, KeyDownEventArgs, bool> KeyDown;
public Func<InputState, KeyUpEventArgs, bool> KeyUp;
public InputTarget()
{
RelativeSizeAxes = Axes.Both;
AlwaysPresent = true;
Alpha = 0;
}
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => KeyDown?.Invoke(state, args) ?? false;
protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => KeyUp?.Invoke(state, args) ?? false;
}
} }
} }

View File

@ -4,6 +4,8 @@
using System; using System;
using System.Linq; using System.Linq;
using OpenTK; using OpenTK;
using OpenTK.Input;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Timing; using osu.Game.Beatmaps.Timing;
@ -76,13 +78,19 @@ namespace osu.Game.Rulesets.Mania.UI
protected override DrawableHitObject<ManiaHitObject, ManiaJudgement> GetVisualRepresentation(ManiaHitObject h) protected override DrawableHitObject<ManiaHitObject, ManiaJudgement> GetVisualRepresentation(ManiaHitObject h)
{ {
var maniaPlayfield = Playfield as ManiaPlayfield;
if (maniaPlayfield == null)
return null;
Bindable<Key> key = maniaPlayfield.Columns.ElementAt(h.Column).Key;
var holdNote = h as HoldNote; var holdNote = h as HoldNote;
if (holdNote != null) if (holdNote != null)
return new DrawableHoldNote(holdNote); return new DrawableHoldNote(holdNote, key);
var note = h as Note; var note = h as Note;
if (note != null) if (note != null)
return new DrawableNote(note); return new DrawableNote(note, key);
return null; return null;
} }

View File

@ -55,7 +55,8 @@ namespace osu.Game.Rulesets.Mania.UI
} }
} }
public readonly FlowContainer<Column> Columns; private readonly FlowContainer<Column> columns;
public IEnumerable<Column> Columns => columns.Children;
private readonly ControlPointContainer barlineContainer; private readonly ControlPointContainer barlineContainer;
@ -87,7 +88,7 @@ namespace osu.Game.Rulesets.Mania.UI
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = Color4.Black Colour = Color4.Black
}, },
Columns = new FillFlowContainer<Column> columns = new FillFlowContainer<Column>
{ {
Name = "Columns", Name = "Columns",
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,
@ -114,7 +115,7 @@ namespace osu.Game.Rulesets.Mania.UI
}; };
for (int i = 0; i < columnCount; i++) for (int i = 0; i < columnCount; i++)
Columns.Add(new Column(timingChanges)); columns.Add(new Column(timingChanges));
TimeSpan = time_span_default; TimeSpan = time_span_default;
} }
@ -133,17 +134,17 @@ namespace osu.Game.Rulesets.Mania.UI
// Set the special column + colour + key // Set the special column + colour + key
for (int i = 0; i < columnCount; i++) for (int i = 0; i < columnCount; i++)
{ {
Column column = Columns.Children.ElementAt(i); Column column = Columns.ElementAt(i);
column.IsSpecial = isSpecialColumn(i); column.IsSpecial = isSpecialColumn(i);
if (!column.IsSpecial) if (!column.IsSpecial)
continue; continue;
column.Key = Key.Space; column.Key.Value = Key.Space;
column.AccentColour = specialColumnColour; column.AccentColour = specialColumnColour;
} }
var nonSpecialColumns = Columns.Children.Where(c => !c.IsSpecial).ToList(); var nonSpecialColumns = Columns.Where(c => !c.IsSpecial).ToList();
// We'll set the colours of the non-special columns in a separate loop, because the non-special // We'll set the colours of the non-special columns in a separate loop, because the non-special
// column colours are mirrored across their centre and special styles mess with this // column colours are mirrored across their centre and special styles mess with this
@ -162,11 +163,11 @@ namespace osu.Game.Rulesets.Mania.UI
int keyOffset = default_keys.Length / 2 - nonSpecialColumns.Count / 2 + i; int keyOffset = default_keys.Length / 2 - nonSpecialColumns.Count / 2 + i;
if (keyOffset >= 0 && keyOffset < default_keys.Length) if (keyOffset >= 0 && keyOffset < default_keys.Length)
column.Key = default_keys[keyOffset]; column.Key.Value = default_keys[keyOffset];
else else
// There is no default key defined for this column. Let's set this to Unknown for now // There is no default key defined for this column. Let's set this to Unknown for now
// however note that this will be gone after bindings are in place // however note that this will be gone after bindings are in place
column.Key = Key.Unknown; column.Key.Value = Key.Unknown;
} }
} }
@ -189,7 +190,7 @@ namespace osu.Game.Rulesets.Mania.UI
} }
} }
public override void Add(DrawableHitObject<ManiaHitObject, ManiaJudgement> h) => Columns.Children.ElementAt(h.HitObject.Column).Add(h); public override void Add(DrawableHitObject<ManiaHitObject, ManiaJudgement> h) => Columns.ElementAt(h.HitObject.Column).Add(h);
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
{ {
@ -225,7 +226,7 @@ namespace osu.Game.Rulesets.Mania.UI
timeSpan = MathHelper.Clamp(timeSpan, time_span_min, time_span_max); timeSpan = MathHelper.Clamp(timeSpan, time_span_min, time_span_max);
barlineContainer.TimeSpan = value; barlineContainer.TimeSpan = value;
Columns.Children.ForEach(c => c.ControlPointContainer.TimeSpan = value); Columns.ForEach(c => c.ControlPointContainer.TimeSpan = value);
} }
} }

View File

@ -56,6 +56,7 @@
<Compile Include="Beatmaps\Patterns\Pattern.cs" /> <Compile Include="Beatmaps\Patterns\Pattern.cs" />
<Compile Include="MathUtils\FastRandom.cs" /> <Compile Include="MathUtils\FastRandom.cs" />
<Compile Include="Judgements\HitWindows.cs" /> <Compile Include="Judgements\HitWindows.cs" />
<Compile Include="Judgements\ManiaHitResult.cs" />
<Compile Include="Judgements\ManiaJudgement.cs" /> <Compile Include="Judgements\ManiaJudgement.cs" />
<Compile Include="ManiaDifficultyCalculator.cs" /> <Compile Include="ManiaDifficultyCalculator.cs" />
<Compile Include="Objects\Drawables\DrawableHoldNote.cs" /> <Compile Include="Objects\Drawables\DrawableHoldNote.cs" />