BitmapDataを使ったParticle Systemの実装

前からずっと気になっていたParticle Systemの実装方式について調べました。

調査を進めてみると、SpriteをわずBitmapDataを使って描画をするという選択肢もあるということが分かり新鮮でした。
ということで、今回はBitmapDataを使ったParticleSystemの実装を解説します。

そもそもParticle Systemは、粒子(particle)の動きをシミュレーションし粒子の状態に基づいて画面描画するという動作を繰り返します。

この「動きのシミュレーション」と「画面描画」を分けるのが非常に重要で、調査前の私の理解ではこの境界が曖昧でした。

Spriteを使って描画するParticle Systemの実装は、たまに見かけるのであえて私はあえてBitmapDataに直接書き込む方式で実装してみました。
実装するにあたって、aM laboratoryのparticlesを参考にしました。というか、ほぼそのままです。

描画方法:setPixel() + BlurFilter

BitmapData上にあるParticleの位置にsetPixel()で点を描画し、BlurFilterを適用する方法です。
この方法はとても単純だけど、色々と使い勝手がありそうです。

コードは、以下のようになります。

var buffer:BitmapData = new BitmapData(WIDTH, HEIGHT, false, 0);
var blur:BlurFilter = new BulrFilter(2,2,1);
(中略)
buffer.setPixcel(particle.x, particle.y, particle.color);
buffer.applyFilter(buffer, buffer.rect, ORIGIN, blur);

この方法を使ったサンプルは、次の通りです。

画面中央下からParticleが沸き出してきます。沸き出した際に初速度をランダムで与え、以降はy軸方向を等速、x軸方向をバネの動きにしています。
以上の設定だと画面中央付近のParticleの密度が高くなり炎っぽく見えます。

描画方法:setPixel()のみ

次は単純にsetPixel()のみで描画したサンプルです。

Particleが動き始めた後に外力を加えてないのでParticleの生存時間を記録していれば、逆再生でもとの状態に戻すことができます。
このサンプルでは、逆再生する際に2ステップずつ戻すことで倍速を実現しています。

for ( i = 0; i < particles.length; i++ ) {
   p = particles[i];
   if ( p.lifetime > 0 ) {
       if ( p.lifetime % 2 != 0 ) {
           p.x -= p.vx;
           p.y -= p.vy;
           p.lifetime -= 1;
       }
       else {
           p.x -= p.vx * 2;
           p.y -= p.vy * 2;
           p.lifetime -= 2;
       }
   }
   output.setPixel(p.x, p.y, p.color);
}

ソースコード

ここからダウンロードできます。

(おまけ)Particle Systemとは?

そもそもParticle Systemの定義ってなんなのかいまいちピンと来なかったので、Particleの原著(?)に当たってみました。
原著によると、Particleは、

  • 位置
  • 速度
  • サイズ
  • 色(アルファ含む)
  • 生存時間

の属性を持ち、時間とともにその状態を変化させます。

作成するParticleが必ずしもすべての属性を持たなければならないという訳ではないですが、上記に上げた項目はよく使われます。