1. 程式人生 > >win10 uwp 螢火蟲效果

win10 uwp 螢火蟲效果

pri bound gif 全部 目的 疑問 creat += ldoc

原文:win10 uwp 螢火蟲效果

本文在Nukepayload2指導下,使用他的思想用C#寫出來。

本文告訴大家,如何使用 win2d 做出螢火蟲效果。

安裝 win2d

安裝win2d的方法請使用 Nuget 下載的方法,參見:win10 uwp win2d

技術分享圖片

下面先讓大家看一下效果圖再告訴大家如何做

技術分享圖片

創建界面

界面只需要很簡單兩句代碼,第一句代碼是命名引用,第二句代碼就是添加 win2d

    xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"

        <canvas:CanvasAnimatedControl
x:Name="canvas" ClearColor="Black" Update="Canvas_OnUpdate" Draw="Canvas_Draw">
</canvas:CanvasAnimatedControl>

這裏為何使用 CanvasAnimatedControl 而不是使用 CanvasControl ?因為需要進行更新,CanvasAnimatedControl提供了一些事件,這些事件可以用來做動畫。

後臺的方法

Canvas_OnUpdate就寫更新所有螢火蟲的代碼,在Canvas_Draw就寫畫出螢火蟲的代碼。

螢火蟲

於是開始創建螢火蟲的代碼,在創建之前,需要一個隨機的類,這個類用於控制螢火蟲的呼吸和移動,都是隨機的。

在指定的範圍之內,隨機取一個點,這個點作為目的的點。於是當前的值就開始移動向目的的點,移動的過程存在速度。

技術分享圖片

從這裏可以知道,這個類需要下面這些屬性

        public double Value { get; set; }
        public double To { get; set; }
        public double Dalue { get; set; }

        public double Ma { get
; set; } public double Mi { get; set; } /// <summary> /// 加速度 /// </summary> public double Po { get; set; }

其中 Dalue 就是速度,從 Value 到 To 的速度,這個速度在隨時可以被修改。

下面是這個類全部代碼

    class Ran
    {
        public Ran(double value, double ma, double mi)
        {
            Value = value;
            Ma = ma;
            Mi = mi;
            To = ran.NextDouble() * (Ma - Mi) + Mi;
        }

        public double Value { get; set; }
        public double To { get; set; }
        public double Dalue { get; set; }

        public double Ma { get; set; }

        public double Mi { get; set; }

        public bool EasingFunction { get; set; }

        /// <summary>
        /// 加速度
        /// </summary>
        public double Po { get; set; }

        public void Time(TimeSpan time)
        {

            if (Math.Abs(Dalue) < 0.000001)
            {
                if (Math.Abs(Po) < 0.0001)
                {
                    Dalue = Math.Abs(Value - To) / ran.Next(10, 300);
                }
                else
                {
                    Dalue = Po;
                }
            }
            //減數
            if (EasingFunction && Math.Abs(Value - To) < Dalue*10/*如果接近*/)
            {
                Dalue /= 2;
                if (Math.Abs(Dalue) < 1)
                {
                    Dalue = 1;
                }
            }
            int n = 1;
            if (Value > To)
            {
                n = n * -1;
            }
            Value += n * Dalue * time.TotalSeconds * 2;
            if (n > 0 && Value >= To)
            {
                Value = To;
                To = ran.NextDouble() * (Ma - Mi) + Mi;
                Dalue = 0;
            }
            if (n < 0 && Value <= To)
            {
                Value = To;
                To = ran.NextDouble() * (Ma - Mi) + Mi;
                Dalue = 0;
            }
        }


        private static Random ran = new Random();
    }

下面就是主要的類FireflyParticle包含了位置和顏色,不同透明度,當然不透明度可以做呼吸效果,於是這些值都需要做隨機移動

    class FireflyParticle
    {
        public FireflyParticle(Rect bound)
        {
            Point = new Point(ran.Next((int) bound.Width), ran.Next((int) bound.Height));
            _x = new Ran(Point.X, bound.Width, 0)
            {
                EasingFunction = true,
            };
            _y = new Ran(Point.Y, bound.Height, 0)
            {
                EasingFunction = true,
            };
            _radius = new Ran(ran.Next(2, 5), 5, 2)
            {
                Po = 0.71
            };
            Bound = bound;
        }

        public FireflyParticle()
        {
        }

        public void Time(TimeSpan time)
        {
            _radius.Time(time);
            _opColor.Time(time);
            _x.Time(time);
            _y.Time(time);

            Radius = _radius.Value;
            OpColor = _opColor.Value;
            Point = new Point(_x.Value, _y.Value);
        }

        public Point Point { get; set; }

        public Rect Bound
        {
            get { return _bound; }
            set
            {
                _bound = value;
                _x.Ma = value.Width;
                _y.Ma = value.Height;
            }
        }

        public double Radius { get; set; } = 10;
        public Color CenterColor { get; set; } = Color.FromArgb(255, 252, 203, 89);
        public double OpColor { set; get; } = 1;
        private static Random ran = new Random();

        private Ran _radius;
        private Ran _opColor = new Ran(1, 1, 0.001);

        private Ran _x;
        private Ran _y;
        private Rect _bound;
    }

看到這,是不是覺得參數存在 time 無法理解?這裏的使用 time 是為了在性能比較差的電腦得到效果和性能比較好的一樣,雖然中途有一些沒有顯示的,但是計算結果相同,不會出現性能差的電腦,動畫速度和性能好的電腦不一樣。

動畫

下面就是更新所有的值,創建屬性FireflyParticle用於放所有的類,因為很簡單,我就不解釋。

        private List<FireflyParticle> FireflyParticle { set; get; } = new List<FireflyParticle>();

        private void BpyaxxjwkQwknemobzPage_Loaded(object sender, RoutedEventArgs e)
        {
            if (!FireflyParticle.Any())
            {
                Rect bound = new Rect(0, 0, canvas.ActualWidth, canvas.ActualHeight);
                for (int i = 0; i < 100; i++)
                {
                    FireflyParticle.Add(new FireflyParticle(bound));
                }
            }
        }

         private void Canvas_OnUpdate(ICanvasAnimatedControl sender, CanvasAnimatedUpdateEventArgs args)
        {
            foreach (var temp in FireflyParticle)
            {
                temp.Time(args.Timing.ElapsedTime);
            }
        }

把所有的值都進行變化,就是在做動畫,但是移動距離不能太長,移動的算法在上面的隨機類寫的,算法很簡單,也不是關鍵,於是在這裏就不說了。

核心代碼

這裏的核心就是畫出來,如何在 win2d 畫出一個點,把這個點高斯模糊。不知道大家知道 PhotoShop ,這裏用到了圖層,需要自己心中知道是什麽東西。現在的圖片一般都是很多個圖片合成,於是可以把一個點作為一個圖層,到時候把這些點合並就是上面給大家看到的圖。

如何在 win2d 使用圖層,主要的類是CanvasCommandList用它就可以做出圖層,最好使用DrawImage把他弄出來。

      private void Canvas_Draw(ICanvasAnimatedControl sender, CanvasAnimatedDrawEventArgs args)
        {
            using (var session = args.DrawingSession)
            {
                 using (var cl = new CanvasCommandList(session))
                 using (var ds = cl.CreateDrawingSession())
                 {
                    //這裏就是圖層
                    // session.DrawImage(cl); 把 圖層畫出來

                 }
            }
        }

如何對圖層做模糊?在win2d有很多效果,先嘗試把點畫出來,效果圖:

技術分享圖片

需要知道所有的效果都是可以直接畫出來,我用的方法很簡單,就直接寫代碼

   class GlowEffectGraph : IDisposable
    {
        private MorphologyEffect morphology;
        public GlowEffectGraph()
        {
            Blur.BlurAmount = 10;
            Blur.BorderMode = EffectBorderMode.Soft;

            morphology = new MorphologyEffect()
            {
                Mode = MorphologyEffectMode.Dilate,
                Width = 10,
                Height = 10,
            };

            Blur.Source = morphology;

        }

        public GaussianBlurEffect Blur { get; set; } = new GaussianBlurEffect();

        public void Dispose()
        {
            Blur.Dispose();
            morphology.Dispose();
        }

        public void Setup(ICanvasImage canvas, double amount = 10)
        {
            morphology.Source = canvas;
            amount = Math.Min(amount / 2, 100);
            morphology.Width = (int) Math.Truncate(Math.Floor(amount));
            morphology.Height = (int) Math.Truncate(Math.Floor(amount));
            Blur.BlurAmount = (float) amount;
        }
    }

如何要把圖層畫出來,那麽修改Canvas_Draw的代碼

     private void Canvas_Draw(ICanvasAnimatedControl sender, CanvasAnimatedDrawEventArgs args)
        {
            using (var session = args.DrawingSession)
            {
                foreach (var temp in FireflyParticle)
                {
                    using (var cl = new CanvasCommandList(session))
                    using (var ds = cl.CreateDrawingSession())
                    {
                        var c = temp.CenterColor;
                        c.A = (byte) (temp.OpColor * 255);
                        ds.FillCircle((float) temp.Point.X, (float) temp.Point.Y, (float) temp.Radius, c);
                        using (var glow = new GlowEffectGraph())
                        {
                            glow.Setup(cl, temp.Radius);
                            session.DrawImage(glow.Blur);
                        }
                    }
                }
            }
        }

這個效果我放在 商業遊戲 可以玩一下,代碼開源https://github.com/lindexi/UWP/tree/master/uwp/src/VarietyHiggstGushed

參見:使用win2d實現螢火蟲粒子效果 - Nukepayload2 - 博客園

技術分享圖片
本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名林德熙(包含鏈接:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發布。如有任何疑問,請與我聯系。

win10 uwp 螢火蟲效果