傾斜プラクティス ver.2
地形の傾斜にしたがってパーティクルが低いところへ集まります。
パーティクル群の重心と画面中心の座標差分で地形をスクロールさせてるので、
うまく重心が中心をずれるとパーティクルが有機的に?流れ出します。
画面クリックで地形をリライト。
---
いちいち地形から傾斜を算出すると重いので、座標ごとの傾斜をデータとして保存させている。
前回作った傾斜マップの仕組みをリアルタイム生成できるように変更。
このことで、地形を動かすことでパーティクルの動きに変化をつけられるようになった。
地形を、パーリンノイズをベースにスクロールさせていることで、いい感じの地形だと段々帯状の動きに変わってきます。
パーリンノイズのシームレススクロールの方がいい気がするけど、重くなりそうなのと、
これはこれで緩急のついた動きの変化になっているのでとりあえずこの状態でアップ。
-----
今回のプラクティスは、
座標ごとの傾斜データを前回配列に入れていたのをBitmapDataに格納場所を変えたこと。
各点が32bitの情報をもてるので、x成分y成分を16bitずつに丸めて格納してる。
高速化につながってるかどうかは、ビジュアル表現を変えちゃったのでwいまいちわからないけど、
ビットシフトがやってみたかったんだ!
/**
* Copyright lagash ( http://wonderfl.net/user/lagash )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/8HxI
*/
package {
/*
地形の傾斜にしたがってパーティクルが低いところへ集まります。
パーティクル群の重心と画面中心の座標差分で地形をスクロールさせてるので、
うまく重心が中心をずれるとパーティクルが有機的に?流れ出します。
画面クリックで地形をリライト。
---
いちいち地形から傾斜を算出すると重いので、座標ごとの傾斜をデータとして保存させている。
前回作った傾斜マップの仕組みをリアルタイム生成できるように変更。
このことで、地形を動かすことでパーティクルの動きに変化をつけられるようになった。
地形を、パーリンノイズをベースにスクロールさせていることで、いい感じの地形だと段々帯状の動きに変わってきます。
パーリンノイズのシームレススクロールの方がいい気がするけど、重くなりそうなのと、
これはこれで緩急のついた動きの変化になっているのでとりあえずこの状態でアップ。
-----
今回のプラクティスは、
座標ごとの傾斜データを前回配列に入れていたのをBitmapDataに格納場所を変えたこと。
各点が32bitの情報をもてるので、x成分y成分を16bitずつに丸めて格納してる。
高速化につながってるかどうかは、ビジュアル表現を変えちゃったのでwいまいちわからないけど、
ビットシフトがやってみたかったんだ!
*/
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.Bitmap;
import flash.display.Stage;
import flash.display.BitmapData;
import flash.display.DisplayObjectContainer;
import flash.display.LineScaleMode;
import flash.display.BlendMode;
import flash.events.MouseEvent;
import flash.filters.DisplacementMapFilter;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.geom.ColorTransform;
import flash.events.Event;
import flash.utils.ByteArray;
import flash.filters.BlurFilter;
import net.hires.debug.Stats;
public class partest extends Sprite {
var bmp:Bitmap;
var bmp2:Bitmap;
var baseMatrix: Matrix = new Matrix();
var baseRect:Rectangle;
var basePoint:Point;
var baseColorTransform:ColorTransform;
var keishaMap:BitmapData;
const maxParticles = 1000;
static public var forceMap: BitmapData;
private var COLOR: uint = 0xFFFFFF;
private var seed: int;
private var mw: int;
private var mh: int;
private var arr: Array;
private var point: Point;
private var point2: Point;
private var colorTf: ColorTransform;
private var blur: BlurFilter;
static public const _TABLE_SIZE:int = 0x10000;
static public const _PI:Number = Math.PI;
static public const _RADIANS:Number;// = _DEGREES * (_PI / 180);
static public const _TWO_PI:Number = 2 * _PI;
static public const _TWO_PI_SCALE:Number = _TABLE_SIZE / _TWO_PI;
static public const _HALF_PI:Number = _PI / 2;
static public const _table:Vector.<Number> = new function ():Vector.<Number>{
var table:Vector.<Number> = new Vector.<Number>(_TABLE_SIZE, true);
for (var i:uint = 0; i < _TABLE_SIZE; i++) {
table[i] = Math.sin(i / _TWO_PI_SCALE);
}
return table;
};
static public var stageWidth;
static public var stageHeight;
var centerX:uint;
var centerY:uint;
private var particles:Vector.<particle>=new Vector.<particle>();
public function partest() {
super();
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event) {
stage.frameRate = 60;
stageWidth = stage.stageWidth;
stageHeight = stage.stageHeight;
bmp = new Bitmap(new BitmapData(stage.stageWidth, stage.stageHeight, true, 0xff000000), "auto", true);//bitmap処理用
bmp.alpha = .5;
bmp2 = new Bitmap(new BitmapData(stage.stageWidth, stage.stageHeight, true, 0xff000000), "auto", true);//bitmap処理用
basePoint = new Point(0, 0);
baseRect = new Rectangle(0, 0, stageWidth, stageHeight);
baseColorTransform = new ColorTransform;
//baseColorTransform.alphaMultiplier = .99;
//baseColorTransform.redMultiplier = baseColorTransform.greenMultiplier = baseColorTransform.blueMultiplier = 1.01;
baseColorTransform.redOffset = baseColorTransform.greenOffset = baseColorTransform.blueOffset = -10;
forceMap = new BitmapData(stageWidth / 2, stageHeight / 2);
setMap();
baseMatrix.identity();
//emptymatrix.b = emptymatrix.c = 2;
stage.addEventListener(MouseEvent.CLICK, mouseClickHandlr);
stage.addEventListener(Event.ENTER_FRAME, enterframeHandlr);
addChild(bmp2);
addChild(bmp);
addChild(new Stats());
for (var i = 0; i < maxParticles; i++) {
if (i != 0) {
particles.push(new particle(stage.stageWidth * Math.random(), stage.stageHeight * Math.random(), particles.length, particles[particles.length - 1]));
}else {
particles.push(new particle(stage.stageWidth * Math.random(), stage.stageHeight * Math.random(), 0));
}
}
}
private function mouseClickHandlr(e) {
setMap();
}
function setMap():void{
forceMap.perlinNoise(mw = forceMap.width >> 2, mh = forceMap.height >> 2, 2,
seed = Math.random() * 0xFFFF, true, true, 1);
arr = [point = new Point(), point2 = new Point()];
keishaMap = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x00000000);//傾斜データ保存用
}
function setMapPoint(tmpX,tmpY):uint{
var col = forceMap.getPixel(tmpX >> 1, tmpY >> 1);
var dx = 0;
var dy = 0;
for (var py = -1; py < 2; py++){
for (var px = -1; px < 2; px++) {
if (px == 0 && py == 0) continue;
var ppx = tmpX + px;
var ppy = tmpY + py;
if (ppx < 0 || ppx >= stageWidth) { ppx = int(ppx<0)* (stageWidth-1); }
if (ppy < 0 || ppy >= stageHeight){ ppy = int(ppy<0)* (stageHeight-1);}
var tmpcol = forceMap.getPixel(ppx >> 1, ppy >> 1);
bmp2.bitmapData.setPixel(ppx, ppy, tmpcol);
if (px*px + py*py == 1) {
dx += (col - tmpcol) * px;
dy += (col - tmpcol) * py;
}else {
dx += (col - tmpcol) * px*.7;
dy += (col - tmpcol) * py*.7;
}
}
}
col = uint((uint((uint(dx/5)&0x80000000)>>>16)+(uint(dx/5)&0x7fff)<<16)+uint((uint(dy/5) & 0x80000000) >>> 16) + (uint(dy/5) & 0x7fff));
keishaMap.setPixel32(tmpX, tmpY, col);
return col;
}
private function enterframeHandlr(e)
{
//frameCounter+=.01;
//coefficientOfMass = (_table[(frameCounter * _TWO_PI_SCALE) & (_TABLE_SIZE - 1)]*_table[(frameCounter * _TWO_PI_SCALE) & (_TABLE_SIZE - 1)])*3;
//mouse_X = e.currentTarget.mouseX;
//mouse_Y = e.currentTarget.mouseY;
var flg_2 = 0;
bmp.bitmapData.lock();
centerX = centerY = 0;
var col: uint, h: Number;
for (var i = 0; i < particles.length; i++) {
var tmpObj = particles[i];
centerX += tmpObj.xx;
centerY += tmpObj.yy;
col = i/maxParticles*0x99;
col = 0x10000 * (col * 0xff) + 0x100 * (col * 0xff) + (col * 0xaa);
var tmpCol = keishaMap.getPixel32(tmpObj.xx, tmpObj.yy);
if (forceMap.getPixel(tmpObj.xx>>1, tmpObj.yy>>1)!=bmp2.bitmapData.getPixel(tmpObj.xx, tmpObj.yy)) tmpCol=setMapPoint(int(tmpObj.xx), int(tmpObj.yy));
var bX = tmpCol >>> 16;
var bY = tmpCol & 0xffff;
tmpObj.dx = int(uint((((bX&0x8000)<<16)>>16)+(bX&0x7fff)))*.00001;
tmpObj.dy = int(uint((((bY&0x8000)<<16)>>16)+(bY&0x7fff)))*.00001;
tmpObj.tx = tmpObj.tx * .99 + (tmpObj.dx * uint(tmpObj.dx > 0 && tmpObj.tx < 4) + tmpObj.dx * uint(tmpObj.dx<0 && tmpObj.tx>-4));
tmpObj.ty = tmpObj.ty * .99 + (tmpObj.dy * uint(tmpObj.dy > 0 && tmpObj.ty < 4) + tmpObj.dy * uint(tmpObj.dy<0 && tmpObj.ty>-4));
tmpObj.xx += tmpObj.tx;
tmpObj.yy += tmpObj.ty;
if (tmpObj.xx < 0 || tmpObj.xx >= stageWidth) { tmpObj.xx = uint(tmpObj.tx < 0) * (stageWidth-1);}
if (tmpObj.yy < 0 || tmpObj.yy >= stageHeight) { tmpObj.yy = uint(tmpObj.ty < 0) * (stageHeight-1);}
bmp.bitmapData.setPixel(tmpObj.xx, tmpObj.yy, col );
}
centerX /= particles.length;
centerY /= particles.length;
//スクロール処理
//bmp.bitmapData.colorTransform(baseRect, baseColorTransform);
//bmp2.bitmapData.applyFilter(bmp2.bitmapData, baseRect, basePoint, new DisplacementMapFilter(bmp.bitmapData));
//bmp.bitmapData.scroll((stageWidth / 2 - centerX) / 10, (stageHeight / 2 - centerY) / 10);
//bmp.bitmapData.scroll(_table[((frameCounter + _HALF_PI) * _TWO_PI_SCALE) & (_TABLE_SIZE - 1)] * 10, _table[(frameCounter * _TWO_PI_SCALE) & (_TABLE_SIZE - 1)] * 10);
//tmpBmd.colorTransform(baseRect, baseColorTransform);
//tmpBmd.scroll( -(stageWidth / 2 - centerX) / 5, -(stageHeight / 2 - centerY) / 5);
forceMap.scroll( -(stageWidth / 2 - centerX) / 20, -(stageHeight / 2 - centerY) / 20);
//bmp.bitmapData.draw(shape1,baseMatrix, null, BlendMode.LIGHTEN);
//bmp.bitmapData.draw(shape2,baseMatrix, null, BlendMode.ADD);
//bmp.bitmapData.copyPixels(tmpBmd, baseRect, basePoint, tmpBmd, new Point(0, 0), true);
bmp.bitmapData.applyFilter(bmp.bitmapData, baseRect, basePoint,new BlurFilter(2,2,1));
//bmp2.bitmapData.applyFilter(bmp.bitmapData, baseRect, basePoint,new BlurFilter(2,2,1));
//bmp.bitmapData.draw(shape1,baseMatrix, null, BlendMode.OVERLAY);
bmp.bitmapData.unlock();
/*
//パーティクル追加
if (!flg && flg_2==0 || (mouse_X<0 || mouse_X>stageWidth || mouse_Y<0 || mouse_Y>stageHeight)) return;
if (particles.length > 0) {
//if (getLineLength(new Rectangle(particles[particles.length - 1].xx, particles[particles.length - 1].yy, mouse_X, mouse_Y)) < 3) { ; return false; }
do{
var newX = mouse_X + (Math.random() * 100-50) * flg_2;
var newY = mouse_Y + (Math.random() * 100-50) * flg_2;
}while (newX<0 || newX>stageWidth || newY<0 || newY>stageHeight);
particles.push(new particle(newX,newY, particles.length, particles[particles.length-1]));
particles[0].setObj(particles[particles.length-1]);
} else {
particles.push(new particle(mouse_X,mouse_Y,0));
}
if (particles.length > maxParticles) {
particles.shift();
}
*/
}
function getLineLength(p:Rectangle):Number
{
var vx=p.x-p.width;
var vy=p.y-p.height;
var vl=Math.sqrt(Math.pow(vx,2)+Math.pow(vy,2));
return vl;
}
function getLine(p:Rectangle):Point
{
var vx=p.x-p.width;
var vy=p.y-p.height;
var ts=new Point();
ts.x=vy/vx;
ts.y=p.height-ts.x*p.width;
return ts;
}
function getCrossLine(p:Rectangle):Point
{
var vx=p.x-p.width;
var vy=p.y-p.height;
var ts=new Point();
ts.x=-vx/vy;
ts.y=p.y-ts.x*p.x;
return ts;
}
function clone( arg:* ) :*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(arg);
myBA.position = 0;
return( myBA.readObject() );
}
}
}
class particle{
var col:uint = 0;
var ox:Number=0;
var oy:Number=0;
var ol:Number=0;
var xx:Number=0;
var yy:Number=0;
var _x:Number=0;
var _y:Number=0;
var tx:Number=0;
var ty:Number=0;
var dx:Number=0;
var dy:Number=0;
var dl:Number = 0;
var M:Number=1;
var cnt:Number=0;
var obj:particle;
var cut:Boolean = false;
var mv:uint;
var name:String;
public function particle(... args):void {
ox= xx = args[0];
oy= yy = args[1];
name = args[2];
obj = args[3];
if (args[3]==undefined)obj = this;
var tmptime = new Date();
cnt = tmptime.milliseconds * .002 * Math.PI;
tx = 0;// partest._table[((cnt + partest._HALF_PI) * partest._TWO_PI_SCALE) & (partest._TABLE_SIZE - 1)];
ty = 0;// partest._table[(cnt * partest._TWO_PI_SCALE) & (partest._TABLE_SIZE - 1)];
col = Math.random() * 16777215;
}
}