ホーム > タグ > processing

processing

Processingの流体サンプルをasに

[Flash]流体っぽいのを作ろうと思った | blog ViolentCoding
を見てずっと気になっていたんですが、同記事で紹介されている

Fluid \ Learning \ Processing 1.0
をそのままas3に持ってきてみました。

Processingの流体サンプルをそのまま持ってきたもの – wonderfl build flash online

変数宣言が微妙に違うぐらいで、そこを直せば割とあっさり動きました。
最適化してないせいもあるけど、やっぱFlashは重いですね。
変数名なんかはそのままです。
スパイス的な謎の定数が結構あって完全に読み解くのは大変そう。

しかし紹介して下さったe_s_jpさんが作ってるDisplacementMapFilterのバージョンですが、
よくあそこまで膨らませたなぁ、と思います。
凄いす。

僕も、processing.orgから持ってきたコードを、もうちょっと分かりやすく分解して理解してみようと思います。

変数名なんかを自分用に置き換えただけなのはコレ。

package {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.StageQuality;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;

	[SWF(backgroundColor="0x0", width="465", height="465", frameRate="60")]
	public class Main2 extends Sprite {

		public function Main2():void {
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}

		private var pmouseX:Number;
		private var pmouseY:Number;

		private function init(e:Event = null):void {
			removeEventListener(Event.ADDED_TO_STAGE, init);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			stage.quality = StageQuality.MEDIUM;

			addChild(new Bitmap(canvas));

			numCols = width / resolution;
			numRows = height / resolution;

			vsquaresVectors = new Vector.>(numRows + 1);
			vbuffersVectors = new Vector.>(numRows + 1);

			for (var i:int = 0; i < numParticles; i++) {
				particles[i] = new Particle(Math.random() * width, Math.random() * height);
			}

			for (var col:int = 0; col <= numCols; col++) {
				vsquaresVectors[col] = new Vector.(numCols + 1);
				vbuffersVectors[col] = new Vector.(numCols + 1);
				for (var row:int = 0; row <= numRows; row++) {
					vsquaresVectors[col][row] = new Vsquare(col * resolution, row * resolution);
					vbuffersVectors[col][row] = new Vbuffer(col * resolution, row * resolution);
				}

				vsquaresVectors[col].fixed = true;//付け足し
				vbuffersVectors[col].fixed = true;//付け足し
			}

			vsquaresVectors.fixed = true;//付け足し
			vbuffersVectors.fixed = true;//付け足し

			addEventListener(Event.ENTER_FRAME, draw);
		}

		private function draw(e:Event):void {
			mouseX = this.mouseX;
			mouseY = this.mouseY;

			var axvel:int = mouseX - pmouseX;
			var ayvel:int = mouseY - pmouseY;

			mouseXvel = (axvel != mouseXvel) ? axvel : 0;
			mouseYvel = (ayvel != mouseYvel) ? ayvel : 0;

			for (var col:int = 0; col < numCols; col++) {
				for (var row:int = 0; row < numRows; row++) {
					vbuffersVectors[col][row].updatebuf(col, row);
					//何にも無い色の設定
					vsquaresVectors[col][row].color = 32;
				}
			}

			for each(var p:Particle in particles) {
				p.updatepos();
			}

			canvas.lock();//付け足し
			for (col = 0; col < numCols; col++) {
				for (row = 0; row < numRows; row++) {
					vsquaresVectors[col][row].addbuffer(col, row);
					vsquaresVectors[col][row].updatevels(axvel, ayvel);
					vsquaresVectors[col][row].display(col, row);
				}
			}
			canvas.unlock();//付け足し

			pmouseX = mouseX;
			pmouseY = mouseY;
		}

		private function mouseDownHandler(e:Event):void {
			mousePressed = true;
		}

		private function mouseUpHandler(e:Event):void {
			mousePressed = false;
		}
	}

}

import flash.display.BitmapData;
var width:int = 200;
var height:int = 200;
var mousePressed:Boolean;
var mouseX:Number = 0;
var mouseY:Number = 0;
var resolution:int = 5;
var penSize:int = 30;
var numCols:int;
var numRows:int;
var numParticles:int = 7000;
var vsquaresVectors:Vector.>;
var vbuffersVectors:Vector.>;
var particles:Vector. = new Vector.(numParticles, true);
var pcount:int = 0;
var mouseXvel:int = 0;
var mouseYvel:int = 0;
var canvas:BitmapData = new BitmapData(width, height, false, 0x0);

class Particle{
	public function Particle(xIn:Number, yIn:Number) {
		x = xIn;
		y = yIn;
	}

	public var x:Number;
	public var y:Number;
	public var xvel:Number = 0;
	public var yvel:Number = 0;
	public var pos:int = 0;

	public function updatepos():void {
		//var col1:Number;//使われていない
		if (x > 0 && x < width && y > 0 && y < height) {
			var col:int = int(x / resolution);//自身が属しているvsquareを見つける
			var row:int = int(y / resolution);
			var vsquare:Vsquare = vsquaresVectors[col][row];

			var ax:Number = (x % resolution) / resolution;
			var ay:Number = (y % resolution) / resolution;

			xvel += (1 - ax) * vsquaresVectors[col][row].xvel * 0.05;
			yvel += (1 - ay) * vsquaresVectors[col][row].yvel * 0.05;

			xvel += ax * vsquaresVectors[col + 1][row].xvel * 0.05;
			yvel += ax * vsquaresVectors[col + 1][row].yvel * 0.05;

			xvel += ay * vsquaresVectors[col][row + 1].xvel * 0.05;
			yvel += ay * vsquaresVectors[col][row + 1].yvel * 0.05;

			//自身がいるマスの色を濃くする
			vsquare.color += 4;

			x += xvel;
			y += yvel;
		}
		else {
			x = Math.random() * width;
			y = Math.random() * height;
			xvel = 0;
			yvel = 0;
		}

		xvel *= 0.5;
		yvel *= 0.5;
	}
}

class Vbuffer {
	public function Vbuffer(xIn:int, yIn:int) {
		x = xIn;
		y = yIn;
		pressureX = 0;
		pressureY = 0;
	}

	public var x:int;
	public var y:int;
	public var xvel:Number = 0;
	public var yvel:Number = 0;
	public var pressureX:Number = 0;
	public var pressureY:Number = 0;
	public var pressure:Number = 0;

	public function updatebuf(col:int, row:int):void {
		if (col > 0 && col < numCols && row > 0 && row < numRows) {
			pressureX = (
				  vsquaresVectors[col - 1][row - 1].xvel * 0.5
				+ vsquaresVectors[col - 1][row].xvel
				+ vsquaresVectors[col - 1][row + 1].xvel * 0.5
				- vsquaresVectors[col + 1][row - 1].xvel * 0.5
				- vsquaresVectors[col + 1][row].xvel
				- vsquaresVectors[col + 1][row + 1].xvel * 0.5
			);

			pressureY = (
				  vsquaresVectors[col - 1][row - 1].yvel * 0.5
				+ vsquaresVectors[col][row - 1].yvel
				+ vsquaresVectors[col + 1][row - 1].yvel * 0.5
				- vsquaresVectors[col - 1][row + 1].yvel * 0.5
				- vsquaresVectors[col][row + 1].yvel
				- vsquaresVectors[col + 1][row + 1].yvel * 0.5
			);

			pressure = (pressureX + pressureY) * 0.25;
		}
	}
}

import flash.geom.Rectangle;
class Vsquare{

	public function Vsquare(xIn:int, yIn:int) {
		x = xIn;
		y = yIn;
	}

	public var x:int;
	public var y:int;
	public var xvel:Number = 0;
	public var yvel:Number = 0;
	public var color:Number = 0;

	public function addbuffer(col:int, row:int):void {
		if (col > 0 && col < numCols && row > 0 && row < numRows) {
			xvel += (
				  vbuffersVectors[col - 1][row - 1].pressure * 0.5
				+ vbuffersVectors[col - 1][row].pressure
				+ vbuffersVectors[col - 1][row + 1].pressure * 0.5
				- vbuffersVectors[col + 1][row - 1].pressure * 0.5
				- vbuffersVectors[col + 1][row].pressure
				- vbuffersVectors[col + 1][row + 1].pressure * 0.5
			) * 0.25;

			yvel += (
				  vbuffersVectors[col - 1][row - 1].pressure * 0.5
				+ vbuffersVectors[col][row - 1].pressure
				+ vbuffersVectors[col + 1][row - 1].pressure * 0.5
				- vbuffersVectors[col - 1][row + 1].pressure * 0.5
				- vbuffersVectors[col][row + 1].pressure
				- vbuffersVectors[col + 1][row + 1].pressure * 0.5
			) * 0.25;
		}
	}

	public function updatevels(mvelX:int, mvelY:int):void {
		if (mousePressed) {
			var dx:Number = x - mouseX;
			var dy:Number = y - mouseY;

			var dist:Number = Math.sqrt(dy * dy + dx * dx);
			if (dist < penSize) {
				if (dist < 4) dist = penSize;
				var mod:Number = penSize / dist;
				xvel += mvelX * mod;
				yvel += mvelY * mod;
			}
		}

		xvel *= 0.99;
		yvel *= 0.99;
	}

	public function display(i:int, u:int):void {
		var tempColor:uint = 0;

		if (color > 255) color = 255;
		if (i > 0 && i < numCols - 1 && u > 0 && u < numRows - 1) {
			tempColor = (
				  vsquaresVectors[i][u + 1].color
				+ vsquaresVectors[i + 1][u].color
				+ vsquaresVectors[i + 1][u + 1].color * 0.5
			) * 0.4;
			tempColor = int(tempColor + color * 0.5);
		}
		else {
			tempColor = int(color);
		}

		var rgb:uint = tempColor << 16 | tempColor << 8 | tempColor;
		canvas.fillRect(new Rectangle(x, y, resolution, resolution), rgb);
	}
}

Home > Tags > processing

Return to page top