パーティクルをやってみた

前々から気になっていたパーティクルをやってみました。
http://moeten.info/flex/20080619_particles73/bin-release/main.html

作ってて、いやー、すごい感動。
パーティクルなクラスはこちらからダウンロードできます。

Particle.asが本体
流れとしては、特定コンポーネントを描画してあげて

bmData = new BitmapData(screenW, screenH , true , 0x000000 );
bmData.draw(myImage);

for文で特定の色を見つけたらパーティクルを追加

if(col>0x000000){
    addSparkParticle(xpos, ypos, 1);
}

あとはパーティクルを描画更新

updateParticles();

サンプルもあるんだけど、どうもFlashでのサンプルなのでFlexで動かすにはちょっと手直しが必要です。基本的にはサンプルソースのthisの部分をCanvasとかImageにすればいいだけです。

makeParticle(Spark3, this, xpos, ypos)
↓
makeParticle(Spark3, myImage2, xpos, ypos)

こちらもクールなエフェクトを実行しています。

Flexなソースはこちら

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()" backgroundColor="0x000000" viewSourceURL="srcview/index.html">
<mx:Script>
<![CDATA[
[Embed(source='Spark3.swf')]
private var Spark3:Class
[Embed(source='Spark3.swf')]
private var Smoke:Class
private var particles:Array = new Array();
private var spareParticles:Dictionary = new Dictionary();
private var particle:Object;
private var scanX:Number =0;
private var screenW:Number = 550;
private var screenH:Number = 400;
private var bmData:BitmapData = new BitmapData(screenW, screenH,true,0x000000);
private var bm:Bitmap = new Bitmap(bmData);
//初期化関数
private function init():void{
    hts.send();
    onChange();
    myImage2.addChild(bm);
    this.addEventListener(Event.ENTER_FRAME, enterFrame);
}
//テキスト変更イベント
private function onChange():void{
    bmData = new BitmapData(screenW, screenH , true , 0x000000 );
    bmData.draw(myImage);
}
//ループ
private function enterFrame(e:Event):void{
    //パーティクルの更新
    updateParticles();
    scanX+=8;
    if(scanX>screenW){
        onChange();
        scanX = 0;
    }
    for(var ypos:Number = 0; ypos<screenH; ypos+=4){
        var xpos:Number = scanX-(ypos/4);
        if(xpos>0){
            var col:Number = bmData.getPixel(xpos, ypos);
            if(col>0x000000){
                addSparkParticle(xpos, ypos, 1);
                addSmokeParticle(xpos, ypos, 3);
                ypos+=10;
            }
        }
    }
}
private function addSparkParticle(xpos:Number, ypos:Number, particlecount:int):void{
    for(var i:int=0; i< particlecount; i++){
        // make a new particle
        particle = makeParticle(Spark3, myImage2, xpos, ypos)
        // give it a random velocity
        particle.setVel(randRange(-5,5),randRange(-5,5));
        // give it a random size
        particle.setScale(2); // randRange(1,2));
        particle.shrink = 0.8;
        //particle.gravity = 1;
        particle.drag = 0.98;
        //particle.directionRotate = true;
        //particle.updateRotation();
        // and add it to the particle array...
        particles.push(particle);
    }
}
private function addSmokeParticle(xpos:Number, ypos:Number, particlecount:int):void{
    for(var i:int=0; i< particlecount; i++){
        particle = makeParticle(Smoke, myImage2, xpos, ypos)
        // give it a random velocity
        particle.setVel(randRange(-0.25,0.25),-1);
        // give it a random size
        particle.clip.scaleX = particle.clip.scaleY = randRange(0.5,0.9);
        // make it transparent
        particle.clip.alpha = 0.3;
        particle.drag = 0.99;
        particle.fade = 0.95;
        particle.shrink = 1.03;
        particle.gravity = -0.07;
        // and add it to the particle array...
        particles.push(particle);
    }
}
private function updateParticles():void{
    var particle:Particle;
    // if there are more than 500 particles delete the first one in the array...
    while(particles.length>500){
        particle = particles.shift();
        particle.disable();
        if(!spareParticles[particle.spriteClass])
            spareParticles[particle.spriteClass] = new Array();
        spareParticles[particle.spriteClass].push(particle);
    }
    // go through the array of particles...
    for(var i:int = 0;i<particles.length;i++){
        //... and update each one
        particle = particles[i];
        particle.update();
        if(particle.clip.width<2) particle.disable();
    }
}
private function makeParticle(pclass:Class, target:Sprite, xpos:Number, ypos:Number):Object{
    if((spareParticles[pclass])    && (spareParticles[pclass].length>0)){
        particle = spareParticles[pclass].shift();
        particle.restart(xpos, ypos);
    }else{
        // make a new particle
        particle = new Particle(pclass, target, xpos, ypos);
    }
    return particle;
}
private function randRange(min:Number, max:Number):Number{
    var randomNum:Number = (Math.random() * (max - min )) + min;
    return randomNum;
}
private function onResult():void{
}
]]>
</mx:Script>
<mx:HTTPService id="hts" url="http://moeten.info/maidcafe/?type=shop&amp;tid=13&amp;cid=1&amp;m=api" resultFormat="e4x" result="onResult()"/>
<mx:Image id="myImage2" x="0" y="0" width="550" height="400"/>
<mx:Canvas id="myImage" x="0" y="0" width="550" height="400">
    <mx:TextArea change="{onChange()}" fontSize="30" borderStyle="solid" horizontalScrollPolicy="on"
        borderThickness="0" color="0xffffff" backgroundAlpha="0" x="10" y="10" width="307" height="39" text="haruhi&#xa;test&#xa;hogehoge&#xa;"/>
    <mx:Button x="325" y="57" label="ボタン"/>
    <mx:CheckBox x="325" y="83" label="チェックボックス" color="0xffffff"/>
    <mx:TileList x="10" y="57" width="310" height="210"  backgroundAlpha="0" dataProvider="{hts.lastResult.item}"
         columnCount="3"  columnWidth="90" rowCount="2" borderThickness="0" borderStyle="solid"
        >
        <mx:itemRenderer>
        <mx:Component>
            <mx:VBox verticalScrollPolicy="off" horizontalScrollPolicy="off">
                <mx:Image source="{data.image.image1}" width="50" height="80"/>
                <mx:Text text="{data.shopname}" color="0xffffff"/>
            </mx:VBox>
        </mx:Component>
        </mx:itemRenderer>
    </mx:TileList>
    <mx:Button x="325" y="57" label="ボタン"/>
    <mx:Label x="380" y="30" text="←変更できるよ" color="0xffffff"/>
    <!--<mx:TextArea id="myText" x="10" y="57" width="307" height="305" backgroundAlpha="0" color="0xffffff"/>-->
</mx:Canvas>
</mx:Application>