2008.04.02
category
comments

パーティクルクラスを作ってみた

勉強用に自作で作ってみたので公開してみる。4月なので桜の花びらをパーティクルで散らしてみた。使い方はドキュメントクラスに下記のように記述する。

Main.as

ACTIONSCRIPT:
package
{
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import info.five.filters.Particle;
   
    public class Main extends Sprite
    {
        private var p:Particle;
       
        //------------------------------
        //   コンストラクタ
        //------------------------------
        public function Main():void
        {
            this.stage.addEventListener(MouseEvent.CLICK, onClick);
           
            //-----[パーティクル]
            p = new Particle("flower", this);
            p.gravity = -0.2;
            p.wind = -0.5;
        }
       
        private function onClick(e:MouseEvent):void
        {
            p.click();
        }
    }
}

まずはパーティクルインスタンスを作る。第1引数はパーティクルの元となるムービークリップのリンケージ名。第2引数はパーティクルを配置する場所。この場合はステージに配置するのでthisとする。インスタンスを作った後は各パラメータを指定する。gravityはマイナス値でパーティクルが上昇。windはマイナス値で左向きにパーティクルが流れる(0だと円状に広がる)。

p.gravity = -0.2;
p.wind = -0.5;

このサンプルではステージにクリックイベントを登録しているので、リスナー関数の中でp.click()を呼び出すことでクリックタイプのパーティクルを発動することができる。これをp.start()にするとパーティクルが生成され続ける。p.stop()で止める事ができる。

パーティクルクラスはこちら
Particle.as

ACTIONSCRIPT:
package info.five.filters
{
    import flash.display.DisplayObjectContainer;
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.TimerEvent;
    import flash.utils.Timer;
    import flash.utils.getDefinitionByName;
    import flash.geom.Point;
   
    public class Particle
    {
        private var container:DisplayObjectContainer;
        private var linkage:String;
        private var timer:Timer;
        private var xVel:Number;
        private var yVel:Number;
        private var _vol:Number = 5;
        private var _drag:Number = 0.99;
        private var _shrink:Number = 0.95;
        private var _gravity:Number = 0.8;
        private var _fade:Number = 0.02;
        private var _wind:Number = 0;
       
       
       
        //------------------------------
        //   コンストラクタ
        //------------------------------
        public function Particle(s:String, targetContainer:DisplayObjectContainer)
        {
            linkage = s;
            container = targetContainer;
        }
       
       
        //------------------------------
        //   パーティクルの生成
        //------------------------------
        private function makeParticle(e:Event):void
        {
            for (var i:uint = 0; i <_vol; i++)
            {
                var mc:MovieClip = new(getDefinitionByName(linkage));
                container.addChild(mc);
               
                var mouseX:int = container.stage.mouseX;
                var mouseY:int = container.stage.mouseY;
                var mousePt:Point = new Point(mouseX, mouseY);
                var pt:Point = getNearPoint(mousePt);
               
                mc.x = pt.x;
                mc.y = pt.y;
                mc.xVel = getRandRange( -5, 5);
                mc.yVel = getRandRange( -5, 5);
                mc.rot = getRandRange( -20, 20);
               
                mc.addEventListener(Event.ENTER_FRAME, onRender);
            }
        }
       
       
        //------------------------------
        //   指定範囲からランダム値の取得
        //------------------------------
        private function getRandRange(min:Number, max:Number):Number
        {
            var randomNum:Number = (Math.random() * (max - min )) + min;
            return randomNum;
        }
       
       
        //------------------------------
        //   近似ポイント座標の取得
        //------------------------------
        private function getNearPoint(pt1:Point):Point
        {
            var len:uint = Math.round(Math.random() * 10);
            var angle:uint = Math.round(Math.random() * 2 * Math.PI);
            var pt2:Point = Point.polar(len, angle);
           
            pt2.offset(pt1.x, pt1.y);
            return pt2;
        }
       
       
        //------------------------------
        //   スタート
        //------------------------------
        public function start():void
        {
            container.stage.addEventListener(Event.ENTER_FRAME, makeParticle);
        }
       
       
        //------------------------------
        //   ストップ
        //------------------------------
        public function stop():void
        {
            container.stage.removeEventListener(Event.ENTER_FRAME, makeParticle);
        }
       
       
        //------------------------------
        //   クリック
        //------------------------------
        public function click():void
        {
            container.stage.addEventListener(Event.ENTER_FRAME, makeParticle);
           
            timer = new Timer(300, 1);
            timer.addEventListener(TimerEvent.TIMER, onDelay);
            timer.start();
        }
       
        private function onDelay(e:TimerEvent):void
        {
            container.stage.removeEventListener(Event.ENTER_FRAME, makeParticle);
            timer.removeEventListener(TimerEvent.TIMER_COMPLETE, onDelay);
        }
       
       
        //------------------------------
        //   レンダー
        //------------------------------
        private function onRender(e:Event):void
        {
            var mc:MovieClip = e.target as MovieClip;
           
            if (mc.alpha> 0)
            {
                mc.x += mc.xVel + _wind * 10;
                mc.y += mc.yVel;
               
                mc.xVel *= _drag;
                mc.yVel *= _drag;
               
                mc.scaleX *= _shrink;
                mc.scaleY *= _shrink;
               
                mc.yVel += _gravity;
                mc.alpha -= _fade;
                mc.rotation += mc.rot;
            }
            else
            {
                mc.removeEventListener(Event.ENTER_FRAME, onRender);
                mc.removeChildAt(0);
                container.removeChild(mc);
                mc = null;
            }
        }
       
       
        //------------------------------
        //   getter setter
        //------------------------------
        public function get vol():Number { return _vol; }
       
        public function set vol(value:Number):void {
            _vol = value;
        }
       
        public function get drag():Number { return _drag; }
       
        public function set drag(value:Number):void {
            _drag = value;
        }
       
        public function get shrink():Number { return _shrink; }
       
        public function set shrink(value:Number):void {
            _shrink = value;
        }
       
        public function get gravity():Number { return _gravity; }
       
        public function set gravity(value:Number):void {
            _gravity = value;
        }
       
        public function get fade():Number { return _fade; }
       
        public function set fade(value:Number):void {
            _fade = value;
        }
       
        public function get wind():Number { return _wind; }
       
        public function set wind(value:Number):void {
            _wind = value;
        }
    }
}

不具合があれば、指摘していただけると嬉しいです。

13 Comments

  1. Adrien Says

    I’m starting AS3 and i would like to thank you for the tips on targetContainer’
    That’s strange that the stage can’t be call from every where…

  2. simo Says

    >Adrien
    I’m studying AS3 too.I think it is difficult until becoming accustomed.

    In the another way, after the MovieClip is done in addChild, the reference to the stage can be acquired from MovieClip’s property.

  3. Adrien Says

    interesting point…
    So let’s do that in all AS3 project’

    var stageContainer:MovieClip = new MovieClip();
    addChild(stageContainer);
    var _stage:Stage = stageContainer.stage;
    trace(_stage.stageWidth , _stage.stageHeight);

    Thank you for your help work Simo*

  4. simo Says

    >Adrien
    You’re welcome. It was good to have your help!

  5. dasign Says

    こんにちは。
    このパーティクル、おもしろいなと思って試していて発見です。

    レンダーの if (mc.alpha> 0)
    →>は >
    パーティクルの生成の for (var i:uint = 0; i <_vol; i++)
    →<は <

    ですよね。

  6. dasign Says

    あら、同じになってしまった…
    該当箇所見ていただければ、どういうことか分かりますので
    見てみて下さい!

  7. simo Says

    はじめまして。コメントありがとうございます!

    んーと、仰っている意味がよく分かりませんで申し訳ないです。不等号の向きが逆ではないかという事でしょうか?お手数ですが詳しく教えていただけますか?

  8. dasign Says

    説明不足ですみません><
    本当は不等号が表示されるところに、実体参照が表示されてしまってたのです。今見たら直ってました!
    僕のブラウザの問題だったら穴に潜りたい…

  9. simo Says

    なるほど、そういう事だったんですね。実体参照はwordPress側で変換してくれるはずなので、もしかしたらブラウザで表示するときに何かの拍子に参照されずそのままレンダリングされていたのかもしれません・・・。

    また表示がおかしくなってたら、連絡してもらえるとありがたいです。今後ともよろしくお願いしますね!

  10. dasign Says

    そんなことがあるんですねー。
    僕も偉そうですがこの件で実体参照って言葉覚えましたw
    日々勉強ですね
    もちろんですとも。こちらこそよろしくおねがいしますー!

  11. [作ったよ][Flash][AS3]スターパーティクルクラス作ったよ

    5ive.blogのsimoさんがAS3で面白いパーティクルを作っておられて、 俺個人的にはこうしたい!ってとこがあったので改造してみたよ。 イメージ capsule の新曲 JUMPER のPVのキラキラ星 やったこ…

  12. dasign Says

    勝手に僕好みに改造してしまいました、すいません><
    http://d.hatena.ne.jp/dasign/20081128

  13. simo Says

    見ましたよー。パラメータとか色々細かく調整していくと気持ち良い動きになりますよね。がんがん弄ってもらって発展させて下さい!今後の展開も楽しみにしていますので。w

Post a comment




Comment

Trackbacks

この記事のコメント・トラックバックRSS