メタボールという表現の練習です。
各ピクセルのアルファ値を見て、一定以上なら白、一定以下なら黒に置き換えるという処理をしています。
ピクセルの置き換え処理には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)];
}
}
