forked from: 炎のエフェクト
source : http://actionsnippet.com/?p=1750
炎エフェクトを描画したBitmapDataをSpriteの子として持たせるようにしました。
炎のスケーリング方法を少し変えて、横幅が縦幅よりも早く縮小するようにしました。
copyPixelsを勉強するためにFORKさせて頂きました。
レイヤーを重ねるようなイメージではなく、まるごとピクセルをコピーするというイメージなのですね。
/**
* Copyright Hado_A ( http://wonderfl.net/user/Hado_A )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/1qW9
*/
// forked from kato's 炎のエフェクト
// source : http://actionsnippet.com/?p=1750
// 炎エフェクトを描画したBitmapDataをSpriteの子として持たせるようにしました。
// 炎のスケーリング方法を少し変えて、横幅が縦幅よりも早く縮小するようにしました。
// copyPixelsを勉強するためにFORKさせて頂きました。
// レイヤーを重ねるようなイメージではなく、まるごとピクセルをコピーするというイメージなのですね。
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.GradientType;
import flash.display.SpreadMethod;
import flash.filters.BlurFilter;
import flash.filters.BitmapFilterQuality;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.ByteArray;
import flash.utils.Dictionary;
import flash.events.Event;
import net.hires.debug.Stats;
[SWF(width="465", height="465", backgroundColor="0x555555", frameRate="30")]
public class ParticleFlame extends Sprite
{
//------------------------------------------------------
// const
//------------------------------------------------------
// グラデーション
private const COLORS :Array = [0xFFCC33, 0xFF0000];
private const ALPHAS :Array = [0.6, 0.2];
private const RATIOS :Array = [50, 200];
private const TWO_PI :Number = Math.PI * 2;
private const CANVAS_SIZE :Number = 465;
//------------------------------------------------------
// var
//------------------------------------------------------
private var canvas :BitmapData;
private var overlay :BitmapData;
private var particles :Dictionary;
private var blurs :Array;
private var m_stage :Sprite;
//------------------------------------------------------
// method
//------------------------------------------------------
//------------------------------------------------------
/**
* コンストラクタ
*/
public function ParticleFlame()
{
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.LOW;
stage.scaleMode = StageScaleMode.NO_SCALE;
init();
}
//------------------------------------------------------
/**
* 初期化。
*/
private function init():void
{
canvas = new BitmapData(CANVAS_SIZE, CANVAS_SIZE, true, 0x00000000); // 実際に描画されるもの
overlay = new BitmapData(CANVAS_SIZE, CANVAS_SIZE, true, 0x00000000); // canvasにコピーして上書きするためのもの
m_stage = new Sprite(); // このスプライトをいじれば、容易に炎を表示・非表示切り換えられる
//m_stage.visible = false;
particles = new Dictionary(true); // パーティクルクラスを格納する
// ブラー(ぼかし)フィルタ
blurs = new Array();
blurs.push(new BlurFilter(6, 6, BitmapFilterQuality.HIGH));
addChild(m_stage);
m_stage.addChild(new Bitmap(canvas));
addChild(new Stats());
addEventListener(Event.ENTER_FRAME, loopHandler);
}
//------------------------------------------------------
/**
* 毎フレームイベント。
*/
private function loopHandler(event:Event):void
{
// パーティクルの作成
for(var i:int = 0; i < 3; i++) { createParticle(); }
// canvasをクリア(canvasにoverlayを丸々コピペ)
canvas.copyPixels(overlay, canvas.rect, new Point(), overlay, new Point(), false);
}
//------------------------------------------------------
/**
* パーティクルを作成。
*/
private function createParticle():void
{
var p:Particle = new Particle();
// パーティクルのサイズ
var diameter:Number = Math.random() * 60 + 5; // 直径(+nで最小の直径を決めている)
var radius:Number = diameter / 2;
// グラデーションの性質を決めるマトリクスを作成
var mat:Matrix = new Matrix();
mat.createGradientBox(diameter, diameter, 0, -radius, -radius);
// グラデーション円描画開始
p.graphics.beginGradientFill(GradientType.RADIAL, COLORS, ALPHAS, RATIOS, mat);
p.graphics.drawCircle(0, 0, radius);
p.graphics.endFill();
// 表示位置
p.posX = stage.mouseX;
p.posY = stage.mouseY;
// X座標の遷移を決定づけるパラメータ
p.theta = Math.random() * TWO_PI;
p.inc = Math.random() * 0.4 + 0.01;
p.rad = Math.random() * 2 + 1;
// Y座標の遷移
p.velY = -Math.random() * 5 + 0.5;
// ブラーフィルター設定
p.filters = blurs;
// Dictionaryにこのパーティクルを加える
particles[p] = p;
// ひとつひとつのパーティクルに対して毎フレーム処理イベント
p.addEventListener(Event.ENTER_FRAME, runParticleHandler);
}
//------------------------------------------------------
/**
* ひとつのパーティクルを動かす。
*/
private function runParticleHandler(event:Event):void
{
var p:Particle = event.currentTarget as Particle;
// 移動
p.posX += p.velX;
p.posY += p.velY;
p.x = p.posX;
p.y = p.posY;
// 次フレームの移動方向
p.velX = p.rad * Math.cos(p.theta);
p.theta += p.inc;
if (p.scaleX > 0.06) { p.scaleX -= 0.06; }
// 縮小されて見えなくなったら削除する
if (p.scaleY < 0)
{
particles[p] = null;
p.removeEventListener(Event.ENTER_FRAME, runParticleHandler);
}
else
{
p.scaleY -= 0.03;
}
// 描画
// pのtransform.matrixには p.x, p.scaleX などに関係する行列が入っている?
canvas.draw(p, p.transform.matrix, p.transform.colorTransform, BlendMode.ADD);
}
}
}
//--------------------------------------
//
// Class Particle
//
//--------------------------------------
import flash.display.Sprite;
internal class Particle extends Sprite
{
public var velX:Number;
public var velY:Number;
public var posX:Number;
public var posY:Number;
public var theta:Number;
public var inc:Number;
public var rad:Number;
public function Particle()
{
this.velX = 0;
this.velY = 0;
this.posX = 0;
this.posY = 0;
this.theta = 0;
this.inc = 0;
this.rad = 0;
}
}