win10 uwp 萤火虫效果

原文: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 ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

原文地址:https://www.cnblogs.com/lonelyxmas/p/8521889.html

时间: 2024-10-07 23:35:22

win10 uwp 萤火虫效果的相关文章

Win10 UWP开发系列:使用VS2015 Update2+ionic开发第一个Cordova App

安装VS2015 Update2的过程是非常曲折的.还好经过不懈的努力,终于折腾成功了. 如果开发Cordova项目的话,推荐大家用一下ionic这个框架,效果还不错.对于Cordova.PhoneGap.ionic.AngularJS这些框架或库的关系,我个人理解是这样,PhoneGap是一个商业项目,用来实现HTML5式的跨平台开发,后来Adobe公司将其中的核心代码开源,就是Cordova,Cordova只负责实现JavaScript调用原生代码的功能,是一个壳,而壳里具体用什么样式,在H

Win10 UWP开发系列:实现Master/Detail布局

在开发XX新闻的过程中,UI部分使用了Master/Detail(大纲/细节)布局样式.Win10系统中的邮件App就是这种样式,左侧一个列表,右侧是详情页面.关于这种 样式的说明可参看MSDN文档:https://msdn.microsoft.com/zh-cn/library/windows/apps/xaml/dn997765.aspx 样式如下: 在微软官方的Sample里,有这种样式的代码示例,下载地址:https://github.com/Microsoft/Windows-univ

Win10 UWP系列:更新UWP时注意的问题——TargetDeviceFamily

原文:Win10 UWP系列:更新UWP时注意的问题--TargetDeviceFamily 前几天把CurrencyExchanger提交到微软参加Master认证,结果没有通过,反馈了一些错误,看来微软检查还是比较仔细的. 错误主要有: Visual feedback helps users recognize whether their interactions with your application are detected, interpreted, and handled as

【Win10 UWP】后台任务与动态磁贴

动态磁贴(Live Tile)是WP系统的大亮点之一,一直以来受到广大用户的喜爱.这一讲主要研究如何在UWP应用里通过后台任务添加和使用动态磁贴功能. 从WP7到Win8,再到Win10 UWP,磁贴模板不断进行调整和优化,目前磁贴模板已经发展到第三代,一般称之为“Adaptive Tile Templates”. 在运用UWP动态磁贴之前,请先了解一下自适应磁贴的语法规则.关于自适应磁贴模板的语法规则,请详读这篇文章:http://blogs.msdn.com/b/tiles_and_toas

win10 uwp 渲染原理 DirectComposition 渲染

本文来告诉大家一个新的技术DirectComposition,在 win7 之后(实际上是 vista),微软正在考虑一个新的渲染机制 在 Windows Vista 就引入了一个服务,桌面窗口管理器Desktop Window Manager,虽然从借助 C++ 进行 Windows 开发博客可以看到 DWM 不是一个好的方法,但是比之前好. 在 win8 的时候,微软提出了 DirectComposition ,这是一个新的方法. 在软件的渲染一直都是两个阵营,一个是使用直接渲染模式.直接渲

win10 uwp 线程池

原文:win10 uwp 线程池 如果大家有开发 WPF 或以前的程序,大概知道线程池不是 UWP 创造的,实际上在很多技术都用到线程池. 为什么需要线程池,他是什么?如何在 UWP 使用线程池,本文就是来告诉大家这些 目录 为什么需要线程池 什么是线程池 线程池原理 应用 等待代码完成 定时器 为什么需要线程池 在程序中,创建和销毁线程是需要很多资源的,如果只是为了完成很小的代码而创建一个新的线程,创建线程占用的时间在总的运行时间占有比例很大.所以大神就说,那就不创建线程了. 因为花费总时间划

Win10 UWP系列:关于错误 0x80073CF9及一个小bug的解决

原文:Win10 UWP系列:关于错误 0x80073CF9及一个小bug的解决 最近一直在开发XX的uwp版本,也是边摸索边做,最近遇到几个比较奇怪的问题,记录于此. 1.项目可用部署到PC,但无法部署到手机,提示以下错误: 错误 : DEP0001 : 意外错误: Install failed. Please contact your software vendor. (Exception from HRESULT: 0x80073CF9 为了方便开发,我将常用的类库引用好.默认的几个页面做

Win10 UWP开发系列:解决Win10不同版本的Style差异导致的兼容性问题

原文:Win10 UWP开发系列:解决Win10不同版本的Style差异导致的兼容性问题 最近在开发一个项目时,遇到了一个奇怪的问题,项目依赖的最低版本是10586,目标版本是14393,开发完毕发布到商店后,很多用户报无法正常加载页面.经查,有问题的都是Win10 10586版本. 我上篇博客中写到的自定义的AppBar控件,也存在这个问题,10586会报错. 为此特意下载了10586的SDK调试.错误显示,一个样式找不到,名为ListViewItemBackground.因为开发的时候是基于

Win10 UWP开发系列——开源控件库:UWPCommunityToolkit

原文:Win10 UWP开发系列--开源控件库:UWPCommunityToolkit 在开发应用的过程中,不可避免的会使用第三方类库.之前用过一个WinRTXamlToolkit.UWP,现在微软官方发布了一个新的开源控件库—— UWPCommunityToolkit 项目代码托管在Github上:https://github.com/Microsoft/UWPCommunityToolkit 包括以下几个类库: 都可以很方便的从Nuget上安装. NuGet Package Name des