forked from: forked from: code on 2008-12-17
**********************************************
title:2D metaball + bump-map + textinput
forked by yonedashigeru
http://wab.cc/
**********************************************
----------------------------------------
2D metaball + bump-map
written by keim +Si+
licence: PD
----------------------------------------
//**********************************************
// title:2D metaball + bump-map + textinput
//
// forked from oppei
// forked by yonedashigeru
//
// http://wab.cc/
//
//**********************************************
// forked from oppei's forked from: code on 2008-12-17
//----------------------------------------
// 2D metaball + bump-map
// written by keim +Si+
// licence: PD
//----------------------------------------
package {
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.filters.*;
import flash.text.*;
public class main_bump extends Sprite
{
static public var base:BitmapData; // base image
static private var pixels:BitmapData; // displaying image
static private var screen:Bitmap; // displaying image
static private var balls:Array; // meta-balls array
static private var swidth:int=467;
static private var sheight:int=467;
static private var ptBallsCenter:Point = new Point(); // balls center position
static private var matFace:Matrix = new Matrix(); // face matrix
static private var conv:ConvolutionFilter; // convolution filter for bump
static private var colt:ColorTransform; // color matrix for cutout
static private var face:BitmapData; // face image
public function main_bump()
{
var i:int;
var j:int;
// bitmaps
base = new BitmapData(swidth, sheight, false);
pixels = new BitmapData(swidth, sheight, false);
screen = new Bitmap(pixels);
// create filter instance
colt = new ColorTransform(32,4,1.6,1,-1280,-320,-320,0);
conv = new ConvolutionFilter(3, 3, [-2.5,-2.5,0,-2.5,0,2.5,0,2.5,2.5], 1, 128);
// draw meta-ball gradation
ball.pat = new BitmapData(ball.R*2,ball.R*2,false,0);
var shp:Shape = new Shape();
var mtx:Matrix = new Matrix();
mtx.createGradientBox(ball.R*2,ball.R*2,0,0);
shp.graphics.beginGradientFill(GradientType.RADIAL, [0x808080,0x000000], [1,1], [0,255], mtx);
shp.graphics.drawRect(0,0,ball.R*2,ball.R*2);
shp.graphics.endFill();
base.draw(shp);
base.draw(shp, null, null, BlendMode.MULTIPLY);
var blr:BlurFilter = new BlurFilter(16, 16);
ball.pat.applyFilter(base, ball.pat.rect, ball.pat.rect.topLeft, blr);
// draw face
/*
face = new BitmapData(48, 16, true, 0x00000000);
var tf:TextField = new TextField();
tf.width = 48;
tf.height = 16;
//tf.defaultTextFormat = new TextFormat("MS Gothic", 12, 0x000000, null, null, null, null, null, TextFormatAlign.CENTER);
tf.text = "+---+";
face.draw(tf);
// create ball instance
balls = new Array(16);
for (i=0; i<balls.length; i++) { balls[i] = new ball(10*i, 10*i); }
*/
var tf:TextField = new TextField();
tf.defaultTextFormat = new TextFormat("MS Gothic", 12, 0x000000, null, null, null, null, null, TextFormatAlign.LEFT);
tf.text = "yoneda";
tf.autoSize = TextFieldAutoSize.LEFT;
var txt_bmd:BitmapData = new BitmapData(swidth, sheight);
var tmp_mt:Matrix = new Matrix();
var tmp_scale:Number = swidth / tf.width;
tmp_mt.scale(tmp_scale, tmp_scale);
txt_bmd.draw(tf, tmp_mt);
var pixelW:int = 10;
var pixelH:int = 10;
balls = new Array();
for(i=0; i<sheight/pixelH; i++)
{
for(j=0; j<swidth/pixelW; j++)
{
if(txt_bmd.getPixel32(pixelW*j, pixelH*i) == 0xff000000)
{
var tmp_ary:Array = new Array();
var tmp_01_ball:ball = new ball(pixelW*j, pixelH*i);
balls.push(tmp_01_ball);
var tmp_02_ball:ball = new ball(pixelW*j, pixelH*i, [tmp_01_ball]);
balls.push(tmp_02_ball);
var tmp_03_ball:ball = new ball(pixelW*j, pixelH*i, [tmp_01_ball]);
balls.push(tmp_03_ball);
}
}
}
// set sprite/event
addChild(screen);
stage.quality = StageQuality.HIGH;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.doubleClickEnabled = true;
stage.addEventListener(Event.ENTER_FRAME, _onEnterFrame);
stage.addEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
stage.addEventListener(MouseEvent.DOUBLE_CLICK, _onDoubleClick);
//addChild(new Bitmap(txt_bmd));
}
private function _onEnterFrame(event:Event) : void
{
var i:int, j:int;
// execute
ball.mouseX = mouseX;
ball.mouseY = mouseY;
for (i=0; i<balls.length; i++) { ball(balls[i]).gravity(); ball(balls[i]).interact();}
//for (i=0; i<balls.length-1; i++) for (j=i+1; j<balls.length; j++) { ball(balls[i]).interact(ball(balls[j])); }
for (i=0; i<balls.length; i++) { ball(balls[i]).run(); }
calcBallCenter();
// draw
base.fillRect(pixels.rect,0x000000);
for (i=0; i<balls.length; i++) { ball(balls[i]).draw(base); }
pixels.applyFilter(base, pixels.rect, pixels.rect.topLeft, conv);
base.colorTransform(pixels.rect, colt);
pixels.draw(base,null,null,BlendMode.MULTIPLY);
//drawFace();
}
private function _onMouseDown(event:MouseEvent) : void
{
for (var i:int=0; i<balls.length; i++) { ball(balls[i]).check_hold(event.localX, event.localY); }
}
private function _onMouseUp(event:MouseEvent) : void
{
for (var i:int=0; i<balls.length; i++) { ball(balls[i]).hold = false; }
}
private function _onDoubleClick(event:MouseEvent) : void
{
for (var i:int=0; i<balls.length; i++) { ball(balls[i]).blast(); }
}
private function calcBallCenter() : void
{
ptBallsCenter.x = 0;
ptBallsCenter.y = 0;
for (var i:int=0; i<balls.length; i++) { ptBallsCenter.offset(balls[i].x, balls[i].y); }
var dv:Number=1/balls.length;
ptBallsCenter.x *= dv;
ptBallsCenter.y *= dv;
}
private function drawFace() : void
{
matFace.identity();
matFace.translate(-24, -8);
matFace.rotate(Math.atan2(balls[0].y-ptBallsCenter.y, balls[0].x-ptBallsCenter.x));
matFace.translate(ptBallsCenter.x, ptBallsCenter.y);
pixels.draw(face, matFace, null, null, null, true);
}
}
}
import flash.display.*;
import flash.geom.*;
class ball
{
static internal var pat:BitmapData;
static internal var R :Number = 20; // radius
static internal var K :Number = 0.1; // spring
static internal var K2:Number = 0.15; // dumper
static internal var D :Number = 48; // comfortable distance
static internal var G :Number = 1.4; // gravity
static internal var HR:Number = 32*32; // holding radius ^ 2
internal var mat:Matrix = new Matrix();
internal var ax:Number = 0;
internal var ay:Number = 0;
internal var vx:Number = 0;
internal var vy:Number = 0;
internal var x:Number = 0;
internal var y:Number = 0;
private var initX:Number = 0;
private var initY:Number = 0;
private var other_ary:Array;
internal var hold:Boolean = false;
internal var holdX:Number = 0;
internal var holdY:Number = 0;
static internal var mouseX:Number = 0;
static internal var mouseY:Number = 0;
function ball(initX:Number, initY:Number, other_ary:Array = null) {
this.initX = initX;
this.initY = initY;
this.other_ary = other_ary;
trace("initX = " + initX);
trace("initY = " + initY);
reset();
}
internal function reset() : void {
x = Math.random()*R+120;
y = Math.random()*R;
vx = 0;
vy = 0;
ax = 0;
ay = 0;
hold = false;
}
internal function run() : void {
if (hold) {
x = mouseX+holdX;
y = mouseY+holdY;
} else {
x += vx + ax * 0.5;
y += vy + ay * 0.5;
vx += ax - vx * K2;
vy += ay - vy * K2;
//if (y>240) { vy=-vy; y=480-y; }
//if (x<0) { vx=-vx; x=-x; } else
//if (x>240) { vx=-vx; x=480-x; }
}
mat.identity();
mat.translate(x-R, y-R);
}
internal function draw(base:BitmapData) : void {
base.draw(pat, mat, null, BlendMode.ADD);
}
internal function gravity() : void {
ax = 0;
ay = G;
}
internal function interact() : void {
//var dx:Number = b.x - x;
//var dy:Number = b.y - y;
var dx:Number;
var dy:Number;
var l:Number;
var f:Number;
if(!other_ary)
{
dx = initX - x;
dy = initY - y;
l = Math.sqrt(dx*dx+dy*dy);
f = (D-l)*K/l;
dx *= f;
dy *= f;
ax -= dx;
ay -= dy;
//b.ax += dx;
//b.ay += dy;
}else{
for(var i:int=0; i<other_ary.length; i++)
{
dx = (initX + other_ary[i].x)/2 - x;
dy = (initY + other_ary[i].y)/2 - y;
l = Math.sqrt(dx*dx+dy*dy);
f = (D-l)*K/l;
dx *= f;
dy *= f;
ax -= dx;
ay -= dy;
other_ary[i].ax += dx;
other_ary[i].ay += dy;
}
}
}
internal function check_hold(x_:Number, y_:Number) : void {
holdX = x - x_;
holdY = y - y_;
if (holdX*holdX+holdY*holdY < HR) { hold = true; }
}
internal function blast() : void {
x = Math.random()*240;
y = Math.random()*240;
}
}