AS3でメタボール

Filed under AS3



メタボールという表現の練習です。

各ピクセルのアルファ値を見て、一定以上なら白、一定以下なら黒に置き換えるという処理をしています。

ピクセルの置き換え処理にはpaletteMapを使っています。

サンプルはこちら

以下、ソースです。

package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageQuality;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.filters.BlurFilter;
	import flash.geom.Point;

	[SWF(backgroundColor="#ffffff")]
	public class metaball extends Sprite
	{
		private var container:Array;
		private var canvas:BitmapData;
		private var canvas_bmp:Bitmap;
		private var canvas_sp:Sprite;
		private var alpha_array:Array;

		public function metaball()
		{
			// ステージの設定
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			stage.quality = StageQuality.MEDIUM;
			stage.frameRate = 30;

			// 変数の初期化
			canvas_sp = new Sprite;
			canvas = new BitmapData(640, 480, true, 0xff000000);
			canvas_bmp = addChild(new Bitmap(canvas)) as Bitmap;
			onResize();

			// ボールの用意
			container = [];
			for(var i:int=0 ; i<10 ; i++)
			{
				var ball:Ball = new Ball(Math.random()*300 + 200, Math.random()*200 + 200, Math.random()*8-4, Math.random()*8-4, Math.random()*50+30);
				container[i] = canvas_sp.addChild(ball);
			}

			// paletteMapで利用する配列
			// アルファ値が0~149までのピクセルは黒に、150~255までのピクセルは白に塗りなおす
			alpha_array = [];
			for (i = 0; i<150; i++) alpha_array.push(0xff000000);
			for (i = 150; i<=255; i++) alpha_array.push(0xffffffff);

			// イベントの設定
			addEventListener(Event.ENTER_FRAME, onFrame);
			stage.addEventListener(Event.RESIZE, onResize);
		}

		// フレームイベント
		private function onFrame(e:Event):void
		{
			canvas.lock();
			canvas.fillRect(canvas.rect, 0x00000000);

			// 描写
			canvas.draw(canvas_sp);

			// アルファ値によるピクセルの置き換え
			canvas.paletteMap(canvas, canvas.rect, new Point, null, null, null, alpha_array);

			// エフェクト
			canvas.applyFilter(canvas, canvas.rect, new Point, new BlurFilter(8,8,1));
			canvas.unlock();

			// ボールの移動
			for(var i:int=0 ; i<10 ; i++)
			{
				var ball:Ball = container[i] as Ball;
				ball.x += ball.dx;
				ball.y += ball.dy;

				if(ball.x < ball.radius || ball.x > 640-ball.radius) ball.dx *= -1;
				if(ball.y < ball.radius || ball.y > 480-ball.radius) ball.dy *= -1;
			}
		}

		// リサイズイベント
		private function onResize(e:Event=null):void
		{
			canvas_bmp.x = (stage.stageWidth - 640) / 2;
			canvas_bmp.y = (stage.stageHeight - 480) / 2;
		}
	}
}

// ボールクラス
import flash.display.Shape;
import flash.filters.BlurFilter;

class Ball extends Shape
{
	public var radius:Number;
	public var dx:Number;
	public var dy:Number;

	public function Ball(x:Number, y:Number, dx:Number, dy:Number, radius:Number)
	{
		this.x = x;
		this.y = y;
		this.dx = dx;
		this.dy = dy;
		this.radius = radius;

		graphics.beginFill(0x000000);
		graphics.drawCircle(0,0,radius);
		graphics.endFill();
		filters = [new BlurFilter(30,30,1)];
	}
}

Post a Comment

Your email is never published nor shared.