forked from: Forcemap Particles
/**
* Copyright takumi0125 ( http://wonderfl.net/user/takumi0125 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/8iB7
*/
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.Timer;
[SWF(backgroundColor = "0xffffff", frameRate = "60")]
public class Main extends Sprite {
private var _particles:Vector.<ParticleItem>; //パーティクルデータ
private var _mainBitmap:Bitmap; //メインのBitmap
private var _mainBitmapData:BitmapData; //メインのBitmapData
private var _forceMap:BitmapData; //forcemap (BitmapData)
private var _forceMapOffset:Array; //forcemapのoffset
private var _forceMapSeed:Number; //forcemapのseed
private var _forceMapUpdateTimer:Timer; //forcemap更新のタイマー
private var _bitmapRect:Rectangle; //ビットマップの範囲
private var _fadeOutColorTransform:ColorTransform; //フェードアウト用のColorTransform
private var _particleDisplayItem:Shape;
private var _displayBitmapDatas:Vector.<BitmapData>;
private const _NUM_PARTICLES:uint = 10000; //パーティクルの数
//constructor
public function Main() {
_init();
}
//イニシャライズ
private function _init():void {
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT
//動かす図形
_particleDisplayItem = new Shape();
var g:Graphics = _particleDisplayItem.graphics;
g.lineStyle(1, 0xffffff);
g.beginFill(0xaacf53);
g.moveTo(-10, -10);
g.lineTo(-10, 10);
g.lineTo(10, 0);
g.lineTo(-10, -10);
g.endFill();
//予めビットマップを描画 1度ずつ
_displayBitmapDatas = new Vector.<BitmapData>();
var tmpBitmapData:BitmapData;
var matrix:Matrix = new Matrix();
for(var i:uint = 0; i <= 360; i++) {
tmpBitmapData = new BitmapData(20, 20, true, 0x000000);
matrix.identity();
matrix.rotate(i / _RADIAN);
matrix.translate(10, 10);
tmpBitmapData.draw(_particleDisplayItem, matrix);
_displayBitmapDatas.push(tmpBitmapData);
}
//メインのビットマップ
_mainBitmap = new Bitmap();
addChild(_mainBitmap);
_fadeOutColorTransform = new ColorTransform(1, 1, 1, 1, 10, 10, 10);
//タイマーでフォースマップを1秒ごとに更新
_forceMapOffset = [ new Point(0,0), new Point(0,0) ];
_forceMapUpdateTimer = new Timer(1000);
_forceMapUpdateTimer.addEventListener(TimerEvent.TIMER, _updatePerlinNoise);
_resizeHandler();
//パーティクルデータ生成
_particles = new Vector.<ParticleItem>();
var particle:ParticleItem;
for(i = 0; i < _NUM_PARTICLES; i++) {
particle = new ParticleItem();
_particles.push(particle);
}
//リサイズ処理
stage.addEventListener(Event.RESIZE, _resizeHandler);
//フレームごとの処理
addEventListener(Event.ENTER_FRAME, _enterFrameHandler);
}
//perlineNoiseを更新
private function _updatePerlinNoise(e:TimerEvent = null):void {
_forceMapOffset[0].x += 3;
_forceMapOffset[1].y += 3;
_forceMapSeed = Math.floor(Math.random() * 0xFFFFFF);
_forceMap.perlinNoise(200, 200, 2, _forceMapSeed, false, true, 6, false, _forceMapOffset);
}
//リサイズ処理
private function _resizeHandler(e:Event = null):void {
_bitmapDataWidth = stage.stageWidth;
_bitmapDataHeight = stage.stageHeight;
_bitmapRect = new Rectangle(0, 0, _bitmapDataWidth, _bitmapDataHeight);
//フォースマップ
if(_forceMap) _forceMap.dispose();
_forceMap = new BitmapData(_bitmapDataWidth, _bitmapDataHeight, false, 0x000000);
_forceMapUpdateTimer.stop();
_forceMapUpdateTimer.reset();
_forceMapUpdateTimer.start();
_updatePerlinNoise();
//メインのビットマップ
if(_mainBitmapData) _mainBitmapData.dispose();
_mainBitmapData = new BitmapData(_bitmapDataWidth, _bitmapDataHeight, false, 0xff000000);
_mainBitmap.bitmapData = _mainBitmapData;
}
//フレームごとの処理
private function _enterFrameHandler(e:Event):void {
_mainBitmapData.colorTransform(_bitmapRect, _fadeOutColorTransform);
var particle:ParticleItem;
_mainBitmapData.lock();
for(var i:uint = 0; i < _NUM_PARTICLES; i++) {
particle = _particles[i];
//フォースマップの色抽出
particle.updateParams(_forceMap.getPixel(particle.x, particle.y));
//描画
var rot:Number = Math.round(Math.atan2(particle.vy, particle.vx) * _RADIAN);
if(rot < 0) rot += 360;
_mainBitmapData.copyPixels(_displayBitmapDatas[rot], _displayBitmapDatas[rot].rect, new Point(particle.x - 10, particle.y - 10));
}
_mainBitmapData.unlock();
}
}
}
var _bitmapDataWidth:Number; //ビットマップの横幅
var _bitmapDataHeight:Number; //ビットマップの縦幅
const _RADIAN:Number = 180 / Math.PI; //1ラジアン
//パーティクル
class ParticleItem {
private var _x:Number, _y:Number; //位置
private var _vx:Number, _vy:Number; //速度
private var _ax:Number, _ay:Number; //加速度
//constructor
public function ParticleItem() {
_vx = _vy = _ax = _ay = 0;
_x = Math.random() * _bitmapDataWidth;
_y = Math.random() * _bitmapDataHeight;
}
//位置、加速度、速度更新
public function updateParams(color:uint):void {
_ax += ((color & 0xff) - 0x80 ) * .0005;
_ay += ((color >> 8 & 0xff) - 0x80 ) * .0005;
_vx += _ax;
_vy += _ay;
_x += _vx;
_y += _vy;
_ax *= .96;
_ay *= .96;
_vx *= .92;
_vy *= .92;
(_x > _bitmapDataWidth)? _x = 0: (_x < 0)? _x = _bitmapDataWidth: 0;
(_y > _bitmapDataHeight)? _y = 0: (_y < 0)? _y = _bitmapDataHeight: 0;
}
//_xを取得
public function get x():Number {
return _x;
}
//_yを取得
public function get y():Number {
return _y;
}
//_vxを取得
public function get vx():Number {
return _vx;
}
//_vyを取得
public function get vy():Number {
return _vy;
}
}