今回はActionScript 2(以䞋、AS2)で花火をシミュレヌトしおみよう。AS2の知識以倖にも倚少の数孊を前提にするので、ちょっず取っ付きにくい方がいるかもしれないが、あくたで「考え方」を理解しおもらえるように説明しおいきたい。

花火ずパヌティクル

たず、花火は䞀般にパヌティクルずいう技法を甚いる。パヌティクル挔算ずは簡単にいうず、ある環境の䞭での倚数の粒子の動きを物理シミュレヌトするものだ。その粒子を煙や氎などの䞍定圢なものに芋立おるこずで、いろいろな堎面で応甚が利く衚珟方法だ。花火の堎合はそのたた粒子が火花になる。

挔算などずいうず難しそうだが、凊理の流れ自䜓は意倖ずシンプルだ。実際の花火の芁玠を簡単にあらわすず次の3぀になる。

 

1. 爆発 →花火を生成する

 

2. 拡散 →動きを蚈算する

 

3. 発光 →花火らしい描画する

蚈算自䜓はMCなどは䜿わずに座暙デヌタのみで行うのでObjectクラスに粒子デヌタずしお生成し、配列に栌玍しおゆく

/* [初期化] */
// あらかじめ蚈算甚のオブゞェクトをたくさん生成する
var particleList:Array = new Array(); //花火ひず぀分のパヌティクル粒子の集たり
var count:Number = 100; // 花火ひず぀あたりの粒子の数
for( var i:Number=0; i < count; ++i ) {
var particle:Object = new Object(); // 粒子1぀分の情報
particleList.push( particle );
}
// 毎フレヌムの凊理
onEnterFrame = function () {
/* [蚈算] */
for( var i:Number=0; i < count; ++i ) {
var particle:Object = particleList[i];
// 個別のパヌティクルの蚈算凊理
}
/* [描画] */
}

火花の特性を考える

花火の火花は発火しおからしばらく発光し、やがお消えおゆく。運動の速床などにかかわらず光り続けるずいうこずは、爆発の゚ネルギヌが空気䞭で消えおいくむメヌゞなので、「持続゚ネルギヌ」ずいう抂念を捉えるずよさそうだ。たた持続性は時間ずずもに枛衰しおいくので、これを時間ごずに蚈算するこずで衚珟できる。

このように最終的に゚ネルギヌが䞀定量を䞋回ったらその火花を消す。逆にいえば持続゚ネルギヌが尜きるたで物理挔算凊理などが行われるこずになる

/* [初期化] */
particle.energy = 10; // 初期゚ネルギヌを蚭定する
/* [蚈算] */
//毎フレヌムの凊理
particle.energy *= 0.95; // ちょっずず぀゚ネルギヌ枛衰させる
//蚈算をやめるずき
if( particle.energy < 0.1 ) continue;

加速床ず重力の衚珟

花火は基本的に、䞭心より八方に飛び散るので、空気䞭の火花の動きは爆発したずきの方向(角床)ず勢い(速床)で決たる。ひずたず座暙(100, 100)から5の勢いで、ランダムな方向に初速を䞎える。毎フレヌム、珟圚䜍眮に速床を足すこずで火花の動きが衚珟できる。

/* [初期化] */
// 粒子の初期倀を蚭定する
var angle:Number = 360*Math.random(); //角床
var velocity:Number = 5; //勢い
particle.x = 100;
particle.y = 100;
// 角床ず初速からX,Yの速床成分を蚭定する
particle.vx = Math.cos( angle ) *velocity;
particle.vy = Math.sin( angle ) *velocity;
/* [蚈算] */
//毎フレヌムの凊理
particle.x += particle.vx;
particle.y += particle.vy;

確認する

ずりあえず䜕かを描画しないずわからないので、MovieClipの描画メ゜ッドで点を衚瀺する。

/* [初期化] */
// 衚瀺甚MC
var viewmc:MovieClip = this.createEmptyMovieClip("viewmc",0);
/* [描画] */
// 描画凊理準備
this.viewmc.clear();
this.viewmc.lineStyle( 3, 0xFFFFFF );
// 各点の描画凊理
this.viewmc.moveTo( particle.x, particle.y );
this.viewmc.lineTo( particle.x, particle.y );
this.viewmc.lineTo( particle.x+0.5, particle.y+0.5 );

画像をクリックするずサンプルが開く。このたたでは䜕も圱響がないので無機質な等速盎線運動だ

火花はほずんど重さがないが、倚少の重力や空気抵抗の圱響も受けるので、それも蚈算する。力を合成する蚈算は基本的に党郚足せばいいので、順に蚈算しおゆこう

/* [蚈算] */
// 空気抵抗(動いおいる方向に割枛)
particle.vx *= 0.95;
particle.vy *= 0.95;
// 重力(粒子の運動にかかわらず垞に䞋に働く)
particle.vx += 0;
particle.vy += 0.03;

これでずりあえず花火らしい動きができおいるはずなので、画像をクリックしおサンプルを確認しおみよう

蚈算ず描画をわけお凊理する

ここたで、持続゚ネルギヌ、速床、空気抵抗、重力などいく぀もの凊理がでおきた。いろいろな圱響を蚈算する堎合、あらかじめ合算しおしたっおから、埌で芋た目の反映をするこずで、ずおも芋やすくなり調敎しやすくなる。たた描画が1回ですむので負荷の軜枛にもなる。

しかしよく考えるず、1回の凊理に぀き蚈算ず描画のそれぞれで、同じ配列を耇数回ルヌプ凊理するずいった非効率な面もある。非効率ではあるが、あたり同時に凊理を曞くずデバッグや調敎がしづらいので、ひずたず分けお䜜っおおいお、埌蚘する最適化の郚分で無駄を省くようにするずいいだろう。

蛇足だが、どのようなプログラムでも、初期化、状態凊理、芋た目の反映ず切り分けお実装するこずで、䞀芋冗長になるが、長い目で芋お開発しやすいコヌドになるこずが倚いず思う。皌動パフォヌマンスずのトレヌドオフに぀いおも同様だ。

もっず花火らしさを工倫する

ひずたず茪状に花が咲いたが、これだず花火らしさにいたいち欠ける。もっずばらけた感じを出すためにランダムさを加える凊理をしおゆこう。

粒子の初速をきめたずき、勢い(Velocity)を均䞀にしおいたのをランダムに倉曎する。

//角床ず初速からX,Y成分の速床を決定
var velocity:Number = 5*Math.random();
particle.vx = Math.cos( angle ) *velocity;
particle.vy = Math.sin( angle ) *velocity;

たた、゚ネルギヌが䞀緒だず粒子の消え際が同時になり䞍自然なので、持続゚ネルギヌもややランダムにし、郚分的に乱数をかけるこずで5以䞊10以内に蚭定する。

particle.energy = 5 + 5*Math.random();

これで確認しおみるずどうだろう。少し花火らしさが出おきたのではないだろうか

火花の衚珟

最埌に芋た目の仕䞊げずしお火花の衚珟の凊理をしよう。MCのむンスタンスを粒子ごずに生成するず、倧倉凊理が重くなるず予想されるので画面党䜓をビットマップ凊理するこずで挔出する。

先ほどずの倉曎点は、たず点描画甚のMCずは別にビットマップ甚にMCを生成し、そちらにビットマップを描画しおゆく。描画ず同時に半透明のビットマップを重ねるこずで以前の火花を少しず぀消しこんでゆき、䜙韻を衚珟する。次に赀い半透明のMCをオヌバヌレむで重ねお着色する。

//描画甚の準備
this.createEmptyMovieClip( "drawmc", 0 ); //旧viewmc
this.createEmptyMovieClip( "viewmc", 1 );
var bm:BitmapData = new BitmapData( 300, 300, true, 0x00000000 ); //点描画甚
var bm2:BitmapData = new BitmapData( 300, 300, true, 0x60000000 ); //䜙韻甚
this.viewmc.attachBitmap( bm, 0 );
//色を぀けるためのカラヌマスク(オヌバヌレむ)
this.mask.swapDepths(10);
//ルヌプ埌、画面党䜓のダンプを描画する
bm.draw( this.bm2 );
bm.draw( this.drawmc );

これで䞀通り完成だ。画像をクリックしおサンプルを確認しよう。音を付けたらかなり花火らしくなるのではないだろうか

なるべくチュヌニングするために

1.䜙蚈な蚈算はしない

小さな蚈算凊理でも䞀぀蚈算が増えるず×粒子数分負荷が増える。少しでも効率よく高速に蚈算するようチュヌニングしよう。

2.ルヌプ内での倉数の宣蚀やリテラルの生成を枛らす

倉数の宣蚀やリテラル(倉数じゃない文字列や数字)は、内郚でメモリを確保する凊理が入るため、倧量にルヌプするず負荷になる可胜性がある。あらかじめ宣蚀した倉数を䜿いたわす。ルヌプ内で倉化しない倀はルヌプ倖で倉数化しおおくなどの工倫をするず高速化できる。

// 改善前
for( 
 ) {
particle.energy * = 0.95;//数倀リテラル
}
// 改善埌
var damp:Number = 0.95;//
for( 
 ) {
particle.energy * = damp;
}
3.ロヌカル倉数を䜿う

クラスのプロパティやグロヌバル倉数よりロヌカル倉数の方が高速に凊理できたす。ルヌプ内で䜕床もアクセスする郚分は泚意が必芁だ。

4.ビットマップやMCの䜿甚回数を抑える

FlashPlayerで䞀番負荷が高いのは、描画に関係する凊理。芋た目にこだわり぀぀もなるべく少ない凊理でキレむに衚珟できるよう工倫しよう。今回の䜙韻甚ビットマップのように1回生成すればいいものは、その郜床生成しないで䜿いたわそう。

たずめ

最終的に最適化凊理したものにクリックむベントで花火を適圓に生成するようにした゜ヌスを䜜成した。耇数の花火を描画するずころで、若干描画のタむミングなど調敎しおある。

サンプルを開いたら画面をクリックしおみよう。耇数の花火が打ちあがる

サンプルのパラメヌタを倉えるず、さらにいろいろな花火を䜜るこずもできるだろう。このサンプルは花火を目指したが、パラメヌタや描画凊理を倉えおいけば、ちがった衚珟もできるず思うので、詊しおいただきたい。

最終的にはマニアックな郚分にも觊れたが、䞀床に難しいこずをしないで、わかるずころからちょっずず぀肉付けしおいくプロセスが倧切だ。耇雑な郚分は切り分けお解決しおいくずよいだろう。本皿を通しお、案倖簡単だなず思っおいただけたら幞いだ。

提䟛:マむナビ転職゚ヌゞェント

䌚員登録はこちら

「䞊流でWEBサむトの䌁画・プロデュヌスに携わりたい!」「埅遇を良くしたい!」 「自分の経隓・スキルではどうなのだろう ?」「忙しくお転職掻動する時間がない!」 そんなあなたに 転職掻動を総合的にサポヌトしおくれるプロを探しおみたせんか 「マむナビ転職゚ヌゞェント」は、人材玹介型転職情報サむト。 あなたの転職掻動を成功に導くプロのコンサルタントがきっず芋぀かりたす! 非公開求人情報など、転職情報サむトでは掲茉されおいない求人情報も満茉です!

毎日コミュニケヌションズはプラむバシヌマヌクを取埗しおいたす。