Particle Sample Part3
大量のパーティクルを発生させてみた
動きの指定方法を模索中
Emitter の初期化時にレンダリングする DisplayObject や、1フレームで追加するパーティクル数やパーティクルの初期化時のステータスおよび update ごとに更新する部分をオブジェクトで指定するようにしてみた
// forked from cellfusion's Particle Sample Part2
// forked from cellfusion's Particle Sample
// write as3 code here..
// 大量のパーティクルを発生させてみた
// 動きの指定方法を模索中
// Emitter の初期化時にレンダリングする DisplayObject や、1フレームで追加するパーティクル数やパーティクルの初期化時のステータスおよび update ごとに更新する部分をオブジェクトで指定するようにしてみた
package
{
import flash.display.Sprite;
import flash.display.StageQuality;
import flash.events.Event;
import flash.events.MouseEvent;
import net.hires.debug.Stats;
[SWF(width="465", height="465", backgroundColor="0x000000", frameRate="30")]
public class ParticleSample extends Sprite
{
private var _emitter:Emitter;
public function ParticleSample()
{
stage.quality = StageQuality.LOW;
setup();
addChild(new Stats());
}
private function setup():void
{
_emitter = new Emitter(this, 5,
{x:0, y:{min:0, max:10}, vx:{min:-1, max:1}, vy:function(p:Particle):Number{ return Math.random() * -10; }, life:{min:5, max:60}},
{
vx:function(p:Particle):Number { return p.vx + Math.random()*3-1.5; },
alpha:function(p:Particle):Number { return (p.life - p.count) / p.life; },
vy:-5
});
addChild(_emitter);
addEventListener(Event.ENTER_FRAME, update);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
}
private function update(event:Event):void
{
_emitter.update();
}
private function mouseDown(event:MouseEvent):void
{
_emitter.isCreate = true;
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
}
private function mouseUp(event:MouseEvent):void
{
_emitter.isCreate = false;
stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp);
}
}
}
import flash.display.GradientType;
import flash.display.SpreadMethod;
import flash.display.Sprite;
import flash.geom.Matrix;
class Emitter extends Sprite
{
//private var _particles:Vector.<Particle> = new Vector.<Particle>();
private var _particles:Array = [];
private var _display:Sprite;
private var _num:uint;
private var _init:Object;
private var _obj:Object;
private var _isCreate:Boolean;
public var vx:Number = 0;
public var vy:Number = 0;
public function get isCreate():Boolean { return _isCreate; }
public function set isCreate(b:Boolean):void { _isCreate = b; }
public function get motionObj():Object { return _obj; }
public function set motionObj(obj:Object):void { _obj = obj; }
public function Emitter(display:Sprite, num:uint, init:Object, obj:Object)
{
_display = display;
_num = num;
_init = init;
_obj = obj;
_isCreate = false;
for (var i:uint = 0; i < 10000; i++) {
_particles.push(new Particle());
}
}
/**
* Emitter 自身の位置と particle の位置を更新
*/
public function update():void
{
var dx:Number = root.mouseX - x;
var dy:Number = root.mouseY - y;
var d:Number = Math.sqrt(dx*dx+dy*dy) * 0.2;
var rad:Number = Math.atan2(dy, dx);
vx += Math.cos(rad)*d;
vy += Math.sin(rad)*d;
vx *= 0.7;
vy *= 0.7;
x += vx;
y += vy;
//if (_isCreate) create();
create();
for each (var p:Particle in _particles) {
if (!p.destroy) {
setParticleParam(p, _obj);
p.update();
}
}
}
private function setParticleParam(p:Particle, obj:Object):void
{
for (var name:String in obj) {
if (obj[name] is Function) {
p[name] = obj[name](p);
} else if (obj[name] is Number) {
p[name] = obj[name];
} else if (obj[name] is String) {
p[name] += Number(obj[name]);
} else {
if (obj[name].max != null && obj[name].min != null) {
p[name] = (obj[name].max - obj[name].min) * Math.random() + obj[name].min;
}
}
}
}
private function initParticleParam(p:Particle, obj:Object):void
{
for (var name:String in obj) {
if (name == "x" || name == "y") {
if (obj[name] is Number) {
p[name] = this[name] + obj[name];
} else if (obj[name] is String) {
p[name] = this[name] + Number(obj[name]);
} else if (obj[name] is Function) {
p[name] = this[name] + obj[name](p);
} else {
if (obj[name].max != null&& obj[name].min != null) {
p[name] = this[name] + (obj[name].max - obj[name].min) * Math.random() + obj[name].min;
}
}
} else {
if (obj[name] is Function) {
p[name] = obj[name](p);
} else if (obj[name] is Number) {
p[name] = obj[name];
} else if (obj[name] is String) {
p[name] += Number(obj[name]);
} else {
if (obj[name].max != null && obj[name].min != null) {
p[name] = (obj[name].max - obj[name].min) * Math.random() + obj[name].min;
}
}
}
}
}
/**
* Particle を生成する
*/
private function create():void
{
var count:uint = 0;
for each (var p:Particle in _particles) {
// 停止している Particle を探す
if (p.destroy) {
initParticleParam(p, _init);
p.init();
_display.addChild(p);
count++;
}
if (count > _num) break;
}
}
}
class Particle extends Sprite
{
public var vx:Number;
public var vy:Number;
public var life:Number;
public var size:Number;
private var _count:uint;
private var _destroy:Boolean;
public function Particle()
{
size = Math.random() * 30;
var red:uint = Math.floor(Math.random()*100+156);
var blue:uint = Math.floor(Math.random()*100+100);
var green:uint = Math.floor(Math.random()*156);
var color:Number = (red << 16) | (green << 8) | (blue);
var fillType:String = GradientType.RADIAL;
var colors:Array = [color , 0x000000];
var alphas:Array = [100, 100];
var ratios:Array = [0x00, 0xFF];
var mat:Matrix = new Matrix();
mat.createGradientBox(size * 2, size * 2, 0, -size, -size);
var spreadMethod:String = SpreadMethod.PAD;
graphics.clear();
graphics.beginGradientFill(fillType, colors, alphas, ratios, mat, spreadMethod);
graphics.drawCircle(0, 0, size);
graphics.endFill();
blendMode = "add";
_destroy = true;
}
public function get count():uint {
return _count;
}
public function init():void
{
_count = 0;
_destroy = false;
}
public function update():void
{
x += vx;
y += vy;
_count++;
// 死亡フラグ
if (life < _count) {
_destroy = true;
parent.removeChild(this);
}
}
public function get destroy():Boolean
{
return _destroy;
}
}