在Windows 8 Metro中的烟花动画

3
我正在尝试制作一段动画,其中一个类似火箭的东西将向上飞到屏幕上方,然后爆炸成各个部分,并沿着路径下降并像真正的爆竹一样消失。我已经尝试使用更新循环和绘制循环,然后在位图上渲染图像来制作它。但是动画中存在很多延迟。我想在我的游戏结束时实现这个功能,当用户点击屏幕时,火箭将前往该位置,然后爆炸。我尝试过的代码在此处...
public class Plotter : UserControl, IDisposable
    {
        Random _rand = new Random((int)DateTime.Now.Ticks);
        WriteableBitmap _particleBmp;
        EventBlob[] _data;
        private int NUMPBLOBS = 25;
        private const int CANWIDTH = 1366;
        private const int CANHEIGHT = 768;
        double _lastx, _lasty;

        public Plotter()
        {
        }

        public async Task PlotterMethod(Point current)
        {
            _lastx = current.X;
            _lasty = current.Y;
            await Setup();
        }

        private async Task Setup()
        {
            _particleBmp = await Util.LoadBitmap("tspark.png");

            CompositionTarget.Rendering += CompositionTarget_Rendering;

            _data = new EventBlob[NUMPBLOBS];

            int ang = 0;
            for (int i = 0; i < NUMPBLOBS; i++)
            {
                EventBlob eb = new EventBlob();

                eb.img = _particleBmp;
                eb.SourceRect = new Rect(0, 0, 30, 30);

                eb.Position.X = _rand.Next((int)_lastx - 10, (int)_lastx + 10);
                eb.Position.Y = _rand.Next((int)_lasty - 10, (int)_lasty + 10);
                eb.VX = 5;
                eb.VY = 5;
                eb.angle = ang;
                ang += 36 / 5;

                eb.Opacity = 1;
                eb.BlendMode = WriteableBitmapExtensions.BlendMode.Additive;
                eb.FadeRate = _rand.NextDouble() * 0.005 + 0.002;
                Color c = new Color();

                c.A = (byte)0;
                c.R = (byte)_rand.Next(0, 255);
                c.G = (byte)_rand.Next(0, 255);
                c.B = (byte)_rand.Next(0, 255);

                eb.Color = c;
                _data[i] = eb;
            }
        }

        int counterupdate = 0;
        void CompositionTarget_Rendering(object sender, object e)
        {
            if (counterupdate % 2 == 0)
            {
                Update();
                DrawBitmap();
            }
            counterupdate++;
        }

        int count = 0;
        bool opacitycheck = true;
        private void Update()
        {
            bool isallclear = true;
            for (int i = 0; i < _data.Length; i++)
            {
                var p = _data[i];

                if (i < 51)
                {
                    p.VX = 2 * Math.Cos(p.angle);
                    p.VY = 2 * Math.Sin(p.angle);
                }

                p.Position.X += p.VX;
                p.Position.Y += p.VY;

                if (opacitycheck)
                {
                    if (p.Color.A + 30 < 255)
                        p.Color.A += 30;
                    else
                    {
                        opacitycheck = false;
                        p.Color.A = 255;
                    }
                }
                else
                {
                    if (p.Color.A - 30 > 0)
                        p.Color.A -= 30;
                    else
                    {
                        p.Color.A = 0;
                    }
                }

                if (p.Color.A != 0)
                {
                    isallclear = false;
                }
            }

            count++;

            if (isallclear)
            {
                _data = new EventBlob[0];
                CompositionTarget.Rendering -= CompositionTarget_Rendering;
                NUMPBLOBS = 0;
                opacitycheck = true;
                Completed(this, null);
            }
        }

        private void DrawBitmap()
        {
            using (TargetBmp.GetBitmapContext())
            {
                TargetBmp.Clear();

                for (int i = 0; i < _data.Length; i++)
                {
                    var b = _data[i];
                    this.TargetBmp.Blit(b.Position, b.img, b.SourceRect, b.Color, b.BlendMode);  
                }

                TargetBmp.Invalidate();
            }
        }

        public WriteableBitmap TargetBmp { get; set; }

        public Image Imagemain { get; set; }

        public event EventHandler<object> Completed;

        public void Dispose()
        {
        }
    }

    public class EventBlob
    {
        public double Opacity { get; set; }
        public double FadeRate { get; set; }
        public Color Color;
        public Rect SourceRect { get; set; }
        public WriteableBitmap img { get; set; }
        public Point Position;
        public double VX { get; set; }
        public double VY { get; set; }
        public WriteableBitmapExtensions.BlendMode BlendMode;
        public double angle { get; set; }
    }

在我的主页中,我是这样调用它的...
 async void MainPage_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            if (LayoutRoot.Children.Count < 6)
            {
                Plotter asd = new Plotter();
                await asd.PlotterMethod(e.GetCurrentPoint(LayoutRoot).Position);
                WriteableBitmap _wb = new WriteableBitmap(1366, 786);
                asd.TargetBmp = _wb;
                Image image = new Image();
                image.Height = 786;
                image.Width = 1366;
                image.Stretch = Stretch.Fill;
                image.Source = _wb;
                asd.Imagemain = image;
                asd.Completed += asd_Completed;

                LayoutRoot.Children.Add(image);
            }
        }

        void asd_Completed(object sender, object e)
        {
            var obj = (Plotter)sender;
            LayoutRoot.Children.Remove(obj.Imagemain);
            obj.Dispose();
        }

但如果我创建这4个对象,那么延迟太大,fps 降至10帧。

请建议更好的方式或优化此代码的方法。谢谢。

1个回答

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接