SilverlightでFlash的なパーティクル(サンプル)

| コメント(0) | トラックバック(0)
とりあえず見せれるものを作ってみた。


Microsoft Silverlight を取得


フレームレート 200でガンガン動く!
だいぶ前にAS3で書いて、wonderflに投稿したものを移植しただけなんだけど、
AS3のはフレームレート30です。
AS3のようにモーションをやるのには、
ちょっと書いててしっくりこない部分が多い感じがしました

コードは続きに載せてみます。
Canvas の位置を 設定 / 取得 するのに

//設定
Canvas.SetLeft(target, position);
Canvas.SetTop(target, position);
//取得
Canvas.GetLeft(target);
Canvas.GetTop(target);
という感じでCanvasクラスの staticメソッドで行う。

CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
は、画面表示が更新されたときに呼ばれるイベント。

_stage.Children.Add(target);
_stage.Children.Remove(target);
こうやって 表示オブジェクトのコレクションに入れてあげることで、AS3のaddChild,removeChild
でも深度管理は
Canvas.SetZIndex(target, depth);
で出来る。
これはどうやって管理してるのかなぁ、、

まぁ、全文は以下

using System;
using System.Windows;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Controls;

namespace SilverlightApplicationTest
{
    public class Main : Application
    {

        private int SW = 400;
        private int SH = 300;
        private const int FR = 200;
        private const int NUM = 50;
        private const int MIN_SIZE = 10;
        private const int MAX_SIZE = 20;
        private const double AMOUNT = 0.0002;

        private Canvas _stage;
        private FrameRate _fps;
        private TextBlock _fpsView;
        private Particle[] _particles;
        private Random _random = new Random();

        public Main()
        {
            this.Host.Settings.MaxFrameRate = FR;
            this.Startup += new StartupEventHandler(Main_Startup);
            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
        }

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            update();
        }

        private void Main_Startup(object sender, StartupEventArgs e)
        {
            init();
            createParticles();
            //_frameTimer.Start();
        }

        private void init()
        {
            _fps = new FrameRate();
            _stage = new Canvas();
            _fpsView = new TextBlock();
            _fpsView.Text = "";
            _stage.Children.Add(_fpsView);
            Canvas.SetZIndex(_fpsView, NUM);
            RootVisual = _stage;
        }

        private void createParticles()
        {
            _particles = new Particle[NUM];
            Particle p;
            for (int i = 0; i < NUM; i++)
            {
                int r = (int)_random.Next(MIN_SIZE, MAX_SIZE);
                int x = (int)_random.Next(SW);
                int y = (int)_random.Next(SH);
                p = new Particle(r);
                Canvas.SetLeft(p, x);
                Canvas.SetTop(p, y);
                _stage.Children.Add(p);
                _particles[i] = p;
            }
        }


        private void _frameTimer_Tick(object sender, EventArgs e)
        {
            update();
        }

        private void update()
        {
            double xi, xj, yi, yj, dx, dy, ax, ay, distSQ, dist;
            Particle pi, pj;
            for (int i = 0; i < NUM; i++)
            {
                pi = _particles[i];
                xi = Canvas.GetLeft(pi);
                yi = Canvas.GetTop(pi);
                for (int j = i + 1; j < NUM; j++)
                {
                    pj = _particles[j];
                    xj = Canvas.GetLeft(pj);
                    yj = Canvas.GetTop(pj);
                    dx = xj - xi;
                    dy = yj - yi;
                    distSQ = dx * dx + dy * dy;
                    dist = Math.Sqrt(distSQ);
                    if (dist < 100)
                    {
                        ax = dx * AMOUNT;
                        ay = dy * AMOUNT;
                        pi.update(ax, ay);
                        pj.update(-ax, -ay);
                    }

                }
                pi.updatePosition(SW, SH, xi, yi);
            }

            _fps.count();
            _fpsView.Text = "FPS : " + _fps.getFrameRate().ToString() + " / " + FR.ToString();
        }

    }


    public class Particle : Canvas
    {

        private int _size;

        private double _vx = 0;
        private double _vy = 0;

        public Particle(int size)
        {
            this._size = size;

            setup();
        }

        public void updatePosition(int sw, int sh, double x, double y)
        {
            x += _vx;
            y += _vy;
            x = border(x, sw);
            y = border(y, sh);
            Canvas.SetLeft(this, x);
            Canvas.SetTop(this, y);
        }


        public void update(double ax, double ay)
        {
            _vx += ax / _size;
            _vy += ay / _size;
        }

        private double border(double x, double b)
        {
            if (x < -_size)
            {
                x = b;
            }
            else if (x > b + _size)
            {
                x = 0;
            }

            return x;
        }


        private void setup()
        {
            SolidColorBrush brush = new SolidColorBrush();
            brush.Color = Color.FromArgb(0x44, 0x00, 0x66, 0xFF);

            int w = _size;
            int h = _size;

            Ellipse eL = new Ellipse();
            eL.Fill = brush;
            eL.Width = _size;
            eL.Height = _size;
            Canvas.SetLeft(eL, -_size / 2);
            Canvas.SetTop(eL, -_size / 2);
            this.Children.Add(eL);

            int s = (int)(_size * 0.5);
            w = s;
            h = s;

            Ellipse eS = new Ellipse();
            eS.Fill = brush;
            eS.Width = s;
            eS.Height = s;
            Canvas.SetLeft(eS, -s / 2);
            Canvas.SetTop(eS, -s / 2);
            this.Children.Add(eS);

        }
    }

    public class FrameRate
    {

        private long basetime;
        private int cnt;
        private float framerate;

        public FrameRate()
        {
            basetime = System.DateTime.Now.Ticks;
        }

        public float getFrameRate()
        {
            return framerate;
        }

        public void count()
        {
            cnt++;
            long now = System.DateTime.Now.Ticks;
            if (now - basetime >= 10000000)
            {
                framerate = (float)(cnt * 10000000) / (float)(now - basetime);
                basetime = now;
                cnt = 0;
            }
        }
    }

}

トラックバック(0)

トラックバックURL: http://blog.sph62.net/admin/mt-tb.cgi/25

コメントする