In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

粒子あやつる forked from: 流体パーティクル

--------------------------------------------------------------------------------//

http://wonderfl.net/code/23f89f2a5e8d9df21c8a72210c2a22c9c7490600
via StreamLine
http://gofar2.iobb.net/~htaka/wordpress/archives/953

フォースマップをマウスドラッグでいじります。
粒子はマウスから発生して、フォースマップに従って流れていきます。
スペースキーを押すと粒子表示/フォースマップ編集が切り替わります。
フォースマップ編集時には前に描いたフォースマップはリセットされます。
--------------------------------------------------------------------------------//
package
{
//--------------------------------------------------------------------------------//
//	forked from 流体パーティクル
//	http://wonderfl.net/code/23f89f2a5e8d9df21c8a72210c2a22c9c7490600
//	via StreamLine
//	http://gofar2.iobb.net/~htaka/wordpress/archives/953
//
//	フォースマップをマウスドラッグでいじります。
//	粒子はマウスから発生して、フォースマップに従って流れていきます。
//	スペースキーを押すと粒子表示/フォースマップ編集が切り替わります。
//	フォースマップ編集時には前に描いたフォースマップはリセットされます。
//--------------------------------------------------------------------------------//
	
	import frocessing.display.F5MovieClip2DBmp;
	[SWF(width="465", height="465", frameRate="30")]
	public class ForceMap2 extends F5MovieClip2DBmp
	{
		private var vectorF:VectorField;
		private var strokeColor:Number;
		private var numOfLine:int = 100;
		private var myParticle:Array;
		private var drawflg:int = 0;
		
		public function ForceMap2()
		{
			super();
		}
		
		public function setup():void {
			size(465,465);
			background(0);
			vectorF = new VectorField(this,width/20,height/20,0.1,54655465);
			
			strokeColor = color(150,255,255,20);
			var i:int;
			myParticle = [];
			for(i=0;i < numOfLine;i++){
			  myParticle[i] = new Particle(mouseX,mouseY,0,0,this,vectorF);
			}
			
		}
		
		public function keyPressed():void {
			switch(keyCode){
  				case 32:
  				 if(drawflg==0) {
  				 	drawflg=1;
  				 	vectorF.resetVector();
  				 } else {
  				 	drawflg=0;
  				 }
  				 break;
  			}
		}
		
		public function draw():void {
			
			fill(0, 0, 0, 1);
			noStroke();
		  	rect(0, 0, width, height);
			if(drawflg==0) {
			  	noFill();
				var i:int;
				for(i=0;i<numOfLine;i++) {
					myParticle[i].draw();
				}
				noStroke();
			} else {
				vectorF.drawVector()
			}
		}
	}
}

class VectorField {
	private var numOfCellX:int;
	private var numOfCellY:int;
	private var cellWidth:Number, cellHeight:Number;
	public var cells:Array;
	private var rootMC:F5MovieClip2DBmp;
	private var mox:Number, moy:Number;
	
	public function VectorField(_root:F5MovieClip2DBmp, _numOfCellX:int, _numOfCellY:int, noiseFactor:Number, seed:int) {
		rootMC = _root;
		numOfCellX = _numOfCellX;
		numOfCellY = _numOfCellY;
		cellWidth = rootMC.width / numOfCellX;
		cellHeight = rootMC.height / numOfCellY;
		
		mox = rootMC.mouseX;
		moy = rootMC.mouseY;
		var offsetAX:Number = rootMC.mouseX;
		var offsetAY:Number = rootMC.mouseY;
		var offsetBX:Number = (Math.random()*rootMC.width)-rootMC.width/2;
		var offsetBY:Number = (Math.random()*rootMC.height)-rootMC.height/2;
		
		var i:int;
		var j:int;
		cells = [];
		for(i=0;i<numOfCellX+1; i++) {
			cells[i]=[];
		}
		for(j=0;j<numOfCellY+1;j++) {
			for(i=0;i<numOfCellX+1; i++) {
				cells[i][j] = new Cell(i,j,
					rootMC.noise((i + offsetAX) *noiseFactor, (j+offsetAY) * noiseFactor) - 0.5,
					rootMC.noise((i+offsetBX) *noiseFactor, (j+offsetBY) * noiseFactor ) - 0.5,
					cellWidth, cellHeight);
			}
		}
		
		var gridData:Cell;
		//隣接するグリッドをセットしていく。
		for(j=0;j<numOfCellY+1;j++) {
			for(i=0;i<numOfCellX+1; i++) {
				gridData = cells[i][j];
				if (j > 0) {
					var up:Cell = cells[i][j - 1];//上
					gridData.up = up;
					up.low = gridData;//下
				}
				if (i > 0) {
					var left:Cell = cells[i - 1][j];//左
					gridData.left = left;
					left.right = gridData;//右
				}
				if (j > 0 && i > 0) {
					var upperLeft:Cell = cells[i - 1][j - 1];
					gridData.upperLeft = upperLeft;
					upperLeft.lowerRight = gridData;
				}
				if (j > 0 && i < numOfCellX - 1) {
					var upperRight:Cell = cells[i + 1][j - 1];
					gridData.upperRight = upperRight;
					upperRight.lowerLeft = gridData;
				}
			}
		}
		
		
	}
	
	public function getCell(_posX:Number,_posY:Number):Cell {
		return cells[int(_posX/cellWidth)][int(_posY/cellHeight)];
	}
	public function getVecX(_posX:Number,_posY:Number):Number {
		return cells[int(_posX/cellWidth)][int(_posY/cellHeight)].getVecX;
	}
	public function getVecY(_posX:Number,_posY:Number):Number {
		return cells[int(_posX/cellWidth)][int(_posY/cellHeight)].getVecY;
	}
	
	public function drawGrid():void {
		rootMC.noSmooth();
		rootMC.stroke(128,128);
		var i:int;
		for(i=0;i<numOfCellX;i++) {
			rootMC.line(cellWidth*i,0,cellWidth*i,rootMC.height);
		}
		for(i=0;i<numOfCellY;i++) {
			rootMC.line(0,cellHeight*i,rootMC.width,cellHeight*i);
		}
	}
	
	public function resetVector():void {
		var i:int,j:int;
		for(j=0;j<numOfCellY+1;j++) {
			for(i=0;i<numOfCellX+1; i++) {
				cells[i][j].resetVec();
			}
		}
	}
	public function drawVector():void {
		var drawVectorLength:Number = (cellWidth+cellHeight)/2*10;
		var mnx:Number = rootMC.mouseX;
		var mny:Number = rootMC.mouseY;
		
		rootMC.stroke(0xFFFFFF);
		var i:int,j:int;
		for(j=0;j<numOfCellY+1;j++) {
			for(i=0;i<numOfCellX+1; i++) {
				if(rootMC.isMousePressed){
					cells[i][j].CulcMouseVec(mnx, mny, mnx-mox, mny-moy);
					cells[i][j].updatePressure();
				}
				rootMC.line(cellWidth*i+cellWidth/2, cellHeight*j+cellHeight/2,cellWidth*i+cellWidth/2+cells[i][j].getVecX*drawVectorLength, cellHeight*j+cellHeight/2+cells[i][j].getVecY*drawVectorLength);
			}
		}
		for(j=0;j<numOfCellY+1;j++) {
			for(i=0;i<numOfCellX+1; i++) {
				if(rootMC.isMousePressed)
					cells[i][j].apdateVelocity();
			}
		}
		mox = rootMC.mouseX;
		moy = rootMC.mouseY;
	}
}

	import frocessing.display.F5MovieClip2DBmp;
	import frocessing.math.Random;
	import flash.geom.Rectangle;
	
class BaseGridData {
	
	public var posX:int = 0;
	public var posY:int = 0;
	
	public var x:int = 0;
	public var y:int = 0;
	
	public var vecX:Number = 0;
	public var vecY:Number = 0;
	
	public var pressure:Number = 0;
	
	public var color:Number = 0;
	public var rgb:uint;
	public var rectangle:Rectangle;
}
class NullGridData extends BaseGridData {}
class Cell extends BaseGridData {
	private var cellWidth:Number, cellHeight:Number;
	public function Cell(_posX:int, _posY:int, _vecX:Number, _vecY:Number, _cW:Number, _cH:Number) {
		posX = _posX;
		posY  =_posY;
		vecX = _vecX;
		vecY = _vecY;
		cellWidth = _cW;
		cellHeight = _cH;
		x = posX * cellWidth;
		y = posY * cellHeight;
		rectangle = new Rectangle(x, y, cellWidth, cellHeight);
	}
	
	//すべてのグリッドが8方向に隣接したグリッドを持つわけではないので、
	//空のデータをセットしておく。
	public var upperLeft:BaseGridData = new NullGridData();//左上
	public var up:BaseGridData = new NullGridData();//上
	public var upperRight:BaseGridData = new NullGridData();//右上
	public var left:BaseGridData = new NullGridData();//左
	public var right:BaseGridData = new NullGridData();//右
	public var lowerLeft:BaseGridData = new NullGridData();//左下
	public var low:BaseGridData = new NullGridData();//下
	public var lowerRight:BaseGridData = new NullGridData();//右下	
	
	public function get getVecX():Number {
		return vecX;
	}
	public function get getVecY():Number {
		return vecY;
	}
	
	public function resetVec():void {
		vecX = 0;
		vecY = 0;
	}
	public function CulcMouseVec(mx:Number, my:Number, mvx:Number, mvy:Number):void {
		var dx:Number = mx - posX*cellWidth;
		var dy:Number = my - posY*cellHeight;
		var distance:Number = Math.sqrt(dx*dx+dy*dy);
		var penSize:Number = 40;
		
		if(distance<penSize) {
			if(distance<4) {
				distance=penSize;
			}
			
			var power:Number = 0.005*penSize/distance;
			vecX += mvx * power;
			vecY += mvy * power;
		}
	}
	
	public function updatePressure():void {
		var pressureX:Number = (
			  upperLeft.vecX * 0.5 //左上
			+ left.vecX       //左
			+ lowerLeft.vecX * 0.5 //左下
			- upperRight.vecX * 0.5 //右上
			- right.vecX       //右
			- lowerRight.vecX * 0.5 //右下
		);
		var pressureY:Number = (
			  upperLeft.vecY * 0.5 //左上
			+ up.vecY       //上
			+ upperRight.vecY * 0.5 //右上
			- lowerLeft.vecY * 0.5 //左下
			- low.vecY       //下
			- lowerRight.vecY * 0.5 //右下
		);
		pressure = (pressureX + pressureY) * 0.25;
	}
	
	public function apdateVelocity():void {
			vecX += (
				  upperLeft.pressure * 0.5 //左上
				+ left.pressure       //左
				+ lowerLeft.pressure * 0.5 //左下
				- upperRight.pressure * 0.5 //右上
				- right.pressure       //右
				- lowerRight.pressure * 0.5 //右下
			) * 0.25;
			
			vecY += (
				  upperLeft.pressure * 0.5 //左上
				+ up.pressure       //上
				+ upperRight.pressure * 0.5 //右上
				- lowerLeft.pressure * 0.5 //左下
				- low.pressure       //下
				- lowerRight.pressure * 0.5 //右下
			) * 0.25;
			
			vecX *= 0.99;
			vecY *= 0.99;
		}
}


class Particle {
	public var posX:Number, posY:Number, oldPosX:Number, oldPosY:Number;
	public var velocityX:Number, velocityY:Number;
	public var noLineflg:Boolean = false;
	private var root:F5MovieClip2DBmp;
	private var vectorF:VectorField;
	private var resolution:int = 10;
	
	public function Particle(_px:Number,_py:Number,_velx:Number, _vely:Number, rMC:F5MovieClip2DBmp,vec:VectorField) {
		root = rMC;
		posX = _px;
		posY = _py;
		oldPosX = _px;
		oldPosY = _py;
		velocityX = _velx;
		velocityY = _vely;
		vectorF = vec;
		noLineflg = false;
	}
	
	public function draw():void {
		update();
		if(noLineflg) {
			oldPosX = posX;
			oldPosY = posY;
			noLineflg = false;
		} else {
			root.stroke(0xFFFFFF);
			root.moveTo(posX, posY);
			root.lineTo(oldPosX, oldPosY);
			oldPosX = posX;
			oldPosY = posY;
		}
	}
	public function update():void {
		if( (posX<0)||(posY<0)||(posX>root.width)||(posY>root.height) ) {
			clear();
		} else {
			var absvX:Number = velocityX; //絶対値
			absvX = absvX < 0 ? -absvX : absvX;
			var absvY:Number = velocityY; //絶対値 
			absvY = absvY < 0 ? -absvY : absvY;
			
			if(absvX<0.01&&absvY<0.01) {
				clear();
				return;
			}
			var _cell:Cell = vectorF.getCell(posX, posY);
			var ax:Number = (posX % resolution) / resolution;
			var ay:Number = (posY % resolution) / resolution;
			velocityX += (1 - ax) * _cell.vecX * 0.5;
			velocityY += (1 - ay) * _cell.vecY * 0.5;
			
			velocityX += ax * _cell.right.vecX * 0.5;
			velocityY += ax * _cell.right.vecY * 0.5;
			
			velocityX += ay * _cell.low.vecX * 5;
			velocityY += ay * _cell.low.vecY * 5;
			
			velocityX += vectorF.getVecX(posX,posY);
		    velocityY += vectorF.getVecY(posX,posY);
		    posX += velocityX*5;
		    posY += velocityY*5;
		    
		    velocityX *= 0.6;
		    velocityY *= 0.6;
		}
	}
	
	private function clear():void {
		posX = root.mouseX;
		posY = root.mouseY;
		velocityX = Math.random() * 10 - 5;
		velocityY = Math.random() * 10 - 5;
		noLineflg = true;
	}
	
}