Пример #1
0
        public override EffectLayer Render(IGameState gamestate)
        {
            _previousAnimationTime = _currentAnimationTime;
            _currentAnimationTime  = GetAnimationTime() % Properties.AnimationDuration;

            EffectLayer gradient_layer = new EffectLayer();

            if (Properties.AnimationRepeat > 0)
            {
                if (_playTimes >= Properties.AnimationRepeat)
                {
                    return(gradient_layer);
                }

                if (_currentAnimationTime < _previousAnimationTime)
                {
                    _playTimes++;
                }
            }
            else
            {
                _playTimes = 0;
            }

            EffectLayer gradient_layer_temp = new EffectLayer();

            using (Graphics g = gradient_layer_temp.GetGraphics())
            {
                Properties.AnimationMix.Draw(g, _currentAnimationTime);
            }

            Rectangle rect = new Rectangle(0, 0, Effects.canvas_width, Effects.canvas_height);

            if (Properties.ScaleToKeySequenceBounds)
            {
                var region = Properties.Sequence.GetAffectedRegion();
                rect = new Rectangle((int)region.X, (int)region.Y, (int)region.Width, (int)region.Height);
            }

            using (Graphics g = gradient_layer.GetGraphics())
            {
                g.DrawImage(gradient_layer_temp.GetBitmap(), rect, new Rectangle(0, 0, Effects.canvas_width, Effects.canvas_height), GraphicsUnit.Pixel);
            }

            gradient_layer_temp.Dispose();

            if (Properties.ForceKeySequence)
            {
                gradient_layer.OnlyInclude(Properties.Sequence);
            }

            return(gradient_layer);
        }
Пример #2
0
        public override EffectLayer Render(IGameState gamestate)
        {
            EffectLayer animationLayer = new EffectLayer();

            // Calculate elapsed time since last Render call
            long dt = _animTimeStopwatch.ElapsedMilliseconds;

            _animTimeStopwatch.Restart();

            // Update all running animations. We have to call "ToList()" to prevent "Collection was modified; enumeration operation may not execute"
            runningAnimations.ToList().ForEach(anim => {
                anim.currentTime += dt / 1000f;
                if (Properties.AnimationRepeat > 0)
                {
                    anim.playTimes += (int)(anim.currentTime / Properties.AnimationDuration);
                }
                anim.currentTime %= Properties.AnimationDuration;
            });

            // Remove any animations that have completed their play times
            if (Properties.AnimationRepeat > 0)
            {
                runningAnimations.RemoveAll(ra => ra.playTimes >= Properties.AnimationRepeat);
            }

            // Check to see if the gamestate will cause any animations to trigger
            CheckTriggers(gamestate);

            // Render each playing animation. We have to call "ToList()" to prevent "Collection was modified; enumeration operation may not execute"
            runningAnimations.ToList().ForEach(anim => {
                EffectLayer temp = new EffectLayer();

                // Default values for the destination rect (the area that the canvas is drawn to) and animation offset
                Rectangle destRect = new Rectangle(0, 0, Effects.canvas_width, Effects.canvas_height);
                PointF offset      = Properties.KeyTriggerTranslate ? anim.offset : PointF.Empty;

                // When ScaleToKeySequenceBounds is true, additional calculations are needed on the destRect and offset:
                if (Properties.ScaleToKeySequenceBounds)
                {
                    // The dest rect should simply be the bounding region of the affected keys
                    RectangleF affectedRegion = Properties.Sequence.GetAffectedRegion();
                    destRect = Rectangle.Truncate(affectedRegion);

                    // If we are scaling to key sequence bounds, we need to adapt the offset of the pressed key so that it
                    // remains where it is after the bound - scaling operation.
                    // Let's consider only 1 dimension (X) for now since it makes it easier to think about. The scaling process
                    // is: the whole canvas width is scaled down to the width of the affected region, and then it offset by the
                    // X of the affected region. To have a point that remains the same, we need to reposition it when it's being
                    // used on the canvas, therefore this process needs to be inverted: 1.take the original offset of X and
                    // subtract the affected region's X, thereby giving us the distance from the edge of the affected region to
                    // the offset; 2. scale this up to counter-act the down-scaling done, so we calculate the change in scale off
                    // the canvas by dividing canvas width by the affected region's width; 3.multiply these two numbers together
                    // and that's our new X offset.
                    // This probably makes no sense and I'll forget how it works immediately, but hopefully it helps a little in
                    // future if this code ever needs to be revised. It's embarassing how long it took to work this equation out.
                    offset.X = (offset.X - affectedRegion.X) * (Effects.canvas_width / affectedRegion.Width);
                    offset.Y = (offset.Y - affectedRegion.Y) * (Effects.canvas_height / affectedRegion.Height);
                }

                // Draw the animation to a temporary canvas
                using (Graphics g = temp.GetGraphics())
                    Properties.AnimationMix.Draw(g, anim.currentTime, 1f, offset);

                // Draw from this temp canvas to the actual layer, performing the scale down if it's needed.
                using (Graphics g = animationLayer.GetGraphics())
                    g.DrawImage(temp.GetBitmap(), destRect, new Rectangle(0, 0, Effects.canvas_width, Effects.canvas_height), GraphicsUnit.Pixel);

                temp.Dispose();
            });

            if (Properties.ForceKeySequence)
            {
                animationLayer.OnlyInclude(Properties.Sequence);
            }

            return(animationLayer);
        }