燻。
メッシュ化したBitmapDataにDisplacementMapFilterをかけて変形+色の加減算的な処理。
激重なので小さめに描画してます。
...
@author hoge
/**
* Copyright hogemaruo ( http://wonderfl.net/user/hogemaruo )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/sZqMG
*/
// forked from hogemaruo's 七色の炎煙。
package
{
/*
* メッシュ化したBitmapDataにDisplacementMapFilterをかけて変形+色の加減算的な処理。
* 激重なので小さめに描画してます。
*/
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.ColorTransform;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.geom.Matrix;
import flash.filters.GlowFilter;
import flash.filters.BlurFilter;
import flash.filters.DisplacementMapFilter;
import flash.display.DisplayObject;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.display.BlendMode;
import frocessing.color.ColorHSV;
import flash.display.GradientType;
/**
* ...
* @author hoge
*/
[SWF( width=465,height=465)]
public class RainbowFireSmoke extends Sprite
{
private const SW:int = stage.stageWidth;
private const SH:int = stage.stageHeight;
private const MW:int = 400;
private const MH:int = 400;
private static const ZERO_POINT:Point = new Point();
private var offset:Array = [
new Point(0,0),
new Point(0,0),
];
private var ptn:int = 1;
private var noiseSeed:int = Math.floor( Math.random() * 0xffff);
/*
* 文字をディスプレイオブジェクトで返す
*/
private function makeTextSprite(code:String,size:int,col:int):DisplayObject {
var tf:TextField = new TextField();
tf.selectable = false;
tf.autoSize = TextFieldAutoSize.LEFT;
tf.defaultTextFormat = new TextFormat('Verdana', size, col, true);
tf.text = code;
return tf;
}
/*
* ゆがめ用ノイズ作成
*/
private function makeNoise( buf:BitmapData):void {
if ( ptn == 0) {
offset[0].y += 3;//3
offset[0].x += 1;//1
offset[1].y += 8;//8
offset[1].x += -2;//-2
buf.perlinNoise( 150, 200, 2, noiseSeed, true, false, 2 | 4, false,this.offset);
}else {
offset[0].y += 3;
offset[0].x += 1;
offset[1].y += 5;
offset[1].x += -2;
buf.perlinNoise( 40, 80, 2, noiseSeed, false, true, 2 | 4, false,this.offset);
}
}
/*
* 火種をメッシュ化
*/
private function makeDotted(buf:BitmapData):void {
for ( var i:int = 1; i < buf.rect.width; i += 2 ) {
buf.fillRect(new Rectangle( i, 0, 1, buf.rect.height), 0);
}
for ( i = 1; i < buf.rect.height; i += 2 ) {
buf.fillRect(new Rectangle( 0, i, buf.rect.width,1), 0);
}
}
/**
* 火種文字ごとにBitmapData化
*/
private function makeStringSprite(str:String ,sz:int, ar:Array):int {
var w:int = 0;
for ( var i:int = 0; i < str.length; i++ ) {
var spr:DisplayObject = makeTextSprite(str.slice(i,i+1), sz, 0xd0d0d0);
w += (spr.width-8);
var buf:BitmapData = new BitmapData( spr.width, spr.height, true, 0 );
spr.filters = [new GlowFilter(0xffffff, 1, 6, 6,3)];
buf.draw(spr);
ar.push( buf );
}
return w;
}
/**
* カーソル火種作成
*/
private function makeCursor( rad:Number):BitmapData {
var spr:Sprite = new Sprite();
var colors:Array = [0xa00000, 0xff8040, 0xffc080];
var alphas:Array = [1, 1, 1];
var ratios:Array = [128-50,128,128+50];
var matrix:Matrix = new Matrix();
matrix.createGradientBox(rad * 2, rad * 2, 0*Math.PI/180.0, 0, 0);
spr.graphics.beginGradientFill(GradientType.LINEAR,colors,alphas,ratios, matrix);
spr.graphics.drawCircle( rad, rad, rad);
spr.graphics.endFill();
var buf:BitmapData = new BitmapData( spr.width, spr.height, true, 0);
buf.draw(spr);
return buf;
}
private function makeEarth( rad:Number ):BitmapData {
var spr:Sprite = new Sprite();
var colors:Array = [0x303030, 0x000030, 0x403000];
var alphas:Array = [1, 1, 1];
var ratios:Array = [0,128,255];
var matrix:Matrix = new Matrix();
matrix.createGradientBox(rad * 2, rad * 2, 90*Math.PI/180.0, 0, 0);
spr.graphics.beginGradientFill(GradientType.LINEAR,colors,alphas,ratios, matrix);
spr.graphics.drawCircle( rad, rad, rad);
spr.graphics.endFill();
spr.filters = [new GlowFilter(0xd0d0d0, 1, 5, 20,3,1,true)];
var buf:BitmapData = new BitmapData( spr.width, spr.height, true, 0);
buf.draw(spr);
return buf;
}
/*
* メイン
*/
private function mainProc():void {
var cnt:Number = 0;
var bmp:Bitmap = new Bitmap( new BitmapData(SW,SH,false,0) );
var seedBuf:BitmapData = new BitmapData( MW, MH,false,0 );
var bbuf1:BitmapData = new BitmapData( seedBuf.width, seedBuf.height, false, 0 );
var bbuf2:BitmapData = new BitmapData( seedBuf.width, seedBuf.height, false, 0 );
var bbuf3:BitmapData = new BitmapData( seedBuf.width, seedBuf.height, false, 0 );
var arSpr:Array = [];
var arCol:Array = [];
var sprWidth:int = makeStringSprite( 'HEAT', 70, arSpr );
var sprCursor:BitmapData = makeCursor(25);
var ox:int = mouseX;
var oy:int = mouseY;
var sprEarth:BitmapData = makeEarth(120);
addChild(bmp);
//毎フレ処理
addEventListener( Event.ENTER_FRAME, function(e:Event ):void {
cnt++;
var i:int;
var bxx:int = (seedBuf.width - sprWidth) / 2;
var bx:int = 0;
var by:int = 200;
var dx:int = ox -mouseX;
var dy:int = oy -mouseY;
var dist:Number = Math.sqrt( dx * dx + dy * dy);
if ( ptn == 0) {
seedBuf.scroll(-2, -6);//なんだか右に流れるので
}else {
seedBuf.scroll(0, -4);
}
if( ox == 0 && oy == 0 ){//初回に左上にカーソルがくるので
dx = 0;
dy = 0;
}
ox = mouseX;
oy = mouseY;
//カーソル火種
if ( dist > 10 ) {
for ( i = 0; i < dist; i += 10) {
var xx:int = mouseX + dx * i / dist-(SW-MW)/2;
var yy:int = mouseY + dy * i / dist-(SH-MH)/2;
seedBuf.draw( sprCursor, new Matrix( 1, 0, 0, 1, xx - sprCursor.width / 2, yy - sprCursor.height / 2),new ColorTransform(1,1,1,0.1));
}
}else {
xx = mouseX -(SW-MW)/2;
yy = mouseY -(SH-MH)/2;
seedBuf.draw( sprCursor, new Matrix( 1, 0, 0, 1, xx - sprCursor.width / 2,yy - sprCursor.height / 2),new ColorTransform(1,1,1,0.15));
}
seedBuf.draw( sprEarth, new Matrix( 1, 0, 0, 1, (MW-sprEarth.width) / 2,120),new ColorTransform(1,1,1,0.2));
//文字火種
bx = bxx;
for ( i = 0; i < arSpr.length; i++ ) {
var hsv:ColorHSV = new ColorHSV();
hsv.h = cnt * 4 + (arSpr.length-(i+1)) * 360/arSpr.length;
arCol[i] = hsv;
hsv.v = Math.sin(cnt*0.05+i*Math.PI*2/arSpr.length)*0.3+0.7;
hsv.s = Math.sin(cnt*0.2+i*Math.PI*2/arSpr.length)*0.25+0.75;
seedBuf.draw(arSpr[i], new Matrix(1, 0, 0, 1, bx, by),new ColorTransform(hsv.r/255.0,hsv.g/255.0,hsv.b/255.0,0.25));
bx += arSpr[i].width-8;
}
makeDotted(seedBuf );
//ゆがめてちぢめてひきのばす
makeNoise(bbuf1);
seedBuf.applyFilter(seedBuf, seedBuf.rect, ZERO_POINT, new DisplacementMapFilter(bbuf1, ZERO_POINT, 2, 4, 7, 8, "clamp") );
var ff:Number = 4.15;
bbuf3.draw(seedBuf, new Matrix(0.5, 0, 0, 0.5, 0, 0), new ColorTransform(ff, ff, ff, 1), null, null, true);
seedBuf.draw(bbuf3, new Matrix(2, 0, 0, 2, 0, 0),null,null,null,true);
makeDotted(seedBuf );
//炎をスクリーンに描画
bmp.bitmapData.draw(bbuf3, new Matrix(2, 0, 0, 2, (SW-MW)/2, (SH-MH)/2));
//文字を重ねる
bx = bxx;
for ( i = 0; i < arSpr.length; i++ ) {
hsv = arCol[i];
hsv.v = 1;
hsv.s = 1;
bmp.bitmapData.draw(arSpr[i], new Matrix(1, 0, 0, 1, (SW-MW)/2+bx, (SH-MH)/2+by), new ColorTransform(hsv.r/255.0,hsv.g/255.0,hsv.b/255, 0.8),BlendMode.DIFFERENCE);
bx += arSpr[i].width-8;
}
});
}
public function RainbowFireSmoke() {
mainProc();
}
}
}