Merge branch 'master' into catch-autoplay

This commit is contained in:
Dan Balasescu
2018-01-12 20:25:24 +09:00
committed by GitHub
15 changed files with 252 additions and 53 deletions

View File

@ -11,7 +11,7 @@ using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Catch.Beatmaps namespace osu.Game.Rulesets.Catch.Beatmaps
{ {
internal class CatchBeatmapConverter : BeatmapConverter<CatchHitObject> public class CatchBeatmapConverter : BeatmapConverter<CatchHitObject>
{ {
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) };
@ -20,6 +20,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
var curveData = obj as IHasCurve; var curveData = obj as IHasCurve;
var positionData = obj as IHasXPosition; var positionData = obj as IHasXPosition;
var comboData = obj as IHasCombo; var comboData = obj as IHasCombo;
var endTime = obj as IHasEndTime;
if (positionData == null) if (positionData == null)
yield break; yield break;
@ -42,6 +43,19 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
yield break; yield break;
} }
if (endTime != null)
{
yield return new BananaShower
{
StartTime = obj.StartTime,
Samples = obj.Samples,
Duration = endTime.Duration,
NewCombo = comboData?.NewCombo ?? false
};
yield break;
}
yield return new Fruit yield return new Fruit
{ {
StartTime = obj.StartTime, StartTime = obj.StartTime,

View File

@ -12,7 +12,7 @@ using OpenTK;
namespace osu.Game.Rulesets.Catch.Beatmaps namespace osu.Game.Rulesets.Catch.Beatmaps
{ {
internal class CatchBeatmapProcessor : BeatmapProcessor<CatchHitObject> public class CatchBeatmapProcessor : BeatmapProcessor<CatchHitObject>
{ {
public override void PostProcess(Beatmap<CatchHitObject> beatmap) public override void PostProcess(Beatmap<CatchHitObject> beatmap)
{ {

View File

@ -0,0 +1,61 @@
// Copyright (c) 2007-2018 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.Game.Rulesets.Objects.Types;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Catch.Objects
{
public class BananaShower : CatchHitObject, IHasEndTime
{
public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana;
protected override void CreateNestedHitObjects()
{
base.CreateNestedHitObjects();
createBananas();
}
private void createBananas()
{
double spacing = Duration;
while (spacing > 100)
spacing /= 2;
if (spacing <= 0)
return;
for (double i = StartTime; i <= EndTime; i += spacing)
AddNested(new Banana
{
Samples = Samples,
ComboColour = getNextComboColour(),
StartTime = i,
X = RNG.NextSingle()
});
}
private Color4 getNextComboColour()
{
switch (RNG.Next(0, 3))
{
default:
return new Color4(255, 240, 0, 255);
case 1:
return new Color4(255, 192, 0, 255);
case 2:
return new Color4(214, 221, 28, 255);
}
}
public double EndTime => StartTime + Duration;
public double Duration { get; set; }
public class Banana : Fruit
{
public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana;
}
}
}

View File

@ -0,0 +1,35 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Catch.Objects.Drawable
{
public class DrawableBananaShower : DrawableCatchHitObject<BananaShower>
{
private readonly Container bananaContainer;
public DrawableBananaShower(BananaShower s)
: base(s)
{
RelativeSizeAxes = Axes.X;
Origin = Anchor.BottomLeft;
X = 0;
Child = bananaContainer = new Container { RelativeSizeAxes = Axes.Both };
foreach (var b in s.NestedHitObjects.Cast<BananaShower.Banana>())
AddNested(new DrawableFruit(b));
}
protected override void AddNested(DrawableHitObject h)
{
((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false;
bananaContainer.Add(h);
base.AddNested(h);
}
}
}

View File

@ -243,6 +243,27 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
}, },
} }
}; };
case FruitVisualRepresentation.Banana:
return new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Framework.Graphics.Drawable[]
{
new Pulp
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
AccentColour = AccentColour,
Size = new Vector2(small_pulp),
Y = -0.15f
},
new Pulp
{
AccentColour = AccentColour,
Size = new Vector2(large_pulp_4 * 1.2f, large_pulp_4 * 3),
},
}
};
} }
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// 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 System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using OpenTK; using OpenTK;
@ -13,7 +12,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
{ {
private readonly Container dropletContainer; private readonly Container dropletContainer;
public DrawableJuiceStream(JuiceStream s) : base(s) public DrawableJuiceStream(JuiceStream s)
: base(s)
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Origin = Anchor.BottomLeft; Origin = Anchor.BottomLeft;
@ -21,28 +21,30 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
Child = dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }; Child = dropletContainer = new Container { RelativeSizeAxes = Axes.Both, };
foreach (CatchHitObject tick in s.NestedHitObjects.OfType<CatchHitObject>()) foreach (var tick in s.NestedHitObjects)
{ {
TinyDroplet tiny = tick as TinyDroplet; switch (tick)
if (tiny != null)
{ {
case TinyDroplet tiny:
AddNested(new DrawableDroplet(tiny) { Scale = new Vector2(0.5f) }); AddNested(new DrawableDroplet(tiny) { Scale = new Vector2(0.5f) });
continue; break;
} case Droplet droplet:
Droplet droplet = tick as Droplet;
if (droplet != null)
AddNested(new DrawableDroplet(droplet)); AddNested(new DrawableDroplet(droplet));
break;
Fruit fruit = tick as Fruit; case Fruit fruit:
if (fruit != null)
AddNested(new DrawableFruit(fruit)); AddNested(new DrawableFruit(fruit));
break;
}
} }
} }
protected override void AddNested(DrawableHitObject h) protected override void AddNested(DrawableHitObject h)
{ {
((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; var catchObject = (DrawableCatchHitObject)h;
catchObject.CheckPosition = o => CheckPosition?.Invoke(o) ?? false;
catchObject.AccentColour = HitObject.ComboColour;
dropletContainer.Add(h); dropletContainer.Add(h);
base.AddNested(h); base.AddNested(h);
} }

View File

@ -10,7 +10,7 @@ using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Catch.Scoring namespace osu.Game.Rulesets.Catch.Scoring
{ {
internal class CatchScoreProcessor : ScoreProcessor<CatchHitObject> public class CatchScoreProcessor : ScoreProcessor<CatchHitObject>
{ {
public CatchScoreProcessor(RulesetContainer<CatchHitObject> rulesetContainer) public CatchScoreProcessor(RulesetContainer<CatchHitObject> rulesetContainer)
: base(rulesetContainer) : base(rulesetContainer)
@ -21,23 +21,25 @@ namespace osu.Game.Rulesets.Catch.Scoring
{ {
foreach (var obj in beatmap.HitObjects) foreach (var obj in beatmap.HitObjects)
{ {
var stream = obj as JuiceStream; switch (obj)
if (stream != null)
{ {
case JuiceStream stream:
AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
foreach (var unused in stream.NestedHitObjects.OfType<CatchHitObject>()) foreach (var _ in stream.NestedHitObjects.Cast<CatchHitObject>())
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
break;
case BananaShower shower:
AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
continue; foreach (var _ in shower.NestedHitObjects.Cast<CatchHitObject>())
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
break;
case Fruit _:
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
break;
} }
var fruit = obj as Fruit;
if (fruit != null)
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
} }
base.SimulateAutoplay(beatmap); base.SimulateAutoplay(beatmap);

View File

@ -0,0 +1,50 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawable;
using osu.Game.Rulesets.Catch.UI;
namespace osu.Game.Rulesets.Catch.Tests
{
[TestFixture]
[Ignore("getting CI working")]
public class TestCaseBananaShower : Game.Tests.Visual.TestCasePlayer
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(BananaShower),
typeof(DrawableBananaShower),
typeof(CatchRuleset),
typeof(CatchRulesetContainer),
};
public TestCaseBananaShower()
: base(new CatchRuleset())
{
}
protected override Beatmap CreateBeatmap()
{
var beatmap = new Beatmap
{
BeatmapInfo = new BeatmapInfo
{
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 6,
}
}
};
beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 500, NewCombo = true });
return beatmap;
}
}
}

View File

@ -37,13 +37,15 @@ namespace osu.Game.Rulesets.Catch.UI
protected override DrawableHitObject<CatchHitObject> GetVisualRepresentation(CatchHitObject h) protected override DrawableHitObject<CatchHitObject> GetVisualRepresentation(CatchHitObject h)
{ {
var fruit = h as Fruit; switch (h)
if (fruit != null) {
case Fruit fruit:
return new DrawableFruit(fruit); return new DrawableFruit(fruit);
case JuiceStream stream:
var stream = h as JuiceStream;
if (stream != null)
return new DrawableJuiceStream(stream); return new DrawableJuiceStream(stream);
case BananaShower banana:
return new DrawableBananaShower(banana);
}
return null; return null;
} }

View File

@ -61,6 +61,8 @@
<Compile Include="Mods\CatchModRelax.cs" /> <Compile Include="Mods\CatchModRelax.cs" />
<Compile Include="Mods\CatchModSuddenDeath.cs" /> <Compile Include="Mods\CatchModSuddenDeath.cs" />
<Compile Include="Mods\CatchModAutoplay.cs" /> <Compile Include="Mods\CatchModAutoplay.cs" />
<Compile Include="Objects\BananaShower.cs" />
<Compile Include="Objects\Drawable\DrawableBananaShower.cs" />
<Compile Include="Objects\Drawable\DrawableCatchHitObject.cs" /> <Compile Include="Objects\Drawable\DrawableCatchHitObject.cs" />
<Compile Include="Objects\Drawable\DrawableDroplet.cs" /> <Compile Include="Objects\Drawable\DrawableDroplet.cs" />
<Compile Include="Objects\Drawable\DrawableJuiceStream.cs" /> <Compile Include="Objects\Drawable\DrawableJuiceStream.cs" />
@ -77,6 +79,7 @@
<Compile Include="Objects\Fruit.cs" /> <Compile Include="Objects\Fruit.cs" />
<Compile Include="Objects\TinyDroplet.cs" /> <Compile Include="Objects\TinyDroplet.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Tests\TestCaseBananaShower.cs" />
<Compile Include="Tests\TestCaseCatcherArea.cs" /> <Compile Include="Tests\TestCaseCatcherArea.cs" />
<Compile Include="Tests\TestCaseCatchStacker.cs" /> <Compile Include="Tests\TestCaseCatchStacker.cs" />
<Compile Include="Tests\TestCaseFruitObjects.cs" /> <Compile Include="Tests\TestCaseFruitObjects.cs" />

View File

@ -2,6 +2,7 @@
// 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 System; using System;
using System.Globalization;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -17,7 +18,7 @@ using osu.Framework.Graphics.Shapes;
namespace osu.Game.Graphics.UserInterface namespace osu.Game.Graphics.UserInterface
{ {
public class OsuSliderBar<T> : SliderBar<T>, IHasTooltip, IHasAccentColour public class OsuSliderBar<T> : SliderBar<T>, IHasTooltip, IHasAccentColour
where T : struct, IEquatable<T> where T : struct, IEquatable<T>, IComparable, IConvertible
{ {
private SampleChannel sample; private SampleChannel sample;
private double lastSampleTime; private double lastSampleTime;
@ -32,18 +33,25 @@ namespace osu.Game.Graphics.UserInterface
get get
{ {
var bindableDouble = CurrentNumber as BindableNumber<double>; var bindableDouble = CurrentNumber as BindableNumber<double>;
if (bindableDouble != null) var bindableFloat = CurrentNumber as BindableNumber<float>;
var floatValue = bindableDouble?.Value ?? bindableFloat?.Value;
if (floatValue != null)
{ {
if (bindableDouble.MaxValue == 1 && (bindableDouble.MinValue == 0 || bindableDouble.MinValue == -1)) var floatMinValue = bindableDouble?.MinValue ?? bindableFloat.MinValue;
return bindableDouble.Value.ToString(@"P0"); var floatMaxValue = bindableDouble?.MaxValue ?? bindableFloat.MaxValue;
return bindableDouble.Value.ToString(@"n1");
if (floatMaxValue == 1 && (floatMinValue == 0 || floatMinValue == -1))
return floatValue.Value.ToString("P0");
return floatValue.Value.ToString("N1");
} }
var bindableInt = CurrentNumber as BindableNumber<int>; var bindableInt = CurrentNumber as BindableNumber<int>;
if (bindableInt != null) if (bindableInt != null)
return bindableInt.Value.ToString(@"n0"); return bindableInt.Value.ToString("N0");
return Current.Value.ToString(); return Current.Value.ToString(CultureInfo.InvariantCulture);
} }
} }

View File

@ -4,19 +4,18 @@
using System; using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
namespace osu.Game.Overlays.Settings namespace osu.Game.Overlays.Settings
{ {
public class SettingsSlider<T> : SettingsSlider<T, OsuSliderBar<T>> public class SettingsSlider<T> : SettingsSlider<T, OsuSliderBar<T>>
where T : struct, IEquatable<T> where T : struct, IEquatable<T>, IComparable, IConvertible
{ {
} }
public class SettingsSlider<T, U> : SettingsItem<T> public class SettingsSlider<T, U> : SettingsItem<T>
where T : struct, IEquatable<T> where T : struct, IEquatable<T>, IComparable, IConvertible
where U : SliderBar<T>, new() where U : OsuSliderBar<T>, new()
{ {
protected override Drawable CreateControl() => new U protected override Drawable CreateControl() => new U
{ {

View File

@ -155,7 +155,7 @@ namespace osu.Game.Overlays
loading.Hide(); loading.Hide();
getUsersRequest?.Cancel(); getUsersRequest?.Cancel();
if (api?.IsLoggedIn == false) if (api?.IsLoggedIn != true)
return; return;
switch (Header.Tabs.Current.Value) switch (Header.Tabs.Current.Value)

View File

@ -11,7 +11,7 @@ using osu.Game.Overlays.Settings;
namespace osu.Game.Screens.Play.ReplaySettings namespace osu.Game.Screens.Play.ReplaySettings
{ {
public class ReplaySliderBar<T> : SettingsSlider<T> public class ReplaySliderBar<T> : SettingsSlider<T>
where T : struct, IEquatable<T> where T : struct, IEquatable<T>, IComparable, IConvertible
{ {
protected override Drawable CreateControl() => new Sliderbar protected override Drawable CreateControl() => new Sliderbar
{ {
@ -21,6 +21,8 @@ namespace osu.Game.Screens.Play.ReplaySettings
private class Sliderbar : OsuSliderBar<T> private class Sliderbar : OsuSliderBar<T>
{ {
public override string TooltipText => $"{CurrentNumber.Value}";
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {