Circle Fitting

Actionscript:
  1. var circs:Array = []
  2. var circNum:int = 600;
  3. addEventListener(Event.ENTER_FRAME, onAdd);
  4. function onAdd(evt:Event):void {
  5.     if (circs.length <circNum){
  6.         makeGrowable();
  7.     }
  8. }
  9.  
  10. function makeGrowable(){
  11.    
  12.     var s:MovieClip = MovieClip(addChild(new MovieClip()));
  13.     s.x = Math.random() * stage.stageWidth;
  14.     s.y = Math.random() * stage.stageHeight;
  15.     with(s.graphics){
  16.         lineStyle(0,0);
  17.         drawCircle(0,0,10);
  18.     }
  19.     s.scaleX = s.scaleY = 0;
  20.     circs.push(s);
  21.     s.addEventListener(Event.ENTER_FRAME, onScaleUp);
  22. }
  23.  
  24. function onScaleUp(evt:Event):void {
  25.     var c:MovieClip = MovieClip(evt.currentTarget);
  26.     c.scaleX = c.scaleY += 0.05;
  27.     for (var i:int = 0; i<circs.length; i++){
  28.         var circ:MovieClip = circs[i];
  29.         if (circ != c){
  30.             var amt:Number = circ.width/2 + c.width/2;
  31.             var dx:Number = circ.x - c.x;
  32.             var dy:Number = circ.y - c.y;
  33.             var dist:Number = Math.sqrt(dx * dx + dy * dy);
  34.             if (amt> dist){
  35.                 c.removeEventListener(Event.ENTER_FRAME, onScaleUp);
  36.                 if (c.scaleX <0.1){
  37.                     if (contains(c)){
  38.                     removeChild(c);
  39.                     }
  40.                 }
  41.             }
  42.         }
  43.        
  44.     }
  45. }

Circle fitting is one of those things I've never bothered to do... today I figured I'd give it a try and this is what I came up with. I posted it on wonderfl:

This entry was posted in Graphics, misc, motion and tagged , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

6 Comments

  1. Posted June 6, 2010 at 12:41 pm | Permalink

    it’s only half-fitting, you don’t move centers ;)

  2. Posted June 13, 2010 at 6:53 pm | Permalink

    Looks familiar but I didn’t think to animate the circles - http://polygeek.com/1804_flex_kissing-circles.

    Nicely done.

  3. Posted July 30, 2010 at 2:31 am | Permalink

    Inspiring… one more time!

  4. Mike
    Posted August 12, 2010 at 1:15 pm | Permalink

    Really cool! and only 45 lines of code :D

    You could add this:
    circs.splice(circs.indexOf(c), 1);
    at line 38 to let it fill in with more smaller circles at the end by removing those circles from the array, not just the stage.

  5. Mike
    Posted August 12, 2010 at 1:26 pm | Permalink

    OOOooo, and if you comment out the conditions for removing a circle at line 36 you get a cool effect too!
    //if (c.scaleX < 0.1){
    // if (contains(c)){
    removeChild(c);
    circs.splice(circs.indexOf(c), 1);
    // }
    //}

    It throws an error once in a while, but I don’t feel like figuring out why.

  6. Sandremss
    Posted August 29, 2011 at 3:39 am | Permalink

    It looks nice but there are a few places where you could do better on performance.
    For starters using the square root calculation is very heavy on the CPU. It would be much better to do instead of:
    var dist:Number = Math.sqrt(dx * dx + dy * dy); DO:
    var dist:Number = dx * dx + dy * dy;

    Then make the check:
    if (amt*amt> dist*dist){

    This is way better for the cpu while having the exact same amount of precision.

    The part where you used with(mc.graphics){
    it is way better to store this variable and make it like:
    var g:Graphics = mc.graphics;
    g.lineStyle…..

    and the part where you divided:
    var amt:Number = circ.width/2 + c.width/2;
    That is also a bit wrong, you see division lays allot more strain on the CPU than multiplication, so it would be better:
    var amt:Number = circ.width*0.5 + c.width*0.5;

    And the big loop its better to pre-store the length property like:
    var l:uint = circs.length; And then use that for the maximum, otherwise the code will look up this property upon every iteration.

    And the onAdd function doesn’t look to be doing allot apart from doing 1 check and then calling a function, remember that just calling a function itself takes CPU so it would be better to put that code inside the onAdd function.

    A small thing but still a 60% less strain on the CPU is making the variable on the loop uint instead of int. And then when you do:
    var circ:MovieClip = circs[i];
    Its better to do:
    var circ:MovieClip = circs[uint(i)];
    Its strange but true: its faster!

    And last but not least I got a question for you: Why use MovieClips? For this you could also use Sprites which have the exact same functionality which you are using here and are less heavy on the CPU.

    Its those little things that can make all the difference in a big project when it comes down to performance, so it makes sense to get it right even when you are working on a little project.

    //Wow, what a beating I gave to a code that’s not even 50 lines…

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*