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

Metaball

Simple Metaball
Get Adobe Flash player
by takumi0125 18 Jan 2013
/**
 * Copyright takumi0125 ( http://wonderfl.net/user/takumi0125 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/zscM
 */

package  {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.display.GradientType;
    import flash.display.Graphics;
    import flash.display.MovieClip;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.display.Stage;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.filters.BevelFilter;
    import flash.filters.BitmapFilterType;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    
    [SWF(backgroundColor = 0xffffff, frameRate = 60)]
    
    public class Main extends Sprite {
        private var _circlesContainer:Sprite;         //円を配置するSprite
        private var _circles:Vector.<Shape>;          //円を格納するVector
        private var _circleParams:Vector.<Object>;    //円の各値を格納するVector
        private var _criclesBitmapData:BitmapData;    //円を描画するBitmapData
        private var _metaballsBitmap:Bitmap;          //メタボールを描画するBitmap
        private var _metaballsBitmapData:BitmapData;  //メタボールを描画するBitmapData
        private var _thresholdDestPoint:Point;        //2階調化時に使用するPoint (0, 0)
        private var _bitmapRect:Rectangle;            //ビットマップの範囲
        private var _bitmapDataWidth:Number;          //ステージ (ビットマップ)の横幅
        private var _bitmapDataHeight:Number;         //ステージ (ビットマップ)の縦幅
        
        private const _NUM_CIRCLES:uint          =         50;  //円の数
        private const _CIRCLE_MOVE_STEP:uint     =         10;  //円の移動距離の基準値
        private const _CIRCLE_RADIUS:Number      =         60;  //円の半径の基準値
        private const _THRESHOLD:uint            = 0xffffffff;  //2階調化のしきい値
        private const _BITMAP_SIZE_MARGIN:Number =        100;  //ステージ端のフィルタ部分を切り取るためのマージン
        
        //constructor
        public function Main() {
            _init();
        }
        
        //イニシャライズ
        private function _init():void {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT
                        
            //円
            _circlesContainer = new Sprite();
            _circlesContainer.blendMode = BlendMode.ADD;
            _circles = new Vector.<Shape>();
            _circleParams = new Vector.<Object>();
            var circle:Shape, radius:Number;
            for(var i:uint = 0; i< _NUM_CIRCLES; i++) {
                radius = Math.random() * _CIRCLE_RADIUS + _CIRCLE_RADIUS;
                circle = _createCircleShape(radius);
                _circles.push(circle);
                _circlesContainer.addChild(circle);
                
                circle.x = Math.random() * stage.stageWidth;
                circle.y = Math.random() * stage.stageHeight;
                _circleParams.push({ radius: radius, dx: Math.random() * _CIRCLE_MOVE_STEP - _CIRCLE_MOVE_STEP / 2, dy: Math.random() * _CIRCLE_MOVE_STEP - _CIRCLE_MOVE_STEP / 2 });
            }
            
            _thresholdDestPoint = new Point(0, 0);
            
            //addChildするBitmapを生成
            _metaballsBitmap = new Bitmap();
            _metaballsBitmap.x = -(_BITMAP_SIZE_MARGIN >> 1);
            _metaballsBitmap.y = -(_BITMAP_SIZE_MARGIN >> 1);
            addChild(_metaballsBitmap);
            
            //まずサイズを取得してBitmapDataを生成
            _resizeHandler();
            
            //リサイズ処理
            stage.addEventListener(Event.RESIZE, _resizeHandler);
            
            //フレームごとの処理
            addEventListener(Event.ENTER_FRAME, _enterFrameHandler);
        }
        
        //円を生成
        private function _createCircleShape(radius:Number):Shape {
            var circle:Shape = new Shape();
            var circleGraphics:Graphics;
            var matrix:Matrix = new Matrix();
            matrix.createGradientBox(radius * 2, radius * 2, 0, -radius, -radius);
            circleGraphics = circle.graphics;
            circleGraphics.beginGradientFill(GradientType.RADIAL, [ 0xffffff, 0x000000 ], [ 1, 0 ], [ 127, 255 ], matrix);
            circleGraphics.drawCircle(0, 0, radius);
            circleGraphics.endFill();
            circle.blendMode = BlendMode.ADD;
            
            return circle;
        }
        
        //BitmapDataを生成
        private function _createBitmapData():void {
            if(_criclesBitmapData) _criclesBitmapData.dispose();
            _criclesBitmapData = new BitmapData(_bitmapDataWidth, _bitmapDataHeight, true, 0x00000000);
            
            if(_metaballsBitmapData) _metaballsBitmapData.dispose();
            _metaballsBitmapData = new BitmapData(_bitmapDataWidth, _bitmapDataHeight, true, 0x00000000);
            
            _metaballsBitmap.bitmapData = _metaballsBitmapData;
        }
        
        //フレームごとの処理
        private function _enterFrameHandler(e:Event = null):void {
            var circle:Shape, circleParam:Object, radius:Number;
            for(var i:uint = 0; i< _NUM_CIRCLES; i++) {
                circle = _circles[i];
                circleParam = _circleParams[i];
                radius = circleParam.radius;
                
                circle.x += circleParam.dx;
                if(circle.x > _bitmapDataWidth + radius || circle.x < -radius) _circleParams[i].dx *= -1;
                
                circle.y += circleParam.dy;
                if(circle.y > _bitmapDataHeight + radius || circle.y < -radius) _circleParams[i].dy *= -1;
            }
            
            _criclesBitmapData.fillRect(_bitmapRect, 0x00000000);
            _criclesBitmapData.draw(_circlesContainer);
            
            _metaballsBitmapData.fillRect(_bitmapRect, 0xffaacf53);
            _metaballsBitmapData.threshold(_criclesBitmapData, _bitmapRect, _thresholdDestPoint, "<", _THRESHOLD);
        }
        
        //リサイズ処理
        private function _resizeHandler(e:Event = null):void {
            _bitmapDataWidth = stage.stageWidth + _BITMAP_SIZE_MARGIN;
            _bitmapDataHeight = stage.stageHeight + _BITMAP_SIZE_MARGIN;
            _bitmapRect = new Rectangle(0, 0, _bitmapDataWidth, _bitmapDataHeight);
            _createBitmapData();
        }
    }
}