LineStorm(3)
perlinNoiseを利用してラインの移動方向を決めています。
右側に動かしたかったのでちょっと補正入り
不規則感をだすために参照するmapの数を増やしました
最上位レイヤーを消して煙っぽい表現へ
/**
* Copyright okoi ( http://wonderfl.net/user/okoi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/wCTa
*/
//
// LineStorm(3)
// perlinNoiseを利用してラインの移動方向を決めています。
// 右側に動かしたかったのでちょっと補正入り
//
// 不規則感をだすために参照するmapの数を増やしました
// 最上位レイヤーを消して煙っぽい表現へ
//
// @author okoi
//
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.filters.ColorMatrixFilter;
import flash.filters.BlurFilter;
import flash.geom.Point;
[SWF(width = "465", height = "465", frameRate="60")]
/**
* ...
* @author
*/
public class Main extends Sprite
{
private static const FORCENUM:int = 4;
private var forceMap:Vector.<BitmapData>;
private var canvas:BitmapData;
private var backcanvas:BitmapData;
private var particles:Vector.<Particle>;
private var forcect:Vector.<int>;
private var colorFilter:ColorMatrixFilter;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
graphics.beginFill(0);
graphics.drawRect(0, 0, WIDTH, HEIGHT);
graphics.endFill();
forceMap = new Vector.<BitmapData>(FORCENUM,true);
forcect = new Vector.<int>(FORCENUM,true);
for ( var i:int = 0; i < FORCENUM; i++ )
{
forceMap[i] = new BitmapData(WIDTH, HEIGHT, false, 0);
InitForceMap(i);
}
// addChild( new Bitmap( forceMap ) );
backcanvas = new BitmapData(WIDTH, HEIGHT, true, 0);
addChild( new Bitmap( backcanvas ) );
canvas = new BitmapData(WIDTH, HEIGHT, true, 0 );
// addChild( new Bitmap( canvas ) );
InitParticle();
colorFilter = new ColorMatrixFilter([
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0.99, 0
]);
addEventListener(Event.ENTER_FRAME, Update );
}
private function InitForceMap(no:int) : void
{
forcect[no] = Math.random() * 50 + 200;
forceMap[no].perlinNoise(
WIDTH/3, // x 方向で使用する周波数(幅)
HEIGHT/3, // y 方向で使用する周波数(高さ)
1, // 重ねる回数 やりすぎると重い
int(Math.random() * 200), // 適当な整数
false, // 補正があり、タイリング可能なノイズ生成を試みる(第09引数でスクロール時に効果的)
true, // フラクタルノイズの有無。falseの場合、炎や海の波のような視覚効果
(0 | 0 | 2 | 1), // (8 | 4 | 2 | 1), // ノイズ生成のチャンネル
false, // グレースケール化
null // 第03引数で決めた各レイヤーをスクロールするためのPoint型の配列データ
);
}
private function InitParticle() : void
{
particles = new Vector.<Particle>();
for ( var i:int = 0; i < 2000; i++ )
{
var p:Particle = new Particle();
p.x = Math.random() * WIDTH;
p.y = Math.random() * HEIGHT;
p.mx = 0; p.my = 0;
p.forceno = Math.random() * FORCENUM;
particles.push( p );
}
}
private function Update(e:Event):void
{
var i:int;
backcanvas.lock();
backcanvas.fillRect( backcanvas.rect, 0 );
backcanvas.draw( canvas );
backcanvas.applyFilter( backcanvas, backcanvas.rect, new Point(), new BlurFilter(8,8,2) );
backcanvas.unlock();
canvas.lock();
canvas.applyFilter( canvas, canvas.rect, new Point(), colorFilter );
//canvas.fillRect( canvas.rect, 0 );
var num:int = particles.length;
for ( i = 0; i < num; i++ )
{
var p:Particle = particles[i];
var col:uint = forceMap[p.forceno].getPixel( p.x, p.y );
var r:uint = (col >> 16) & 0xff;
var g:uint = (col >> 8) & 0xff;
p.mx += ( r - 128 ) * .005 + 0.1;
p.my += ( g - 128 ) * .005;
p.mx *= 0.96;
p.my *= 0.96;
p.x += p.mx;
p.y += p.my;
if ( p.x < 0 ) p.x = WIDTH + (p.x & WIDTH);
else if ( p.x >= WIDTH ) p.x = p.x % WIDTH;
if ( p.y < 0 ) p.y = HEIGHT + (p.y & HEIGHT);
else if ( p.y >= HEIGHT ) p.y = p.y % HEIGHT;
canvas.setPixel32( p.x, p.y, 0xFFFFFFFF );
}
canvas.unlock();
for ( i = 0; i < FORCENUM; i++ )
{
forcect[i]--;
if ( forcect[i] == 0 ) InitForceMap(i);
}
}
}
}
const WIDTH:int = 465;
const HEIGHT:int = 465;
class Particle {
public var x:Number;
public var y:Number;
public var mx:Number;
public var my:Number;
public var forceno:int;
}