zoukankan      html  css  js  c++  java
  • Silverlight C# 游戏开发:绚丽的粒子特效颜色粒子(一)

    在游戏中,有各种各样特效,其中有一种特效是通过计算随机产生,而不是一张又一张的图片更换,通过模拟现实中的粒子物理规律得到有趣真实的效果,这种叫作粒子特效,它能大量的降低资源大小,咱们一起实现一个简单的跟随鼠标的粒子特效。
    flash中我不清楚是否好做,但是在Silverlight中实现粒子特效非常容易,今天咱们一起来做一个简单的粒子特效。
    现在需要将基本的粒子创建出来,先分析粒子最基本的运动方式和规律,粒子具备衰减的特性,然后就是移动行为,为了让运动不具备规律还要加入例如XY轴随机向量和重力,具体分析请看下图。
    依据上面的分析建立全局参数,为了让粒子效果看起来更加真实和不确定,这些包含了随机、透明度、粒子数、大小范围等等,请参看下面的代码:
    public class GlobalValue
    {
        
    /// <summary>
        
    /// 全局随机函数,从时间取得种子,保证每次都不一样
        
    /// </summary>
        public static Random random = new Random((int)DateTime.Now.Ticks);
        
    /// <summary>
        
    /// 起始透明度
        
    /// </summary>
        public const double OPACITY = 1;
        
    /// <summary>
        
    /// 每次添加多少个粒子
        
    /// </summary>
        public const double FIREWORK_NUM = 2;
        
    /// <summary>
        
    /// 重力
        
    /// </summary>
        public const double GRAVITY = 0.1;
        
    /// <summary>
        
    /// 偏移X
        
    /// </summary>
        public const double X_VELOCITY = 5;
        
    /// <summary>
        
    /// 偏移Y
        
    /// </summary>
        public const double Y_VELOCITY = 5;
        
    /// <summary>
        
    /// 最小的半径
        
    /// </summary>
        public const int SIZE_MIN = 1;
        
    /// <summary>
        
    /// 最大的半径
        
    /// </summary>
        public const int SIZE_MAX = 10;
        
    /// <summary>
        
    /// 透明度衰减值
        
    /// </summary>
        public const double OpacityInc = -0.02;
    }

    然后建立基本粒子,我这里偷懒了,简单的写了一个DOT类:

        public class Dot: Canvas
        {       
            
    public double XVelocity = 1;
            
    public double YVelocity = 1;
            
    public double Gravity = 1;

            
    public Dot(byte red, byte green, byte blue, double size)
            {           
                
    double opac = GlobalValue.OPACITY;
                size 
    = GlobalValue.random.Next(GlobalValue.SIZE_MIN,GlobalValue.SIZE_MAX);
                
    //生成圆圈粒子
                {
                    Ellipse ellipse 
    = new Ellipse();
                    ellipse.Width 
    = size;
                    ellipse.Height 
    = size;                
                    ellipse.Fill 
    = new SolidColorBrush(Color.FromArgb(255, red, green, blue));
                    ellipse.Opacity 
    = opac;                
                    ellipse.SetValue(Canvas.LeftProperty, 
    -ellipse.Width / 2);
                    ellipse.SetValue(Canvas.TopProperty, 
    -ellipse.Height / 2);
                    
    this.Children.Add(ellipse);
                }
            }
            
    public void RunFirework()
            {
                X 
    = X + XVelocity;
                Y 
    = Y + YVelocity;
                
    this.Opacity += GlobalValue.OpacityInc;
                YVelocity 
    += Gravity;            
            }
            
    //制作一个绑定属性
            public double X
            {
                
    get { return (double)(GetValue(Canvas.LeftProperty)); }
                
    set { SetValue(Canvas.LeftProperty, value); }
            }
            
    public double Y
            {
                
    get { return (double)(GetValue(Canvas.TopProperty)); }
                
    set { SetValue(Canvas.TopProperty, value); }
            }
        }

    DOTCanvas继承,它只是一个非常简单的点,然后依照颜色生成,那么现在将点放入到一个循环体中,制作相关的逻辑,我们这次一次使用了游戏循环方式中的链条式循环,基础理论请参看这里:http://www.cnblogs.com/nowpaper/archive/2010/05/16/1736950.html

    建立一个Colorful类也是从Canvas上继承下来,它就是所有粒子的容器。

    public class Colorful : Canvas
    {
        
    private List<Dot> _dotGroup = new List<Dot>();
        
        
    private DispatcherTimer _timer;
        
    private static int IntervalTime = 20;   
        
    public Colorful()
        {
            
    this.Background = new SolidColorBrush(Colors.Gray);      
            List
    <Object> array = new List<Object>();
            Object abc 
    = new Object();
            Start();
        }
        
    void loop_timer_Tick(object sender, EventArgs e)
        {
            moveDots();
        }

        
    void moveDots()
        {
            
    for (int i = _dotGroup.Count - 1; i >= 0; i--)
            {
                Dot dot 
    = _dotGroup[i];
                dot.RunFirework();
                
    if (dot.Opacity <= 0.1)
                {
                    
    this.Children.Remove(dot);
                    _dotGroup.Remove(dot);
                }
            }
        }
        
        
    public virtual void addDotToGroup(double x, double y)
        {
            
    int seed = (int)DateTime.Now.Ticks;

            
    for (int i = 0; i < GlobalValue.FIREWORK_NUM; i++)
            {
                
    double size = GlobalValue.SIZE_MIN + (GlobalValue.SIZE_MAX - GlobalValue.SIZE_MIN) * GlobalValue.random.NextDouble();
                
    byte red = (byte)(128 + (128 * GlobalValue.random.NextDouble()));
                
    byte green = (byte)(128 + (128 * GlobalValue.random.NextDouble()));
                
    byte blue = (byte)(128 + (128 * GlobalValue.random.NextDouble()));

                
    double xVelocity = GlobalValue.X_VELOCITY - 2 * GlobalValue.X_VELOCITY * GlobalValue.random.NextDouble();
                
    double yVelocity = -GlobalValue.Y_VELOCITY * GlobalValue.random.NextDouble();
                Dot dot 
    = new Dot(red, green, blue, size);
                dot.X 
    = x;
                dot.Y 
    = y;
                dot.XVelocity 
    = xVelocity;
                dot.YVelocity 
    = yVelocity;
                dot.Gravity 
    = GlobalValue.GRAVITY;
                dot.RunFirework();
                _dotGroup.Add(dot);

                
    this.Children.Add(dot);
            }
        }
        
    public virtual void Start()
        {
            _timer 
    = new DispatcherTimer();

            _timer.Interval 
    = TimeSpan.FromMilliseconds(IntervalTime);
            _timer.Tick 
    += new EventHandler(loop_timer_Tick);
            _timer.Start();
        }
    }

    这是一个只有执行逻辑的容器,addDot用来增加粒子,moveDots是移动粒子并且检测是否消失,如果消失则从List和父结构中移除掉。

    生成逻辑通过面向对象的方式实现,建立一个Colorful_FollowMouse类:
    public class Colorful_FollowMouse : Colorful
    {
        
    public Colorful_FollowMouse()
        {
            MouseMove 
    += new MouseEventHandler(Colorful_FollowMouse_MouseMove);
        }
        
    void Colorful_FollowMouse_MouseMove(object sender, MouseEventArgs e)
        {
            addDotToGroup(e.GetPosition(
    this).X, e.GetPosition(this).Y);
        }
    }

    添加到MainPageLayoutRoot.Children.Add(new Colorful_ FollowMouse ());

    运行看看效果吧:)鼠标滑动一下看看

    我在工程中加入了一个Colorful_ClickMouse类,是通过点击产生粒子的操作效果,可以更换看看点击的感觉如何:)

    对于一个游戏而言,如果粒子系统作的好,能够为游戏增加很多视觉乐趣,就如今天的颜色点特效,能够应用到很多程序当中,并不只是游戏,而且这个类一旦写好,就可以作为通用的方法为其他开发所用上,这个颜色点很有趣吧,以后后面咱们逐步实现更佳“绚丽”的特效,例如火焰、爆炸等等:)
  • 相关阅读:
    Redis系列(三)-Redis replication 实现主从复制(读写分离)
    Redis系列(二)-Redis的RDB和AOF两种持久化机制
    Redis系列(一)-CentOS7下Redis单机安装+自启动
    vmware安装centos 7,没有ifconfig命令,无法访问网络
    本博客停更
    「杂文」昨日之纯真,明日之坚毅
    OkHttpClient跳过证书验证
    java 获取十个工作日之前或之后的日期(算当天)
    java pdfBox给PDF添加图片水印
    docker pull 提示timeout
  • 原文地址:https://www.cnblogs.com/nowpaper/p/1741479.html
Copyright © 2011-2022 走看看