Esempio n. 1
0
        public LongVisualNote([NotNull] VisualBeatmap beatmap, [NotNull] LongNote baseNote, [NotNull] StageMetrics metrics)
            : base(beatmap, baseNote)
        {
            _baseNote      = baseNote;
            _metrics       = metrics;
            _noteRectangle = new TexturedRectangle(beatmap.GraphicsDevice);

            PreviewStartY = beatmap.CalculateY(baseNote.StartTick, metrics, metrics.FinishLineY);
            PreviewEndY   = beatmap.CalculateY(baseNote.EndTick, metrics, metrics.FinishLineY);
        }
Esempio n. 2
0
        public FloorVisualNote([NotNull] VisualBeatmap beatmap, [NotNull] FloorNote baseNote, [NotNull] StageMetrics metrics)
            : base(beatmap, baseNote)
        {
            _baseNote       = baseNote;
            _metrics        = metrics;
            _noteRectangle  = new TexturedRectangle(beatmap.GraphicsDevice);
            _linkHexahedron = new ColoredHexahedron(beatmap.GraphicsDevice);

            PreviewY = beatmap.CalculateY(baseNote.Tick, metrics, metrics.FinishLineY);
        }
        public SkyVisualNote([NotNull] VisualBeatmap beatmap, [NotNull] SkyNote baseNote, [NotNull] ArcVisualNote parent, [NotNull] StageMetrics metrics)
            : base(beatmap, baseNote)
        {
            _metrics = metrics;

            Parent = parent;

            PreviewY = beatmap.CalculateY(baseNote.Tick, metrics, metrics.FinishLineY);

            var graphicsDevice = beatmap.GraphicsDevice;

            _graphicsDevice = graphicsDevice;

            _vertexBuffer1 = new VertexBuffer(graphicsDevice, VertexPositionColorTexture.VertexDeclaration, 16, BufferUsage.WriteOnly);
            _indexBuffer1  = new IndexBuffer(graphicsDevice, IndexElementSize.SixteenBits, 24, BufferUsage.WriteOnly);

            _vertexBuffer2 = new VertexBuffer(graphicsDevice, VertexPositionColorTexture.VertexDeclaration, 8, BufferUsage.WriteOnly);
            _indexBuffer2  = new IndexBuffer(graphicsDevice, IndexElementSize.SixteenBits, 12, BufferUsage.WriteOnly);

            var indices1 = new ushort[] {
                // bottom, top
                0, 1, 2,
                2, 1, 3,
                4, 5, 6,
                6, 5, 7,

                // front, back
                8, 9, 10,
                10, 9, 11,
                12, 13, 14,
                14, 13, 15
            };

            _indexBuffer1.SetData(indices1);

            var indices2 = new ushort[] {
                0, 1, 2,
                2, 1, 3,
                4, 5, 6,
                6, 5, 7,
            };

            _indexBuffer2.SetData(indices2);

            _shadowRectangle = new ColoredRectangle(graphicsDevice);
        }
        public ArcVisualNote([NotNull] VisualBeatmap beatmap, [NotNull] ArcNote baseNote, [NotNull] StageMetrics metrics)
            : base(beatmap, baseNote)
        {
            _baseNote = baseNote;
            _metrics  = metrics;

            PreviewStartY = beatmap.CalculateY(baseNote.StartTick, metrics, metrics.FinishLineY);
            PreviewEndY   = beatmap.CalculateY(baseNote.EndTick, metrics, metrics.FinishLineY);

            _arcMesh = new BottomlessColoredTriangularPrism(beatmap.GraphicsDevice);
            _shadow  = new ColoredParallelogram(beatmap.GraphicsDevice);
            _support = new TexturedRectangle(beatmap.GraphicsDevice);
            _header  = new BottomlessColoredTetrahedron(beatmap.GraphicsDevice);

            if (baseNote.SkyNotes != null && baseNote.SkyNotes.Length > 0)
            {
                SkyVisualNotes = baseNote.SkyNotes.Select(n => new SkyVisualNote(beatmap, n, this, metrics)).ToArray();
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Calculate a beatmap time's Y distance according to timing and metrics.
        /// </summary>
        /// <param name="beatmapTicks">Current beatmap time, in milliseconds. Please note that beatmap time does not equal to audio time when a beatmap's audio offset is non-zero.</param>
        /// <param name="metrics">Stage metrics.</param>
        /// <param name="addition">The final addition value. This value is directly added to the calculated value. Example usage: assign this parameter the finishing line's Y distance.</param>
        /// <returns></returns>
        public float CalculateY(int beatmapTicks, [NotNull] StageMetrics metrics, float addition)
        {
            const float timeScale = 0.6f;

            var timingNotes = Timings;

            if (timingNotes.Length == 0)
            {
                return(0);
            }

            var measureLength = metrics.FloorNoteHeight * 6;

            var result = 0f;

            for (var i = 0; i < timingNotes.Length; ++i)
            {
                var timingNote = timingNotes[i];

                if (beatmapTicks < timingNote.Tick)
                {
                    break;
                }

                if (i >= timingNotes.Length - 1 || beatmapTicks < timingNotes[i + 1].Tick)
                {
                    result += (beatmapTicks - timingNote.Tick) * timingNote.Bpm;
                }
                else
                {
                    result += (timingNotes[i + 1].Tick - timingNote.Tick) * timingNote.Bpm;
                }
            }

            result /= 100_000f;

            result *= measureLength * timeScale * metrics.Speed;

            result += addition;

            return(result);
        }
Esempio n. 6
0
        /// <summary>
        /// Creates a new <see cref="VisualBeatmap"/> instance from a <see cref="Beatmap"/> using specified stage metrics.
        /// </summary>
        /// <param name="graphicsDevice">A <see cref="Microsoft.Xna.Framework.Graphics.GraphicsDevice"/> used to draw the beatmap's notes.</param>
        /// <param name="baseBeatmap"></param>
        /// <param name="metrics">Stage metrics.</param>
        public VisualBeatmap([NotNull] GraphicsDevice graphicsDevice, [NotNull] Beatmap baseBeatmap, [NotNull] StageMetrics metrics)
        {
            GraphicsDevice = graphicsDevice;
            BaseBeatmap    = baseBeatmap;

            Timings = baseBeatmap.Notes.Where(n => n.Type == NoteType.Timing).Cast <TimingNote>().ToArray();

            var visualNotes = baseBeatmap.Notes.Where(n => n.Type != NoteType.Timing).Select <NoteBase, VisualNoteBase>(n => {
                switch (n.Type)
                {
                case NoteType.Floor:
                    return(new FloorVisualNote(this, (FloorNote)n, metrics));

                case NoteType.Long:
                    return(new LongVisualNote(this, (LongNote)n, metrics));

                case NoteType.Arc:
                    return(new ArcVisualNote(this, (ArcNote)n, metrics));

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }).ToArray();

            VisualNotes = visualNotes;

            // Scan sync sky notes and add lines between the floor note and sky note.
            // Credits: @money, @RW, @JDF, @L-F0rce

            var allArcVisualNotes = visualNotes.Where(note => note.Type == NoteType.Arc).Cast <ArcVisualNote>().ToArray();

            for (var i = 0; i < visualNotes.Length; ++i)
            {
                var visualNote = visualNotes[i];

                if (visualNote.Type != NoteType.Floor || i >= visualNotes.Length - 1)
                {
                    continue;
                }

                var n         = (FloorVisualNote)visualNote;
                var floorBase = (FloorNote)n.BaseNote;

                // TODO: Naive method. Should be optimized.
                foreach (var arcVisualNote in allArcVisualNotes)
                {
                    if (arcVisualNote.SkyVisualNotes == null || arcVisualNote.SkyVisualNotes.Length == 0)
                    {
                        continue;
                    }

                    foreach (var skyVisualNote in arcVisualNote.SkyVisualNotes)
                    {
                        if (Math.Abs(((SkyNote)skyVisualNote.BaseNote).Tick - floorBase.Tick) <= 1)
                        {
                            n.SynchronizedSkyVisualNote = skyVisualNote;
                            break;
                        }
                    }

                    if (n.SynchronizedSkyVisualNote != null)
                    {
                        break;
                    }
                }
            }

            // "Supports"
            foreach (var arcVisualNote in allArcVisualNotes)
            {
                var n = (ArcNote)arcVisualNote.BaseNote;

                var ancestor = allArcVisualNotes.FirstOrDefault(note => {
                    var anotherArcNote = (ArcNote)note.BaseNote;
                    return(anotherArcNote.EndTick == n.StartTick && anotherArcNote.IsPlayable && anotherArcNote.Color == n.Color);
                });

                if (ancestor == null)
                {
                    arcVisualNote.ShouldDrawSupport = true;
                    arcVisualNote.ShouldDrawHeader  = true;
                    continue;
                }

                if (!((ArcNote)ancestor.BaseNote).StartY.Equals(((ArcNote)ancestor.BaseNote).EndY))
                {
                    arcVisualNote.ShouldDrawSupport = true;
                }
            }
        }