Message Particle
前回のBitmapFilterに引き続き、BitmapでParticle練習。
好きな文字を入力後、Enterで開始。クリックで崩れる。
@author rettuce
/**
* Copyright rettuce ( http://wonderfl.net/user/rettuce )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/vHGo
*/
// forked from nutsu's BitmapDataSample11
package
{
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.events.KeyboardEvent;
import flash.display.BitmapDataChannel;
import flash.filters.BlurFilter;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFieldType;
import flash.text.TextFormat;
[SWF(width = 465, height = 465, backgroundColor = 0x000000, frameRate = 60)]
/**
* 前回のBitmapFilterに引き続き、BitmapでParticle練習。
* 好きな文字を入力後、Enterで開始。クリックで崩れる。
* @author rettuce
*/
public class DocumentClass extends Sprite
{
private var bmpdata:BitmapData;
private var vectormap:BitmapData;
private var filter:BlurFilter;
private var particles:Array;
private var particle_number:uint = 40000;
private var size:Number = 465;
private var txt:TextField;
private var tf:TextFormat;
private var tfc:Number;
private var count:uint;
public function DocumentClass()
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
bmpdata = new BitmapData( size, size, false, 0x000000 );
addChild( new Bitmap( bmpdata ) );
// 初期 text Field セット
txt = new TextField();
tf = new TextFormat();
txt.autoSize = TextFieldAutoSize.CENTER;
txt.type = TextFieldType.INPUT;
txt.border = true;
txt.borderColor = 0xFF666666;
txt.background = true;
txt.backgroundColor = 0xFF333333;
txt.text = "wonderfl"; tf.size = 100; tf.bold = true;
tf.color = 0xFF666666;
txt.setTextFormat(tf);
txt.x = (465 - txt.width) / 2; txt.y = 465 / 2 - txt.height / 2;
addChild(txt);
txt.addEventListener(KeyboardEvent.KEY_DOWN, start);
}
private function start(e:KeyboardEvent = null):void
{
if (e.keyCode == 13) // ENTER
{
txt.removeEventListener(KeyboardEvent.KEY_DOWN, start);
removeChild(txt);
//ベクトルマップとパーティクルの初期化
vectormap = new BitmapData( size, size, false, 0 );
mapInit();
particleSet();
//イベント
addEventListener( Event.ENTER_FRAME, enterframe );
}
}
private function fallStart():void
{
removeEventListener( Event.ENTER_FRAME, enterframe );
for (var i:int = 0; i < particle_number; i++)
{
var p:Particle = particles[i];
p.reset();
}
tfc = 0xFF000000;
reset();
addEventListener( Event.ENTER_FRAME, enterframe2 );
stage.addEventListener( MouseEvent.CLICK, clickHandler );
}
private function clickHandler(e:Event):void{
tfc = 0xFFFFFFFF;
reset();
}
private function enterframe(e:Event):void
{
//描画を消す
bmpdata.fillRect(bmpdata.rect, 0xFF000000);
//パーティクルの描画
bmpdata.lock();
for (var i:int = 0; i < particle_number; i++ )
{
var p:Particle = particles[i];
//ベクトルマップのPixel値から加速度を算出
var col:uint = vectormap.getPixel(p.x, p.y);
p.ax += ((col >> 16 & 0xff)-128) * 0.0001;
p.ay += ((col >> 8 & 0xff )-128) * 0.0001;
//加速度から速度と位置を算出
p.x += p.vx += p.ax;
p.y += p.vy += p.ay;
if (p.x > size) { p.x -= size; }
else if(p.x < 0) { p.x += size; }
if (p.y > size) { p.y -= size; }
else if(p.y < 0) { p.y += size; }
//Pixelへ描画
bmpdata.setPixel(p.x, p.y, 0xffffff);
//加速度と速度の減衰
p.ax *= 0.96; p.ay *= 0.96;
p.vx *= 0.92; p.vy *= 0.92;
}
bmpdata.unlock();
if (count >= 80) fallStart();
count++;
}
private function enterframe2(e:Event):void
{
bmpdata.fillRect(bmpdata.rect, 0xFF000000);
bmpdata.lock();
for (var i:int = 0; i < particle_number; i++ )
{
var p:Particle = particles[i];
var col:uint = vectormap.getPixel(p.x, p.y);
p.ax += (col >> 16) * 0.0000003;
p.ay += (col >> 8 ) * 0.0000003;
p.x += p.vx += p.ax;
p.y += p.vy += p.ay;
bmpdata.setPixel(p.x, p.y, 0xffffff);
p.ax *= 0.96; p.ay *= 0.96;
p.vx *= 0.92; p.vy *= 0.92;
}
bmpdata.unlock();
}
private function reset(e:MouseEvent = null):void
{
var randomSeed:int = Math.random() * 0xffffffff;
var colors:uint = BitmapDataChannel.RED | BitmapDataChannel.BLUE | BitmapDataChannel.GREEN;
var matrix:Matrix = new Matrix();
// text Field セット
txt.border = txt.background = false;
txt.text = txt.text;
tf.color = tfc;
matrix.translate( 200, 465 / 2 - txt.height / 2);
txt.setTextFormat(tf);
//ベクトルマップのリセット
vectormap.perlinNoise( size / 2, size / 2, 4, randomSeed, false, true, colors );
vectormap.draw(txt, matrix);
}
private function mapInit():void {
//ベクトルマップの初期化
vectormap = new BitmapData( size, size, false, 0xFFFFFF );
var randomSeed:int = Math.random() * 0xffffffff;
var colors:uint = BitmapDataChannel.RED | BitmapDataChannel.BLUE | BitmapDataChannel.GREEN;
//マップのセット
vectormap.perlinNoise( size / 2, size / 2, 1, 177, false, true, colors );
}
private function particleSet():void {
particles = new Array(particle_number);
for (var i:int = 0; i < particle_number; i++ ) { particles[i] = new Particle(Math.random() * size, Math.random() * size);}
}
}
}
class Particle {
// 位置
public var x:Number;
public var y:Number;
//加速度
public var ax:Number = 0;
public var ay:Number = 0;
//速度
public var vx:Number = 0;
public var vy:Number = 0;
public function Particle(px:Number,py:Number){
x = px;
y = py;
}
public function reset():void{
ax *= ay *= vx *= vy *= 0;
}
}