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

blob like loco roco?

drag them!
Get Adobe Flash player
by zob 18 Oct 2016
/**
 * Copyright zob ( http://wonderfl.net/user/zob )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/xQyK
 */

package
{
    import flash.display.*;
    import flash.text.*;
    import flash.events.*;
    import flash.display.Sprite;
    import flash.net.*;
    import flash.filters.*;
    import flash.geom.*;
    import flash.ui.*;
    import flash.system.*;
    import flash.utils.*;
    import com.bit101.components.PushButton;
    import net.hires.debug.Stats;
    
    [SWF(width=465,height=465,backgroundColor=0x000000,frameRate=60)]
    public class BlobWorld extends Sprite
    {
        public static var GRAPHIC_URL:String ="https://www.dropbox.com/s/4yi7pzmfl00cwu2/loco3.png?raw=1";
        private var loader      :Loader;
        private var bmpd        :BitmapData;
        
        private var mouth_bmpd  :BitmapData;
        private var mouth2_bmpd :BitmapData;
        private var eyes_bmpd   :BitmapData;
        private var hair_bmpd   :BitmapData;
        
        private var painter     :MovieClip          = new MovieClip();
        private var blobs       :Vector.<xBlob>     = new Vector.<xBlob>();
        private var blobCount   :int                = 3;
        private var blobsMouth  :Vector.<Bitmap>    = new Vector.<Bitmap>(0, false);
        private var blobsFace   :Vector.<MovieClip> = new Vector.<MovieClip>(0, false);
        private var blobsEyes   :Vector.<MovieClip> = new Vector.<MovieClip>(0, false);
        
        private var show_bone   :Boolean   = false;
        
        public function BlobWorld()
        {
            loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, init);
            loader.load(new URLRequest(GRAPHIC_URL), new LoaderContext(true));
        }
        
        private function init(e:Event = null):void
        {
            addChild(new Bitmap(new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x6699CC)));
            addChild(new Stats());
            bmpd = Bitmap(loader.content).bitmapData;
            mouth_bmpd = new BitmapData(7, 7, true, 0x0);
            mouth_bmpd.copyPixels(bmpd, new Rectangle(17,0,7,7), new Point());
            mouth2_bmpd = new BitmapData(7, 7, true, 0x0);
            mouth2_bmpd.copyPixels(bmpd, new Rectangle(24,0,3,7), new Point(3,0));
            eyes_bmpd = new BitmapData(17, 7, true, 0x0);
            eyes_bmpd.copyPixels(bmpd, new Rectangle(0,0,17,7), new Point());
            hair_bmpd = new BitmapData(25, 13, true, 0x0);
            hair_bmpd.copyPixels(bmpd, new Rectangle(0,8,25,14), new Point());
            
            addChild( painter );
            
            for(var i:int = 0; i<blobCount; i++)
            {
                addBlob(i);
            }
            var panel:Sprite = new Sprite();
            addChild(panel);
            //new PushButton(panel, stage.stageWidth-170, 5, "show bones", showBones).setSize(80, 16);
            //new PushButton(panel, stage.stageWidth-85, 5, "add blob", addMoreBlob).setSize(80, 16);
            
            stage.addEventListener( MouseEvent.MOUSE_DOWN, mouseDown  );
            stage.addEventListener( MouseEvent.MOUSE_MOVE, mouseMove  );
            stage.addEventListener( MouseEvent.MOUSE_UP,   mouseUp    );
            stage.addEventListener( Event.ENTER_FRAME,     processing );
        }
        
        private function addMoreBlob(...arg):void
        {
            addBlob(blobs.length);
        }
        
        private function addBlob(id:int):void
        {
            
            var plastic_organs:Bitmap;
            blobsFace.push(new MovieClip());
            addChild(blobsFace[id]);
            
            // plastic surgery
            plastic_organs = new Bitmap(hair_bmpd);
            plastic_organs.x = -hair_bmpd.width/2; plastic_organs.y = -hair_bmpd.height*0.9;
            blobsFace[id].addChild(plastic_organs);
            //eye
            blobsEyes.push(new MovieClip());
            plastic_organs = new Bitmap(eyes_bmpd);
            blobsEyes[id].addChild(plastic_organs);
            plastic_organs.y = -eyes_bmpd.height/2;
            blobsEyes[id].x = -eyes_bmpd.width/2; blobsEyes[id].y = 3+eyes_bmpd.height/2;
            blobsFace[id].addChild(blobsEyes[id]);
            //mouth
            plastic_organs = new Bitmap(mouth_bmpd);
            plastic_organs.x = -mouth_bmpd.width/2; plastic_organs.y = eyes_bmpd.height+3;
            blobsFace[id].addChild(plastic_organs);
            blobsMouth.push(plastic_organs);
            
            blobs.push(new xBlob(50+Math.random()*365, 100, 30+Math.random()*40, 15));
            blobs[id].blink = Math.random() * 3000;
            blobs[id].update();
            
        }
        
        public function processing(e:Event):void
        {
            var i:int = 0;
            var j:int = 0;

            //calculate diff
            for(i = 0; i<blobs.length; i++)
                blobs[i].setup();
            
            //check contacts
            for(i = 0; i<blobs.length; i++)
                for(j = 0; j <blobs.length; j++)
                    if(i != j)
                        blobs[i].xcontact(blobs[j]);
                        
            //response
            for(i = 0; i<blobs.length; i++)
                blobs[i].update();
            
            
            paint();
        }
        
        public function mouseDown(em:MouseEvent):void
        {
            for(var i:int = 0; i<blobs.length; i++)
                blobs[i].dragStart(mouseX, mouseY);
        }
        
        public function mouseMove(em:MouseEvent):void
        {
            for(var i:int = 0; i<blobs.length; i++)
                blobs[i].dragAt(mouseX, mouseY);
        }
        
        public function mouseUp(em:MouseEvent):void
        {
            for(var i:int = 0; i<blobs.length; i++)
                blobs[i].dragStop(mouseX, mouseY);
        }
        
        private function showBones(...arg):void
        {
            show_bone = !show_bone;
        }
        
        public function paint():void
        {
            // with(){} is slower?
            painter.graphics.clear();
            
            var i:int = 0;
            var j:int = 0;
            var k:int = 0;

            for(i = 0; i<blobs.length; i++)
            {
                painter.graphics.beginFill(0xFFCC32);
                painter.graphics.lineStyle(0.1, 0xFFCC32,1,false,LineScaleMode.HORIZONTAL,CapsStyle.ROUND,JointStyle.ROUND,4);

                blobsFace[i].x = blobs[i].points[0].x;
                blobsFace[i].y = blobs[i].points[0].y;
                blobsFace[i].rotation = Math.atan2(blobs[i].pvn[0].y, blobs[i].pvn[0].x)/(Math.PI/180) - 90;
                if(int((blobs[i].blink+getTimer())%3000)<200) blobsEyes[i].scaleY = ((blobs[i].blink+getTimer())%200)/200;
                
                if(blobs[i].dragging!=-1)
                {
                    blobsMouth[i].bitmapData = mouth2_bmpd;
                } else 
                    blobsMouth[i].bitmapData = mouth_bmpd;
                painter.graphics.moveTo(blobs[i].mid[0].x, blobs[i].mid[0].y);
                for(j = 0;j<blobs[i].points.length;j++)
                {
                    k = (j+1) % blobs[i].points.length;
                    if(show_bone)
                    {
                        painter.graphics.moveTo(blobs[i].points[j].x, blobs[i].points[j].y);
                        painter.graphics.lineTo(blobs[i].points[j].x+blobs[i].pvn[j].x*blobs[i].r, blobs[i].points[j].y+blobs[i].pvn[j].y*blobs[i].r);
                    
                        painter.graphics.moveTo(blobs[i].points[j].x, blobs[i].points[j].y);
                        painter.graphics.lineTo(blobs[i].points[k].x, blobs[i].points[k].y);
                    }
                    painter.graphics.curveTo(blobs[i].points[k].x, blobs[i].points[k].y, blobs[i].mid[k].x, blobs[i].mid[k].y);/**/
                }
                painter.graphics.endFill();
            }
        }
    }
}

class xBlob
{
    public var points   :Vector.<Dot>    = new Vector.<Dot>(0, false);
    public var mid      :Vector.<Dot>    = new Vector.<Dot>(0, false);
    public var ppoints  :Vector.<Dot>    = new Vector.<Dot>(0, false);
    public var disp     :Vector.<Dot>    = new Vector.<Dot>(0, false);
    public var vlen     :Vector.<Number> = new Vector.<Number>(0, false);
    public var fdiv     :Vector.<Number> = new Vector.<Number>(0, false);
    public var ad       :Vector.<Dot>    = new Vector.<Dot>(0, false);
    public var d        :Vector.<Dot>    = new Vector.<Dot>(0, false);
    public var pvn      :Vector.<Dot>    = new Vector.<Dot>(0, false);

    public var nc       :Number  = 15;
    public var r        :Number  = 30;
    public var comp     :Number  = 0.033;
    public var sd       :Number  = 0.3;
    public var fa       :Number  = 0.9;
    public var g        :Number  = 0.5;

    public var OArea    :Number  = 0;

    public var left     :Boolean = false;
    public var right    :Boolean = false;

    public var clipping :Dot     = new Dot(0,0);
    public var dragging :int     = -1;
    
    public var mouse_x  :Number  = 0;
    public var mouse_y  :Number  = 0;
    
    // extra for rectangle (not working)
    public var w        :Number  = r*2;
    public var h        :Number  = r*2;
    public var cp       :Dot;
    public var org      :Vector.<Dot>    = new Vector.<Dot>(0, false);
    public var olen     :Vector.<Number> = new Vector.<Number>(0, false);
    
    public var blink    :int     = 0;

    public function xBlob(cx:Number=0, cy:Number=0, size:Number=30, nodeCount:Number=15)
    {
        cp = new Dot(cx, cy);
        r = size;
        nc = nodeCount;
        var i:int = 0;
        var j:int = 0;
        var px:Number;
        var py:Number;
        var vx:Number = 0;
        var vy:Number = 0;

        clipping.l = 0;
        clipping.r = 465;
        clipping.t = 0;
        clipping.b = 465;
        
        for (; i<nc; i++)
        {
            px = r*Math.cos(i/nc*Math.PI*2)+cx;
            py = r*Math.sin(i/nc*Math.PI*2)+cy;
            fullpush(px,py);
        }
        
        for(i=0; i < points.length; i++)
        {
            j = (j+1)%points.length;
            vx = points[j].x - points[i].x;
            vy = points[j].y - points[i].y;
            vlen.push(Math.sqrt(vx*vx+vy*vy));
        }
        OArea=calcArea();
    }
    
    public function fullpush(px:Number, py:Number):void
    {
        var tx:Number = px - cp.x;
        var ty:Number = py - cp.y;
        var xlen:Number = Math.sqrt(tx * tx + ty * ty);
        points.push(new Dot(px,py));
        org.push(new Dot(tx,ty));
        disp.push(new Dot(0, 0));
        fdiv.push(0);
        ppoints.push(new Dot(0, 0));
        mid.push(new Dot(0, 0));
        d.push(new Dot(0, 0));
        ad.push(new Dot(0, 0));
        pvn.push(new Dot(tx/xlen, ty/xlen));
        olen.push(xlen);
    }

    public function update():void
    {
        var NArea:Number = calcArea();
        var i:int = 0;
        var j:int = 0;
        var p:Number = (NArea - OArea)*comp/nc;
        var n1:Dot;
        var n2:Dot;
        var np:Dot;
        var n:Dot;
        var nn:Dot;
        var vn:Dot;
        var fx:Number=0;
        var fy:Number=0;
        var dx:Number=0;
        var dy:Number=0;
        var da:Number=0;
        var px:Number=0;
        var py:Number=0;
        var gx:Number =0;
        var gy:Number = 0;
        var vx:Number = 0;
        var vy:Number = 0;
        var xlen:Number = 0;

        for(i = 0; i < points.length; i++)
            if(fdiv[i] > 0)
            {

                gx = disp[i].x / fdiv[i];// / 2;
                gy = disp[i].y / fdiv[i];// / 2;

                points[i].x = points[i].x + gx;
                points[i].y = points[i].y + gy;

                points[i].vx = points[i].vx + gx;
                points[i].vy = points[i].vy + gy;
                
                disp[i].x = 0.0;
                disp[i].y = 0.0;
                
                fdiv[i] = 0;

            }

        for (i=0; i<points.length; i++)
        {
            j = (i+1)%points.length;
            n1 = points[i];
            n2 = points[j];
            
            fx = (n1.x - n2.x) * sd;
            fy = (n1.y - n2.y) * sd;
            
            n1.vx -= fx;
            n1.vy -= fy;
            fdiv[i]   = fdiv[i]   + 1;
            n2.vx += fx;
            n2.vy += fy;
            fdiv[j]   = fdiv[j]   + 1;

        }

        for (i=0; i<points.length; i++)
        {
            np = points[(points.length+i-1)%points.length];
            n = points[i];
            nn = points[(i+1)%points.length];
            vn = vertexNormal(np,n,nn);
            pvn[i].x = vn.x;
            pvn[i].y = vn.y;
            n.vx += vn.x*p;
            n.vy += vn.y*p;
        }

        var pp:Dot;
        for (i = 0; i<nc; i++)
        {
            if (i == dragging)
            {
                points[i].x = mouse_x;
                points[i].y = mouse_y;
                points[i].vx = 0;
                points[i].vy = 0;
            } else {
                n = points[i];
                pp = ppoints[i];

                pp.x = n.x;
                pp.y = n.y;
                pp.vx = n.vx;
                pp.vy = n.vy;

                n.vy += g;
                
                if (isNaN(n.vx))
                {
                    trace("NaN");
                    break;
                }

                n.x += n.vx *= fa;
                n.y += n.vy *= fa;

                if (n.x<clipping.l)
                {
                    n.x=clipping.l;
                    n.vx=0;
                }
                if (n.x>clipping.r)
                {
                    n.x=clipping.r;
                    n.vx=0;
                }
                if (n.y<clipping.t)
                {
                    n.y=clipping.t;
                    n.vy=0;
                }
                if (n.y>clipping.b)
                {
                    n.y=clipping.b;
                    n.vy=0;
                }
            }
        }
        
        for (i = 0; i < points.length; i++)
        {
            j = (i + 1) % points.length;
            vx=points[j].x-points[i].x;
            vy=points[j].y-points[i].y;
            xlen=Math.sqrt(vx*vx+vy*vy);

            if (xlen>0)
            {
                ad[i].x=vx/xlen;
                ad[i].y=vy/xlen;
            }
        }

        if (left)
        {
            for (i = 0; i < nc; i++)
            {
                j = (i + 1) % nc;
                points[j].x-=2*ad[i].x;
                points[j].y-=2*ad[i].y;
            }
        }
        if (right)
        {
            for (i = 0; i < nc; i++)
            {
                points[i].x+=2*ad[i].x;
                points[i].y+=2*ad[i].y;
            }
        }

        for (i=0; i<points.length; i++)
        {
            j = (i+1) % points.length;
            mid[i].x = (points[i].x+points[j].x)/2;
            mid[i].y = (points[i].y+points[j].y)/2;
        }
    }
    
    public function setup():void
    {
        var i    :int = 0;
        var k    :int;
        var vx   :Number = 0;
        var vy   :Number = 0;
        var len  :Number = 0;
        var diff :Number = 0;
        var nx   :Number = 0;
        var ny   :Number = 0;
        var ux   :Number = 0;
        var uy   :Number = 0;
        
        for(; i < points.length; i++)
        {
            k = (i + 1) % points.length;
            
            vx = points[k].x - points[i].x;
            vy = points[k].y - points[i].y;
            len = Math.sqrt(vx * vx + vy * vy);
            diff = vlen[i] - len;

            nx = vx / len;
            ny = vy / len;

            ux = diff * nx;
            uy = diff * ny;

            d[i].x = nx;
            d[i].y = ny;
        }
    }
    
    public function inside(p0:Number, p1:Number, p2:Number):Boolean
    {
        if(p0>p1 && p0<p2)
            return true;
        return false;
    }
    
    public function inBetween(p0:Dot, p1:Dot, p2:Dot):Boolean
    {
        if(inside(p0.x, p1.x, p2.x) || inside(p0.x, p2.x, p1.x) || inside(p0.y, p1.y, p2.y) || inside(p0.y, p2.y, p1.y))
            return true;
        return false;
    }
    
    public function xcontact(blob:xBlob):void
    {
        var i:int = 0;
        var j:int;
        var l:int = 0;
        var k:int = 0;
        var o:int = 0;
        var sx:Number = 0;
        var sy:Number = 0;
        var angle:Number = 0;
        var cosa:Number = 0;
        var sina:Number = 0;
        var x1:Number = 0;
        var y1:Number = 0;
        var vx1:Number = 0;
        var yb:Number = 0;
        var vy1:Number = 0;
        var yy1:Number = 0;
        var adj:Number = 0;
        
        var gx   :Number = 0;
        var gy   :Number = 0;
        var cx   :Number = 0;
        var cy   :Number = 0;
        var dp   :Number = 0;
        var f1   :Number = 0;
        var f2   :Number = 0;
        var vx   :Number = 0;
        var vy   :Number = 0;
        var len  :Number = 0;
        var diff :Number = 0;

        var bvx:Number = 0;
        var bvy:Number = 0;
        var blen:Number = 0;
        var pavn:Dot = new Dot(0, 0);

        for(i = 0; i < points.length; i++) {
            l = (i+1) % points.length;
            if(blob.inPoly(points[i].x, points[i].y))
            {
                for(o = 0; o < blob.points.length; o++) {
                    k = (o+1) % blob.points.length;
                    //if(inBetween(points[o], points[i], points[l]) || ){
                        sx = points[i].x-blob.points[o].x;
                        sy = points[i].y-blob.points[o].y;
                        angle = Math.atan2(blob.points[k].y-blob.points[o].y,blob.points[k].x-blob.points[o].x);
                        cosa = Math.cos(angle);
                        sina = Math.sin(angle);
                        x1 = sx*cosa+sy*sina;
                        y1 = sy*cosa-sx*sina;
                        vx = points[i].x - blob.points[o].x;
                        vy = points[i].y - blob.points[o].y;
                        
                        dp = vx * blob.d[o].x + vy * blob.d[o].y;

                        bvx = blob.points[k].x-blob.points[o].x;
                        bvy = blob.points[k].y-blob.points[o].y;
                        
                        blen = Math.sqrt(bvx*bvx+bvy*bvy);

                        pavn.x = points[i].x + pvn[i].x * r;
                        pavn.y = points[i].y + pvn[i].y * r;

                        if (y1>0 && intersected(points[i], pavn, blob.points[k], blob.points[o])) {
                            cx = blob.points[o].x + dp * blob.d[o].x;
                            cy = blob.points[o].y + dp * blob.d[o].y;
                            
                            vx = points[i].x - cx;
                            vy = points[i].y - cy;
                            
                            len = Math.sqrt(vx * vx + vy * vy);
                            
                            diff = 4 /4;
                            gx = diff * vx;
                            gy = diff * vy;

                            disp[i].x = disp[i].x - gx;
                            disp[i].y = disp[i].y - gy;
                            fdiv[i] = fdiv[i] + 1;

                            f1 = dp / blen;
                            f2 = 1.0 - f1;

                            blob.disp[j].x = blob.disp[j].x + f2 * gx;
                            blob.disp[j].y = blob.disp[j].y + f2 * gy;
                            blob.fdiv[j] = blob.fdiv[j] + 1;
                            blob.disp[k].x = blob.disp[k].x + f1 * gx;
                            blob.disp[k].y = blob.disp[k].y + f1 * gy;
                            blob.fdiv[k] = blob.fdiv[k] + 1;
    
                            points[i].vx = vx1*cosa-vy1*sina;
                            points[i].vy = vy1*cosa+vx1*sina;
                            points[i].x += points[i].vx;
                            points[i].y += points[i].vy;
                            break;
                        }
                    }
                //}
            }
        }
    }

    public function inPoly(px:Number, py:Number):Boolean
    {
        var i:int, j:int;
        var c:Boolean = false;
        for (i = 0, j = points.length-1; i < points.length; j = i++) {
        if ( ((points[i].y>py) != (points[j].y>py)) && (px < (points[j].x-points[i].x) * (py-points[i].y) / (points[j].y-points[i].y) + points[i].x) )
            c = !c;
        }
        return c;
    }
    
    public function dragStart(m_x:Number, m_y:Number):void
    {
        mouse_x = m_x;
        mouse_y = m_y;
        
        var distance:Number = 15;
        var target:int = -1;
        var curr_distance:Number = 0;
        var vx:Number = 0;
        var vy:Number = 0;
        for (var i:int = 0; i<points.length; i++)
        {
            vx = points[i].x - m_x;
            vy = points[i].y - m_y;
            curr_distance = Math.sqrt(vx*vx+vy*vy);
            if(curr_distance<distance)
            {
                distance = curr_distance;
                target = i;
            }
        }
        dragging = target;
    }
    
    public function dragAt(m_x:Number, m_y:Number):void
    {
        if(dragging>=0)
        {
            mouse_x = m_x;
            mouse_y = m_y;
        }
    }
    
    public function dragStop(m_x:Number, m_y:Number):void
    {
        dragging = -1;
    }

    private function calcArea():Number
    {
        var a:Number=0;
        var n1:Dot;
        var n2:Dot;
        var i:int=0;
        //a = 0;
        for (i=0; i<points.length; i++)
        {
            n1=points[i];
            n2 = points[(i+1)%points.length];
            a += (n1.x-n2.x)*(n1.y+n2.y);
        }
        return a/2;
    }
    
    public function intersected(p1:Dot, p2:Dot, p3:Dot, p4:Dot):Boolean
    {
        var s1_x:Number, s1_y:Number, s2_x:Number, s2_y:Number;
        s1_x = p2.x - p1.x;     s1_y = p2.y - p1.y;
        s2_x = p4.x - p3.x;     s2_y = p4.y - p3.y;
    
        var s:Number, t:Number;
        s = (-s1_y * (p1.x - p3.x) + s1_x * (p1.y - p3.y)) / (-s2_x * s1_y + s1_x * s2_y);
        t = ( s2_x * (p1.y - p3.y) - s2_y * (p1.x - p3.x)) / (-s2_x * s1_y + s1_x * s2_y);
    
        if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
        {
            return true;
        }
    
        return false;
    }
    
    private function vertexNormal(np:Dot, n:Dot, nn:Dot):Dot
    {
        var dpx:Number=np.x-n.x;
        var dpy:Number=np.y-n.y;
        var dnx:Number=nn.x-n.x;
        var dny:Number=nn.y-n.y;

        var nx:Number=-dny;
        var ny:Number=dnx;
        var na:Number=Math.sqrt(nx*nx+ny*ny);
        if (na==0)
        {
            nx=1;
            ny=0;
        } else {
            nx/=na;
            ny/=na;
        }

        //rotate dp anti-clockwise by 90C
        var px:Number=dpy;
        var py:Number=-dpx;
        var pa:Number=Math.sqrt(px*px+py*py);
        if (pa==0)
        {
            px=1;
            py=0;
        } else {
            px/=pa;
            py/=pa;
        }

        var fx:Number=nx+px;
        var fy:Number=ny+py;
        var fa:Number=Math.sqrt(fx*fx+fy*fy);
        if (fa==0)
        {
            fx=1;
            fy=0;
        } else {
            fx/=fa;
            fy/=fa;
        }
        
        return new Dot(fx,fy);
    }
}

class Dot {
    public var x:Number = 0;
    public var y:Number = 0;
    public var tx:Number = 0;
    public var ty:Number = 0;
    public var vx:Number = 0;
    public var vy:Number = 0;
    public var nx:Number = 0;
    public var ny:Number = 0;
    public var dx:Number = 0;
    public var dy:Number = 0;
    public var fx:Number = 0;
    public var fy:Number = 0;
    public var angle:Number = 0;
    public var size:Number = 0;
    public var speed:Number = 0;
    public var m:Number = 0;
    public var rad:Number = 0;
    public var a:Number = 0;
    public var drag:Boolean = false;
    public var l:Number = 0;
    public var r:Number = 0;
    public var t:Number = 0;
    public var b:Number = 0;
    
    public function Dot(px:Number=0,py:Number=0) {
        x = px;
        y = py;
        tx = x;
        ty = y;
    }
}