Merge branch 'master' into add-droplet-hypers

This commit is contained in:
smoogipoo 2020-08-21 13:09:16 +09:00
commit 855b5ba4ed
16 changed files with 96 additions and 27 deletions

View File

@ -25,6 +25,7 @@ namespace osu.Game.Rulesets.Catch.Tests
[TestCase("hardrock-stream", new[] { typeof(CatchModHardRock) })] [TestCase("hardrock-stream", new[] { typeof(CatchModHardRock) })]
[TestCase("hardrock-repeat-slider", new[] { typeof(CatchModHardRock) })] [TestCase("hardrock-repeat-slider", new[] { typeof(CatchModHardRock) })]
[TestCase("hardrock-spinner", new[] { typeof(CatchModHardRock) })] [TestCase("hardrock-spinner", new[] { typeof(CatchModHardRock) })]
[TestCase("right-bound-hr-offset", new[] { typeof(CatchModHardRock) })]
public new void Test(string name, params Type[] mods) => base.Test(name, mods); public new void Test(string name, params Type[] mods) => base.Test(name, mods);
protected override IEnumerable<ConvertValue> CreateConvertValue(HitObject hitObject) protected override IEnumerable<ConvertValue> CreateConvertValue(HitObject hitObject)

View File

@ -1,7 +1,9 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Game.Audio;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Catch.UI;
@ -38,7 +40,11 @@ namespace osu.Game.Rulesets.Catch.Tests
new Vector2(width, 0) new Vector2(width, 0)
}), }),
StartTime = i * 2000, StartTime = i * 2000,
NewCombo = i % 8 == 0 NewCombo = i % 8 == 0,
Samples = new List<HitSampleInfo>(new[]
{
new HitSampleInfo { Bank = "normal", Name = "hitnormal", Volume = 100 }
})
}); });
} }

View File

@ -179,7 +179,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
if (amount > 0) if (amount > 0)
{ {
// Clamp to the right bound // Clamp to the right bound
if (position + amount < 1) if (position + amount < CatchPlayfield.WIDTH)
position += amount; position += amount;
} }
else else

View File

@ -27,6 +27,11 @@ namespace osu.Game.Rulesets.Catch.Objects
set => x = value; set => x = value;
} }
/// <summary>
/// Whether this object can be placed on the catcher's plate.
/// </summary>
public virtual bool CanBePlated => false;
/// <summary> /// <summary>
/// A random offset applied to <see cref="X"/>, set by the <see cref="CatchBeatmapProcessor"/>. /// A random offset applied to <see cref="X"/>, set by the <see cref="CatchBeatmapProcessor"/>.
/// </summary> /// </summary>
@ -100,6 +105,14 @@ namespace osu.Game.Rulesets.Catch.Objects
protected override HitWindows CreateHitWindows() => HitWindows.Empty; protected override HitWindows CreateHitWindows() => HitWindows.Empty;
} }
/// <summary>
/// Represents a single object that can be caught by the catcher.
/// </summary>
public abstract class PalpableCatchHitObject : CatchHitObject
{
public override bool CanBePlated => true;
}
public enum FruitVisualRepresentation public enum FruitVisualRepresentation
{ {
Pear, Pear,

View File

@ -15,14 +15,12 @@ using osuTK.Graphics;
namespace osu.Game.Rulesets.Catch.Objects.Drawables namespace osu.Game.Rulesets.Catch.Objects.Drawables
{ {
public abstract class PalpableCatchHitObject<TObject> : DrawableCatchHitObject<TObject> public abstract class PalpableDrawableCatchHitObject<TObject> : DrawableCatchHitObject<TObject>
where TObject : CatchHitObject where TObject : PalpableCatchHitObject
{ {
public override bool CanBePlated => true;
protected Container ScaleContainer { get; private set; } protected Container ScaleContainer { get; private set; }
protected PalpableCatchHitObject(TObject hitObject) protected PalpableDrawableCatchHitObject(TObject hitObject)
: base(hitObject) : base(hitObject)
{ {
Origin = Anchor.Centre; Origin = Anchor.Centre;
@ -65,9 +63,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
public abstract class DrawableCatchHitObject : DrawableHitObject<CatchHitObject> public abstract class DrawableCatchHitObject : DrawableHitObject<CatchHitObject>
{ {
public virtual bool CanBePlated => false; public virtual bool StaysOnPlate => HitObject.CanBePlated;
public virtual bool StaysOnPlate => CanBePlated;
public float DisplayRadius => DrawSize.X / 2 * Scale.X * HitObject.Scale; public float DisplayRadius => DrawSize.X / 2 * Scale.X * HitObject.Scale;

View File

@ -8,7 +8,7 @@ using osu.Game.Skinning;
namespace osu.Game.Rulesets.Catch.Objects.Drawables namespace osu.Game.Rulesets.Catch.Objects.Drawables
{ {
public class DrawableDroplet : PalpableCatchHitObject<Droplet> public class DrawableDroplet : PalpableDrawableCatchHitObject<Droplet>
{ {
public override bool StaysOnPlate => false; public override bool StaysOnPlate => false;

View File

@ -8,7 +8,7 @@ using osu.Game.Skinning;
namespace osu.Game.Rulesets.Catch.Objects.Drawables namespace osu.Game.Rulesets.Catch.Objects.Drawables
{ {
public class DrawableFruit : PalpableCatchHitObject<Fruit> public class DrawableFruit : PalpableDrawableCatchHitObject<Fruit>
{ {
public DrawableFruit(Fruit h) public DrawableFruit(Fruit h)
: base(h) : base(h)

View File

@ -6,7 +6,7 @@ using osu.Game.Rulesets.Judgements;
namespace osu.Game.Rulesets.Catch.Objects namespace osu.Game.Rulesets.Catch.Objects
{ {
public class Droplet : CatchHitObject public class Droplet : PalpableCatchHitObject
{ {
public override Judgement CreateJudgement() => new CatchDropletJudgement(); public override Judgement CreateJudgement() => new CatchDropletJudgement();
} }

View File

@ -6,7 +6,7 @@ using osu.Game.Rulesets.Judgements;
namespace osu.Game.Rulesets.Catch.Objects namespace osu.Game.Rulesets.Catch.Objects
{ {
public class Fruit : CatchHitObject public class Fruit : PalpableCatchHitObject
{ {
public override Judgement CreateJudgement() => new CatchJudgement(); public override Judgement CreateJudgement() => new CatchJudgement();
} }

View File

@ -0,0 +1,17 @@
{
"Mappings": [{
"StartTime": 3368,
"Objects": [{
"StartTime": 3368,
"Position": 374
}]
},
{
"StartTime": 3501,
"Objects": [{
"StartTime": 3501,
"Position": 446
}]
}
]
}

View File

@ -0,0 +1,20 @@
osu file format v14
[General]
StackLeniency: 0.7
Mode: 2
[Difficulty]
HPDrainRate:6
CircleSize:4
OverallDifficulty:9.6
ApproachRate:9.6
SliderMultiplier:1.9
SliderTickRate:1
[TimingPoints]
2169,266.666666666667,4,2,1,70,1,0
[HitObjects]
374,60,3368,1,0,0:0:0:0:
410,146,3501,1,2,0:1:0:0:

View File

@ -10,15 +10,21 @@ namespace osu.Game.Rulesets.Catch.UI
{ {
public class CatchPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer public class CatchPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer
{ {
private const float playfield_size_adjust = 0.8f;
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
private readonly Container content; private readonly Container content;
public CatchPlayfieldAdjustmentContainer() public CatchPlayfieldAdjustmentContainer()
{ {
Anchor = Anchor.TopCentre; // because we are using centre anchor/origin, we will need to limit visibility in the future
Origin = Anchor.TopCentre; // to ensure tall windows do not get a readability advantage.
// it may be possible to bake the catch-specific offsets (-100..340 mentioned below) into new values
// which are compatible with TopCentre alignment.
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Size = new Vector2(0.86f); // matches stable's vertical offset for catcher plate Size = new Vector2(playfield_size_adjust);
InternalChild = new Container InternalChild = new Container
{ {
@ -27,7 +33,7 @@ namespace osu.Game.Rulesets.Catch.UI
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit, FillMode = FillMode.Fit,
FillAspectRatio = 4f / 3, FillAspectRatio = 4f / 3,
Child = content = new ScalingContainer { RelativeSizeAxes = Axes.Both } Child = content = new ScalingContainer { RelativeSizeAxes = Axes.Both, }
}; };
} }
@ -40,8 +46,14 @@ namespace osu.Game.Rulesets.Catch.UI
{ {
base.Update(); base.Update();
// in stable, fruit fall vertically from -100 to 340.
// to emulate this, we want to make our playfield 440 gameplay pixels high.
// we then offset it -100 vertically in the position set below.
const float stable_v_offset_ratio = 440 / 384f;
Scale = new Vector2(Parent.ChildSize.X / CatchPlayfield.WIDTH); Scale = new Vector2(Parent.ChildSize.X / CatchPlayfield.WIDTH);
Size = Vector2.Divide(Vector2.One, Scale); Position = new Vector2(0, -100 * stable_v_offset_ratio + Scale.X);
Size = Vector2.Divide(new Vector2(1, stable_v_offset_ratio), Scale);
} }
} }
} }

View File

@ -216,6 +216,9 @@ namespace osu.Game.Rulesets.Catch.UI
/// <returns>Whether the catch is possible.</returns> /// <returns>Whether the catch is possible.</returns>
public bool AttemptCatch(CatchHitObject fruit) public bool AttemptCatch(CatchHitObject fruit)
{ {
if (!fruit.CanBePlated)
return false;
var halfCatchWidth = catchWidth * 0.5f; var halfCatchWidth = catchWidth * 0.5f;
// this stuff wil disappear once we move fruit to non-relative coordinate space in the future. // this stuff wil disappear once we move fruit to non-relative coordinate space in the future.

View File

@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.UI
lastPlateableFruit.OnLoadComplete += _ => action(); lastPlateableFruit.OnLoadComplete += _ => action();
} }
if (result.IsHit && fruit.CanBePlated) if (result.IsHit && fruit.HitObject.CanBePlated)
{ {
// create a new (cloned) fruit to stay on the plate. the original is faded out immediately. // create a new (cloned) fruit to stay on the plate. the original is faded out immediately.
var caughtFruit = (DrawableCatchHitObject)CreateDrawableRepresentation?.Invoke(fruit.HitObject); var caughtFruit = (DrawableCatchHitObject)CreateDrawableRepresentation?.Invoke(fruit.HitObject);

View File

@ -60,12 +60,7 @@ namespace osu.Game.Rulesets.Mania.Mods
Column = column.Key, Column = column.Key,
StartTime = locations[i].startTime, StartTime = locations[i].startTime,
Duration = duration, Duration = duration,
Samples = locations[i].samples, NodeSamples = new List<IList<HitSampleInfo>> { locations[i].samples, Array.Empty<HitSampleInfo>() }
NodeSamples = new List<IList<HitSampleInfo>>
{
locations[i].samples,
locations[i + 1].samples
}
}); });
} }

View File

@ -2,6 +2,8 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Game.Overlays;
namespace osu.Game.Tests.Visual.Multiplayer namespace osu.Game.Tests.Visual.Multiplayer
{ {
@ -10,11 +12,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
{ {
protected override bool UseOnlineAPI => true; protected override bool UseOnlineAPI => true;
[Cached]
private MusicController musicController { get; set; } = new MusicController();
public TestSceneMultiScreen() public TestSceneMultiScreen()
{ {
Screens.Multi.Multiplayer multi = new Screens.Multi.Multiplayer(); Screens.Multi.Multiplayer multi = new Screens.Multi.Multiplayer();
AddStep(@"show", () => LoadScreen(multi)); AddStep("show", () => LoadScreen(multi));
AddUntilStep("wait for loaded", () => multi.IsLoaded);
} }
} }
} }