AS3のオープンソースライブラリ「stardust」でパーティクルをお勉強(3):Deflector

2010年01月15日  投稿者:ハセガワ
傘に雪(パーティクル)が当たると避けていくようになったよ。
ブックマークする:

進行状況

→第6回:何か作りたい(1):よくあるきらきらしたやつ(ソースあり)
→第5回:Classの中身(2):Emitter2Dクラス(調査中)
→第4回:Classの中身(1):Clockクラス(調査中)
→第3回:お勉強(3):パーティクルがよける…Deflectorクラスで障害物
→第2回:お勉強(2):マウスで作る、やめる…Emitter.active
→第1回:お勉強(1):とりあえず何か出来た

パーティクルを生成する手順(2D)

stardustを使ってパーティクルを作るための基本的な順番は、公式マニュアルによると

(1)Clockを作る…パーティクル発生の頻度
(2)Emitterを作ってclockをセット…エミッターって発生装置みたいなもの(?)
(3)Rendererを作る…画面表示用オブジェクト(?)
(4)Renderer.addEmitter( Emitter )でエミッターをレンダラーにセット
(5)Emitter.addInitializer( 発生場所とか発生させるspiteとか )でエミッターを初期設定
(6)Emitter.addAction( 寿命の長さとか重力とか )で実際の動きを設定
(7)Event.ENTER_FRAMEやTimerEvent.TIMERに、Emitter.step()を関連づけて表示を更新

となっている。

デフレクターでパーティクルを妨害する
FlashPlayerをインストールするか、JavaScriptをONにしてください。

Deflector(障害物)を設定すると、パーティクルの流れを邪魔できる。 

パーティクルのに対して障害物となるインスタンス<Deflector>

Deflectorクラスは、この順番で登録する。

//読み込むクラス(円形の障害物)
import idv.cjcat.stardust.twoD.deflectors.CircleDeflector;

//…(略)…

//半径50の障害物(円)作成
private var circleDeflector:CircleDeflector = new CircleDeflector(0, 0, 50);

//…(略)…

//デフレクター(障害物)の設定 
circleDeflector.bounce = 0;//障害物に当たった時のはねかえり係数
var deflect:Deflect = new Deflect();
deflect.addDeflector( circleDeflector);//デフレクターに円を追加
emitter.addAction(deflect);//エミッターに追加

もちろん、この障害物には色や形がついているわけではないので、
傘のシンボルをfla側で作成し、Umbrellaクラスにしておいた。


あとは、マウスの動きに合わせて、デフレクターと傘を同じ動きにしただけ。

//マウスを動かした時の処理(deflector)
			stage.addEventListener(MouseEvent.MOUSE_MOVE, follow);
//マウスを追いかける
		protected function follow(e:MouseEvent):void {
			circleDeflector.x = umbrella.x = root.mouseX;
			circleDeflector.y =  umbrella.y = root.mouseY;
			if (e) e.updateAfterEvent();
		}

しかし動き重い。core2duo/E6600で52/60FPSくらい。これじゃちょっときつい。

サンプルソース
//Raindrop3.as(snowじゃないじゃんってつっこまんといて) 
package {
	import flash.display.*;
	import flash.events.*;
	import idv.cjcat.stardust.common.actions.*;
	import idv.cjcat.stardust.common.clocks.*;
	import idv.cjcat.stardust.common.emitters.*;
	import idv.cjcat.stardust.common.renderers.*;
	import idv.cjcat.stardust.common.initializers.*;
	import idv.cjcat.stardust.common.math.*;
	import idv.cjcat.stardust.twoD.actions.*;
	import idv.cjcat.stardust.twoD.fields.*;
	import idv.cjcat.stardust.twoD.emitters.*;
	import idv.cjcat.stardust.twoD.initializers.*;
	import idv.cjcat.stardust.twoD.zones.*;
	import idv.cjcat.stardust.twoD.renderers.*;
	import idv.cjcat.stardust.twoD.deflectors.CircleDeflector;


	public class Raindrops3 extends Sprite {
		private var emitter:Emitter2D;
		private var renderer:Renderer;
		private var clock:SteadyClock =new SteadyClock(5);
		private var clickflag:Boolean = false;
		private var circleDeflector:CircleDeflector = new CircleDeflector(0, 0, 50);//半径50の障害物(円)作成
		private var umbrella:Umbrella = new Umbrella();//flaのライブラリの中のシンボル

		private var mc:MovieClip = new MovieClip();

		public function Raindrops3() {
			mc.x=mc.y=0;

			addChild(mc);
			addChild( umbrella );

			emitter=new Emitter2D(clock);
			renderer=new DisplayObjectRenderer(mc);
			renderer.addEmitter(emitter);
			emitter.addInitializer(new DisplayObjectClass(MyCircle));
			emitter.addInitializer(new Velocity(new LazySectorZone(0.01, 0)));
			emitter.addInitializer(new Life(new UniformRandom(100, 5)));
			emitter.addInitializer(new Position(new Line( -100, 600, 0, 0 )));
			emitter.addAction(new Age());
			emitter.addAction(new DeathLife());
			emitter.addAction(new Accelerate(0.2));
			emitter.addAction(new Move());
			emitter.addAction(new ScaleCurve(1,7));

			var bmpField :BitmapField = new BitmapField();
			bmpField.max=0.1;
			bmpField.massless=false;
			bmpField.scaleX=bmpField.scaleY=10;

			var gravity:Gravity = new Gravity();
			gravity.addField(bmpField);
			gravity.addField(new UniformField( 0.2, 0.1));
			emitter.addAction(gravity);
			
			//デフレクター(障害物)の設定 
			circleDeflector.bounce = 0;//障害物に当たった時のはねかえり係数
			var deflect:Deflect = new Deflect();
			deflect.addDeflector( circleDeflector);//デフレクターに円を追加
			emitter.addAction(deflect);//エミッターに追加

			stage.addEventListener(MouseEvent.CLICK, startParticle);

			//マウスを動かした時の処理(deflector)
			stage.addEventListener(MouseEvent.MOUSE_MOVE, follow);

		}
		private function startParticle( e:MouseEvent ):void {
			if( !clickflag ){
				clock.ticksPerCall = 8;
				clickflag = true;
			}else{
				clock.ticksPerCall = 0;
				clickflag =false;
			}
			addEventListener(Event.ENTER_FRAME, loop);
		}
		private function loop(e:Event):void {
			emitter.step();
		}
		//マウスを追いかける
		protected function follow(e:MouseEvent):void {
			circleDeflector.x = umbrella.x = root.mouseX;
			circleDeflector.y =  umbrella.y = root.mouseY;
			if (e) e.updateAfterEvent();
		}
	}
}
import flash.display.*;
class MyCircle extends Sprite {
	public function MyCircle() {
		var colorType:uint=0xffffff;
		var snowSize:int=Math.random()*2+1;
		graphics.beginFill( colorType , 1 );
		graphics.drawCircle(snowSize,snowSize,snowSize);
	}
}
できなかったこと、やりたいこと。

・パーティクル生成中にステージクリックでパーティクル生成ストップ(stopとかあるかと思ってたけどなかった)引き続きもっとスマートなやり方を探索中
傘を表示させて、それにあたると雪が跳ね返る(deflect?)→とりあえず出来た
・表示が重いのでもっと軽く。

僕が買った、もしくは買う予定の参考書
ブックマークする
FlaTech+を購読する
  • 全記事を含むRSSfeed
  • このページをブックマーク: