diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index cf66829ceb..54d8bbd2e7 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -8,6 +8,7 @@ using osu.Framework.Timing; using osu.Game.Beatmaps.Objects; using osu.Game.Beatmaps.Objects.Osu; using osu.Game.Beatmaps.Objects.Osu.Drawable; +using OpenTK; namespace osu.Desktop.VisualTests.Tests { @@ -33,12 +34,14 @@ namespace osu.Desktop.VisualTests.Tests ourClock.ProcessFrame(); - for (int i = 0; i < 20; i++) + const int count = 10; + + for (int i = 0; i < count; i++) { var h = new Circle { StartTime = ourClock.CurrentTime + 1000 + i * 80, - Position = new OpenTK.Vector2(i * 14), + Position = new Vector2((i - count / 2) * 14), }; Add(new DrawableCircle(h) diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs index 1d292442e6..bb7b86db43 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs @@ -6,6 +6,7 @@ using osu.Framework.GameModes.Testing; using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Objects; using osu.Game.Beatmaps.Objects.Osu; using osu.Game.GameModes.Play; @@ -38,18 +39,25 @@ namespace osu.Desktop.VisualTests.Tests objects.Add(new Circle() { StartTime = time, - Position = new Vector2(RNG.Next(100, 400), RNG.Next(100, 200)) + Position = new Vector2(RNG.Next(0, 512), RNG.Next(0, 384)), + NewCombo = i % 4 == 0 }); time += 500; } + var decoder = new ConstructableBeatmapDecoder(); + + Beatmap b = new Beatmap + { + HitObjects = objects + }; + + decoder.Process(b); + Add(new Player { - Beatmap = new WorkingBeatmap(new Beatmap - { - HitObjects = objects - }) + Beatmap = new WorkingBeatmap(b) }); } diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index eb8e9260df..bbd441d25a 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -8,6 +8,7 @@ using osu.Framework.Desktop.Platform; using osu.Framework.Platform; using osu.Game.Database; using osu.Game.IPC; +using osu.Game.GameModes.Play; namespace osu.Game.Tests.Beatmaps.IO { @@ -45,7 +46,7 @@ namespace osu.Game.Tests.Beatmaps.IO var importer = new BeatmapImporter(client); if (!importer.Import(osz_path).Wait(1000)) - Assert.Fail(@"IPC took too long to send"); + Assert.Fail(@"IPC took too long to send"); ensureLoaded(osu, 10000); } @@ -78,7 +79,7 @@ namespace osu.Game.Tests.Beatmaps.IO @"BeatmapSet did not import to the database"); //ensure we were stored to beatmap database backing... - + Assert.IsTrue(resultSets.Count() == 1); IEnumerable<BeatmapInfo> resultBeatmaps = null; @@ -103,7 +104,7 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.IsTrue(set.Beatmaps.Count > 0); - var beatmap = osu.Beatmaps.GetBeatmap(set.Beatmaps[0]); + var beatmap = osu.Beatmaps.GetBeatmap(set.Beatmaps.First(b => b.Mode == PlayMode.Osu)); Assert.IsTrue(beatmap.HitObjects.Count > 0); } diff --git a/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs index f376d831cf..e3d89ac6fc 100644 --- a/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs @@ -1,13 +1,15 @@ using System; using System.Collections.Generic; using System.IO; +using osu.Game.Beatmaps.Objects; +using OpenTK.Graphics; namespace osu.Game.Beatmaps.Formats { public abstract class BeatmapDecoder { private static Dictionary<string, Type> decoders { get; } = new Dictionary<string, Type>(); - + public static BeatmapDecoder GetDecoder(TextReader stream) { var line = stream.ReadLine().Trim(); @@ -20,7 +22,39 @@ namespace osu.Game.Beatmaps.Formats { decoders[magic] = typeof(T); } - - public abstract Beatmap Decode(TextReader stream); + + public virtual Beatmap Decode(TextReader stream) + { + Beatmap b = ParseFile(stream); + Process(b); + return b; + } + + public virtual Beatmap Process(Beatmap beatmap) + { + ApplyColours(beatmap); + + return beatmap; + } + + protected abstract Beatmap ParseFile(TextReader stream); + + public virtual void ApplyColours(Beatmap b) + { + List<Color4> colours = b.ComboColors ?? new List<Color4>() { + new Color4(17, 136, 170, 255), + new Color4(102,136,0, 255), + new Color4(204,102,0, 255), + new Color4(121,9,13, 255), + }; + + int i = -1; + + foreach (HitObject h in b.HitObjects) + { + if (h.NewCombo) i = (i + 1) % colours.Count; + h.Colour = colours[i]; + } + } } } diff --git a/osu.Game/Beatmaps/Formats/ConstructableBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/ConstructableBeatmapDecoder.cs new file mode 100644 index 0000000000..e1dae7b193 --- /dev/null +++ b/osu.Game/Beatmaps/Formats/ConstructableBeatmapDecoder.cs @@ -0,0 +1,20 @@ +//Copyright (c) 2007-2016 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 System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace osu.Game.Beatmaps.Formats +{ + public class ConstructableBeatmapDecoder : BeatmapDecoder + { + protected override Beatmap ParseFile(TextReader stream) + { + throw new NotImplementedException(); + } + } +} diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 7d3b918961..e988498093 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -207,7 +207,7 @@ namespace osu.Game.Beatmaps.Formats }); } - public override Beatmap Decode(TextReader stream) + protected override Beatmap ParseFile(TextReader stream) { var beatmap = new Beatmap { @@ -270,7 +270,9 @@ namespace osu.Game.Beatmaps.Formats handleColours(beatmap, key, val); break; case Section.HitObjects: - beatmap.HitObjects.Add(HitObject.Parse(beatmap.BeatmapInfo.Mode, val)); + var h = HitObject.Parse(beatmap.BeatmapInfo.Mode, val); + if (h != null) + beatmap.HitObjects.Add(h); break; } } diff --git a/osu.Game/Beatmaps/Objects/DrawableHitObject.cs b/osu.Game/Beatmaps/Objects/DrawableHitObject.cs index d6b459b0d1..126f66be19 100644 --- a/osu.Game/Beatmaps/Objects/DrawableHitObject.cs +++ b/osu.Game/Beatmaps/Objects/DrawableHitObject.cs @@ -14,14 +14,18 @@ namespace osu.Game.Beatmaps.Objects { public abstract class DrawableHitObject : Container, IStateful<ArmedState> { + //todo: move to a more central implementation. this logic should not be at a drawable level. public Action<DrawableHitObject> OnHit; public Action<DrawableHitObject> OnMiss; + public Func<DrawableHitObject, bool> AllowHit; + public HitObject HitObject; public DrawableHitObject(HitObject hitObject) { HitObject = hitObject; + Depth = -(float)hitObject.StartTime; } private ArmedState state; @@ -31,12 +35,29 @@ namespace osu.Game.Beatmaps.Objects set { + if (state == value) return; state = value; UpdateState(state); } } + protected double? HitTime; + + protected virtual bool Hit() + { + if (State != ArmedState.Disarmed) + return false; + + if (AllowHit?.Invoke(this) == false) + return false; + + HitTime = Time; + + State = ArmedState.Armed; + return true; + } + protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game/Beatmaps/Objects/HitObject.cs b/osu.Game/Beatmaps/Objects/HitObject.cs index 44cab54fa3..ef6659224f 100644 --- a/osu.Game/Beatmaps/Objects/HitObject.cs +++ b/osu.Game/Beatmaps/Objects/HitObject.cs @@ -4,6 +4,7 @@ using osu.Game.Beatmaps.Objects.Osu; using osu.Game.Beatmaps.Samples; using osu.Game.GameModes.Play; +using OpenTK.Graphics; namespace osu.Game.Beatmaps.Objects { @@ -15,6 +16,10 @@ namespace osu.Game.Beatmaps.Objects public double StartTime; public virtual double EndTime => StartTime; + public bool NewCombo { get; set; } + + public Color4 Colour = new Color4(17, 136, 170, 255); + public double Duration => EndTime - StartTime; public HitSampleInfo Sample; diff --git a/osu.Game/Beatmaps/Objects/Osu/Circle.cs b/osu.Game/Beatmaps/Objects/Osu/Circle.cs index e276132ebc..9b7f92f29e 100644 --- a/osu.Game/Beatmaps/Objects/Osu/Circle.cs +++ b/osu.Game/Beatmaps/Objects/Osu/Circle.cs @@ -7,6 +7,5 @@ namespace osu.Game.Beatmaps.Objects.Osu { public class Circle : OsuBaseHit { - public Color4 Colour = new Color4(17, 136, 170, 255); } } diff --git a/osu.Game/Beatmaps/Objects/Osu/Drawable/DrawableCircle.cs b/osu.Game/Beatmaps/Objects/Osu/Drawable/DrawableCircle.cs index 2b52657f1e..26d7375852 100644 --- a/osu.Game/Beatmaps/Objects/Osu/Drawable/DrawableCircle.cs +++ b/osu.Game/Beatmaps/Objects/Osu/Drawable/DrawableCircle.cs @@ -8,22 +8,21 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Transformations; -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Input; using osu.Framework.MathUtils; +using OpenTK; namespace osu.Game.Beatmaps.Objects.Osu.Drawable { public class DrawableCircle : DrawableHitObject { private Sprite approachCircle; - private CirclePart circle; - private RingPart ring; - private FlashPart flash; - private ExplodePart explode; - private NumberPart number; - private GlowPart glow; + private CircleLayer circle; + private RingLayer ring; + private FlashLayer flash; + private ExplodeLayer explode; + private NumberLayer number; + private GlowLayer glow; private OsuBaseHit h; public DrawableCircle(Circle h) : base(h) @@ -31,28 +30,27 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable this.h = h; Origin = Anchor.Centre; - Alpha = 0; - Position = h.Position; - Scale = new Vector2(0.4f); + RelativePositionAxes = Axes.Both; + Position = new Vector2(h.Position.X / 512, h.Position.Y / 384); Children = new Framework.Graphics.Drawable[] { - glow = new GlowPart() - { - Colour = h.Colour, - }, - circle = new CirclePart() - { - Colour = h.Colour, - Hit = delegate { State = ArmedState.Armed; } - }, - number = new NumberPart(), - ring = new RingPart(), - flash = new FlashPart(), - explode = new ExplodePart() + glow = new GlowLayer { Colour = h.Colour }, + circle = new CircleLayer + { + Colour = h.Colour, + Hit = Hit, + }, + number = new NumberLayer(), + ring = new RingLayer(), + flash = new FlashLayer(), + explode = new ExplodeLayer + { + Colour = h.Colour, + }, approachCircle = new Sprite { Anchor = Anchor.Centre, @@ -61,7 +59,8 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable } }; - Size = new Vector2(100); + //may not be so correct + Size = circle.DrawSize; } protected override void Load(BaseGame game) @@ -71,63 +70,82 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable approachCircle.Texture = game.Textures.Get(@"Play/osu/approachcircle@2x"); } + protected override void LoadComplete() + { + base.LoadComplete(); + + //force application of the state that was set before we loaded. + UpdateState(State); + } + protected override void UpdateState(ArmedState state) { if (!IsLoaded) return; - Flush(); //move to DrawableHitObject + Flush(true); //move to DrawableHitObject - Transforms.Add(new TransformAlpha { StartTime = h.StartTime - 1000, EndTime = h.StartTime - 800, StartValue = 0, EndValue = 1 }); + double t = HitTime ?? h.StartTime; - approachCircle.Transforms.Add(new TransformScale { StartTime = h.StartTime - 1000, EndTime = h.StartTime, StartValue = new Vector2(2f), EndValue = new Vector2(0.6f) }); - approachCircle.Transforms.Add(new TransformAlpha { StartTime = h.StartTime, EndTime = h.StartTime, StartValue = 1, EndValue = 0 }); + //sane defaults + ring.Alpha = circle.Alpha = number.Alpha = approachCircle.Alpha = glow.Alpha = 1; + explode.Alpha = 0; + Scale = Vector2.One; - glow.Transforms.Add(new TransformAlpha { StartTime = h.StartTime, EndTime = h.StartTime + 400, StartValue = glow.Alpha, EndValue = 0 }); + //always-present transforms + Transforms.Add(new TransformAlpha { StartTime = t - 1000, EndTime = t - 800, StartValue = 0, EndValue = 1 }); + approachCircle.Transforms.Add(new TransformScale { StartTime = t - 1000, EndTime = t, StartValue = new Vector2(2f), EndValue = new Vector2(0.6f) }); + + //set transform delay to t==hitTime + Delay(t - Time, true); + + approachCircle.FadeOut(); + glow.FadeOut(400); switch (state) { case ArmedState.Disarmed: - Transforms.Add(new TransformAlpha { StartTime = h.StartTime + h.Duration + 200, EndTime = h.StartTime + h.Duration + 400, StartValue = 1, EndValue = 0 }); + Delay(h.Duration + 200); + FadeOut(200); break; case ArmedState.Armed: - const float flashIn = 30; - const float fadeOut = 800; + const double flash_in = 30; - //Transforms.Add(new TransformScale() { StartTime = h.StartTime, EndTime = h.StartTime + 400, StartValue = Scale, EndValue = Scale * 1.1f }); + flash.FadeTo(0.8f, flash_in); + flash.Delay(flash_in); + flash.FadeOut(100); - ring.Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0 }); - circle.Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0 }); - number.Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0 }); + explode.FadeIn(flash_in); - flash.Transforms.Add(new TransformAlpha { StartTime = h.StartTime, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0.8f }); - flash.Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn + 100, StartValue = 0.8f, EndValue = 0 }); + Delay(flash_in, true); - explode.Transforms.Add(new TransformAlpha { StartTime = h.StartTime, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 1 }); + //after the flash, we can hide some elements that were behind it + ring.FadeOut(); + circle.FadeOut(); + number.FadeOut(); - Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn + fadeOut, StartValue = 1, EndValue = 0 }); - - Transforms.Add(new TransformScale { StartTime = h.StartTime + h.Duration, EndTime = h.StartTime + h.Duration + 400, StartValue = Scale, EndValue = Scale * 1.5f, Easing = EasingTypes.OutQuad }); + FadeOut(800); + ScaleTo(Scale * 1.5f, 400, EasingTypes.OutQuad); break; } } - class NumberPart : Container + private class NumberLayer : Container { private Sprite number; - public NumberPart() + public NumberLayer() { Anchor = Anchor.Centre; Origin = Anchor.Centre; Children = new[] { - number = new Sprite - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Alpha = 1, - } + number = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Alpha = 1 + } }; } @@ -138,39 +156,39 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable } } - class GlowPart : Container + private class GlowLayer : Container { - private Sprite layer3; + private Sprite layer; - public GlowPart() + public GlowLayer() { Anchor = Anchor.Centre; Origin = Anchor.Centre; Children = new[] { - layer3 = new Sprite - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - BlendingMode = BlendingMode.Additive, - Alpha = 0.5f, - } + layer = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + BlendingMode = BlendingMode.Additive, + Alpha = 0.5f + } }; } protected override void Load(BaseGame game) { base.Load(game); - layer3.Texture = game.Textures.Get(@"Play/osu/ring-glow@2x"); + layer.Texture = game.Textures.Get(@"Play/osu/ring-glow@2x"); } } - class RingPart : Container + private class RingLayer : Container { private Sprite ring; - public RingPart() + public RingLayer() { Anchor = Anchor.Centre; Origin = Anchor.Centre; @@ -180,8 +198,8 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable ring = new Sprite { Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, + Origin = Anchor.Centre + } }; } @@ -192,11 +210,12 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable } } - class FlashPart : Container + private class FlashLayer : Container { - public FlashPart() + public FlashLayer() { Size = new Vector2(144); + Masking = true; CornerRadius = Size.X / 2; @@ -210,15 +229,15 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable { new Box { - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.Both } }; } } - class ExplodePart : Container + private class ExplodeLayer : Container { - public ExplodePart() + public ExplodeLayer() { Size = new Vector2(144); @@ -232,53 +251,21 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable { new Triangles { - RelativeSizeAxes = Axes.Both, - }, - }; - } - - class Triangles : Container - { - private Texture tex; - - protected override void Load(BaseGame game) - { - base.Load(game); - - tex = game.Textures.Get(@"Play/osu/triangle@2x"); - - for (int i = 0; i < 10; i++) - { - Add(new Sprite - { - Texture = tex, - Origin = Anchor.Centre, - Position = new Vector2(RNG.NextSingle() * DrawSize.X, RNG.NextSingle() * DrawSize.Y), - Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f), - Alpha = RNG.NextSingle() * 0.3f, - }); + RelativeSizeAxes = Axes.Both } - } - - protected override void Update() - { - base.Update(); - - foreach (Framework.Graphics.Drawable d in Children) - d.Position -= new Vector2(0, (float)(d.Scale.X * (Clock.ElapsedFrameTime / 20))); - } + }; } } - class CirclePart : Container + private class CircleLayer : Container { private Sprite disc; private Triangles triangles; - public Action Hit; + public Func<bool> Hit; - public CirclePart() + public CircleLayer() { Size = new Vector2(144); Masking = true; @@ -292,13 +279,13 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable disc = new Sprite { Anchor = Anchor.Centre, - Origin = Anchor.Centre, + Origin = Anchor.Centre }, triangles = new Triangles { BlendingMode = BlendingMode.Additive, - RelativeSizeAxes = Axes.Both, - }, + RelativeSizeAxes = Axes.Both + } }; } @@ -313,37 +300,38 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable Hit?.Invoke(); return true; } + } - class Triangles : Container + private class Triangles : Container + { + private Texture tex; + + protected override void Load(BaseGame game) { - private Texture tex; + base.Load(game); - protected override void Load(BaseGame game) + tex = game.Textures.Get(@"Play/osu/triangle@2x"); + + for (int i = 0; i < 10; i++) { - base.Load(game); - - tex = game.Textures.Get(@"Play/osu/triangle@2x"); - - for (int i = 0; i < 10; i++) + Add(new Sprite { - Add(new Sprite - { - Texture = tex, - Origin = Anchor.Centre, - Position = new Vector2(RNG.NextSingle() * DrawSize.X, RNG.NextSingle() * DrawSize.Y), - Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f), - Alpha = RNG.NextSingle() * 0.3f, - }); - } + Texture = tex, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.Both, + Position = new Vector2(RNG.NextSingle(), RNG.NextSingle()), + Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f), + Alpha = RNG.NextSingle() * 0.3f + }); } + } - protected override void Update() - { - base.Update(); + protected override void Update() + { + base.Update(); - foreach (Framework.Graphics.Drawable d in Children) - d.Position -= new Vector2(0, (float)(d.Scale.X * (Clock.ElapsedFrameTime / 20))); - } + foreach (Framework.Graphics.Drawable d in Children) + d.Position -= new Vector2(0, (float)(d.Scale.X * (Clock.ElapsedFrameTime / 2880))); } } } diff --git a/osu.Game/Beatmaps/Objects/Osu/OsuBaseHit.cs b/osu.Game/Beatmaps/Objects/Osu/OsuBaseHit.cs index 2f94c70a0e..e4bb272404 100644 --- a/osu.Game/Beatmaps/Objects/Osu/OsuBaseHit.cs +++ b/osu.Game/Beatmaps/Objects/Osu/OsuBaseHit.cs @@ -10,7 +10,6 @@ namespace osu.Game.Beatmaps.Objects.Osu public abstract class OsuBaseHit : HitObject { public Vector2 Position { get; set; } - public bool NewCombo { get; set; } [Flags] private enum HitObjectType diff --git a/osu.Game/GameModes/Play/HitRenderer.cs b/osu.Game/GameModes/Play/HitRenderer.cs index d77aaab50f..e693da527d 100644 --- a/osu.Game/GameModes/Play/HitRenderer.cs +++ b/osu.Game/GameModes/Play/HitRenderer.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps.Objects; using osu.Framework; using System; +using System.Linq; namespace osu.Game.GameModes.Play { @@ -14,6 +15,10 @@ namespace osu.Game.GameModes.Play { public Action<HitObject> OnHit; public Action<HitObject> OnMiss; + + protected Playfield Playfield; + + public IEnumerable<DrawableHitObject> DrawableObjects => Playfield.Children.Cast<DrawableHitObject>(); } public abstract class HitRenderer<T> : HitRenderer @@ -31,8 +36,6 @@ namespace osu.Game.GameModes.Play } } - private Playfield playfield; - protected abstract Playfield CreatePlayfield(); protected abstract HitObjectConverter<T> Converter { get; } @@ -47,7 +50,7 @@ namespace osu.Game.GameModes.Play Children = new Drawable[] { - playfield = CreatePlayfield() + Playfield = CreatePlayfield() }; loadObjects(); @@ -65,7 +68,7 @@ namespace osu.Game.GameModes.Play drawableObject.OnHit = onHit; drawableObject.OnMiss = onMiss; - playfield.Add(drawableObject); + Playfield.Add(drawableObject); } } diff --git a/osu.Game/GameModes/Play/Osu/OsuPlayfield.cs b/osu.Game/GameModes/Play/Osu/OsuPlayfield.cs index 111dd608c1..a6c4112321 100644 --- a/osu.Game/GameModes/Play/Osu/OsuPlayfield.cs +++ b/osu.Game/GameModes/Play/Osu/OsuPlayfield.cs @@ -12,26 +12,48 @@ namespace osu.Game.GameModes.Play.Osu { public class OsuPlayfield : Playfield { - public OsuPlayfield() + protected override Container Content => hitObjectContainer; + + private Container hitObjectContainer; + + public override Vector2 Size { - Size = new Vector2(512, 384); - Scale = new Vector2(1.6f); - Anchor = Anchor.Centre; - Origin = Anchor.Centre; + get + { + var parentSize = Parent.DrawSize; + var aspectSize = parentSize.X * 0.75f < parentSize.Y ? new Vector2(parentSize.X, parentSize.X * 0.75f) : new Vector2(parentSize.Y * 4f / 3f, parentSize.Y); + + return new Vector2(aspectSize.X / parentSize.X, aspectSize.Y / parentSize.Y) * base.Size; + } } - protected override void Load(BaseGame game) + public OsuPlayfield() { - base.Load(game); + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + RelativeSizeAxes = Axes.Both; + Size = new Vector2(0.75f); - Add(new Box() + AddInternal(new Box { + RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, Colour = Color4.Black, - Alpha = 0.5f + Alpha = 0.5f, }); + + AddInternal(hitObjectContainer = new HitObjectContainer + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + } + + class HitObjectContainer : Container + { + protected override Vector2 ChildScale => new Vector2(0.625f); } } } \ No newline at end of file diff --git a/osu.Game/GameModes/Play/Player.cs b/osu.Game/GameModes/Play/Player.cs index 860e077588..d48e252fa5 100644 --- a/osu.Game/GameModes/Play/Player.cs +++ b/osu.Game/GameModes/Play/Player.cs @@ -2,7 +2,6 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.Objects; using osu.Game.GameModes.Backgrounds; using osu.Game.GameModes.Play.Catch; @@ -12,13 +11,15 @@ using osu.Game.GameModes.Play.Taiko; using osu.Framework; using osu.Game.Database; using osu.Framework.Timing; -using osu.Framework.GameModes; using osu.Framework.Audio.Track; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.GameModes.Play { public class Player : OsuGameMode { + const bool autoplay = false; + protected override BackgroundMode CreateBackground() => new BackgroundModeCustom(@"Backgrounds/bg4"); public BeatmapInfo BeatmapInfo; @@ -124,6 +125,9 @@ namespace osu.Game.GameModes.Play hitRenderer.OnHit += delegate (HitObject h) { scoreOverlay.OnHit(h); }; hitRenderer.OnMiss += delegate (HitObject h) { scoreOverlay.OnMiss(h); }; + if (autoplay) + hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.State = ArmedState.Armed)); + Children = new Drawable[] { hitRenderer, diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b2a8cee6a5..92679b7d58 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -64,6 +64,7 @@ </ItemGroup> <ItemGroup> <Compile Include="Beatmaps\Beatmap.cs" /> + <Compile Include="Beatmaps\Formats\ConstructableBeatmapDecoder.cs" /> <Compile Include="Beatmaps\WorkingBeatmap.cs" /> <Compile Include="Beatmaps\Drawable\BeatmapSetHeader.cs" /> <Compile Include="Beatmaps\Drawable\DifficultyIcon.cs" />