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

200 small circles

...
@author Thi
Get Adobe Flash player
by Thy 04 Aug 2010
/**
 * Copyright Thy ( http://wonderfl.net/user/Thy )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/ZvEQ
 */

// forked from http://www.emanueleferonato.com/2008/06/07/managing-multiple-balls-collisions-with-flash-as3-version/
package 
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.display.StageQuality;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.ColorTransform;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    
    /**
     * ...
     * @author Thi
     */
    public class Main extends Sprite 
    {
        
        // drawing
        public var circle_shape:Shape
        public var circle_data:BitmapData
        
        // buiding or viewing
        private var building:Boolean
        
        // circle list
        private var num_circles:uint = 200
        private var circles:Vector.<Circle> = new Vector.<Circle>(num_circles, true)
        
        // continers
        private var num_conteiner:uint = 64
        private var conteiners:Vector.<Conteiner> = new Vector.<Conteiner>(num_conteiner, true)
        // conteiner width = 8 pixels (465/64), so it will have 64 conteiners (8²)
        private var num_conteiner_row:uint = 8
        private var conteiner_factor:Number = 6 // 2³ = 8
        
        // temp
        private var i:int, j:int, k:int
        private var circle:Circle, conteiner:Conteiner, list:Vector.<Circle>
        private var circle2:Circle
        
        // collision
        private var X:Number, Y:Number
        private var dx:Number // distance x, or distance x²
        private var dy:Number // same
        private var d:Number // distance²
        private var nx:Number // normal x
        private var ny:Number // same
        private var mx:Number // midPoint x
        private var my:Number // same
        private var dv:Number // sum of (velocity diference*normal)
        private var vx:Number // something about velocity
        private var vy:Number 
        
        // drawing
        private var bitmapdata:BitmapData = new BitmapData(465, 465, true, 0xFFFFFF)
        private var bitmap:Bitmap = new Bitmap(bitmapdata, "auto", true)
        private var rect:Rectangle = new Rectangle(0, 0, 7, 7)
        private var rect465:Rectangle = new Rectangle(0, 0, 465, 465)
        private var point:Point = new Point()
        private var col:ColorTransform = new ColorTransform(1,1,1,.1)
        
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            stage.quality = StageQuality.LOW // less lagg
            
            // listeners
            stage.addEventListener(MouseEvent.CLICK, click)
            stage.addEventListener(Event.ENTER_FRAME, ef)
            building = true
            
            // draw an circle shape and dopy its pixels
            circle_shape = new Shape()
            circle_shape.graphics.lineStyle(1, 0)
            circle_shape.graphics.drawCircle(3, 3, 3)
            circle_data = new BitmapData(7, 7, true, 0xFFFFFF)
            circle_data.draw(circle_shape)
            circle_shape.graphics.clear()
            circle_shape = null
            
            // build circle list
            i = 0
            circles[i] = new Circle(Math.random()*465, Math.random()*465, Math.random()-.5, Math.random())
            while (++i < num_circles)
            {
                circles[i] = new Circle(Math.random() * 465, Math.random() * 465, Math.random() - .5, Math.random())
                circles[i - 1].next = circles[i]
            }
            
            // build conteiner list
            i = 0
            conteiners[i] = new Conteiner()
            while ( ++i < num_conteiner)
            {
                conteiners[i] = new Conteiner()
                conteiners[i - 1].next = conteiners[i]
            }
            
            
        }
        
        private function click(e:MouseEvent):void
        {
            if (building = !building)
            {
                stage.addEventListener(Event.ENTER_FRAME, ef)
            } else 
            {
                stage.removeEventListener(Event.ENTER_FRAME, ef)
            }
        }
        
        
        
        
        private function ef(e:Event):void
        {
            // walk
            walk()
            

                // update conteiner list
                conteiners_update()
                // collisions
                colsisions()
            
            
            
            // draw screen
            addChild(bitmap)
            bitmapdata.colorTransform(rect465,col)
            bitmapdata.lock()
            
            circle = circles[0];
            point.x = circle.x
            point.y = circle.y
            bitmapdata.copyPixels(circle_data, rect, point)
            while (circle = circle.next)
            {
                point.x = circle.x
                point.y = circle.y
                bitmapdata.copyPixels(circle_data, rect, point)
            }
            bitmapdata.unlock()
        }
        
        private function colsisions():void
        {
            // on each conteiner, there's ball colision tests. The fisrt one:
            conteiner = conteiners[0]
            list = conteiner.list
            i = -1
            j = conteiner.list.length
            while (++i < j)
            {
                X = list[i].x
                Y = list[i].y
                k = 0
                while (++k < j)
                {
                    if(i == k) continue;
                    // test collision
                    dx = X - list[k].x
                    dy = Y - list[k].y
                    if (9 > (d = (dx *= dx) + (dy *= dy)) )
                    {
                        solve_collision()
                    }
                }
            }
            
            // others conteiners
            while (conteiner = conteiner.next)
            {
                list = conteiner.list
                i = -1
                j = conteiner.list.length
                while (++i < j)
                {
                    X = list[i].x
                    Y = list[i].y
                    k = i
                    while (++k < j)
                    {
                        // test collision
                        dx = X - list[k].x
                        dy = Y - list[k].y
                        if (9 > (d = (dx *= dx) + (dy *= dy)) )
                        {
                            solve_collision()
                        }
                    }
                }
            }
        }
        
        private function solve_collision():void
        {
            circle = list[i]
            circle2 = list[k]
            // collision
            nx = dx / d // normal
            ny = dy / d
            mx = (X + list[k].x) >> 1 // midpoint
            my = (Y + list[k].y) >> 1
            // positions
            circle.x = mx - nx * 3
            circle.y = my - ny * 3
            circle2.x = mx + nx * 3
            circle2.y = my + ny * 3
            // velocity
            dv = (circle.vx-circle2.vx)*nx + (circle.vy-circle2.vy)*ny
            vx = dv * nx
            vy = dv * ny
            circle.vx -= vx
            circle.vy -= vy
            circle2.vx += vx
            circle2.vy += vy
        }
        
        private function walk():void
        {
            circle = circles[0]
            circle.x += circle.vx*=.99
            circle.y += (circle.vy += .2)
            if (circle.x > 465)
            {
                circle.x = 465
                if (circle.vx > 0)
                {
                    circle.vx *= -.9
                }
            } else if (circle.x < 0)
            {
                circle.x = 0
                if (circle.vx < 0)
                {
                    circle.vx *= -.9
                }
            }
            if (circle.y < 0)
            {
                circle.y = 0
            } else if (circle.y > 465)
            {
                circle.y = 465
                if (circle.vy > 0)
                {
                    circle.vy *= -.9
                }
            }
            while (circle = circle.next)
            {
                circle.x += circle.vx
                circle.y += (circle.vy += .2)
                if (circle.x > 465)
                {
                    circle.x = 465
                    if (circle.vx > 0)
                    {
                        circle.vx *= -.9
                    }
                } else if (circle.x < 0)
                {
                    circle.x = 0
                    if (circle.vx < 0)
                    {
                        circle.vx *= -.9
                    }
                }
                if (circle.y < 0)
                {
                    circle.y = 0
                } else if (circle.y > 465)
                {
                    circle.y --
                    if (circle.vy > 0)
                    {
                        circle.vy *= -.9
                    }
                }
            }
            
        }
        
        private function conteiners_update():void
        {
            // clear conteiners Circle list
            conteiner = conteiners[0]
            conteiner.list = null
            conteiner.list = new Vector.<Circle>()
            while (conteiner = conteiner.next)
            {
                conteiner.list = null
                conteiner.list = new Vector.<Circle>()
            }
            
            // buil conteiner list
            circle = circles[0];
            conteiners[((circle.y >> conteiner_factor) >> 0) * num_conteiner_row + ((circle.x >> conteiner_factor) >> 0)].list.push(circle)
            while (circle = circle.next)
            {
                conteiners[((circle.y >> conteiner_factor) >> 0) * num_conteiner_row + ((circle.x >> conteiner_factor) >> 0)].list.push(circle)
            }
        }
    }
}


//package  
//{
    /**
     * ...
     * @author Thi
     */
    /*public*/ class Circle
    {
        public var x:Number, y:Number
        public var vx:Number, vy:Number
        public var next:Circle
        
        public function Circle(x:Number, y:Number, vx:Number, vy:Number) 
        {
            this.x = x
            this.y = y
            this.vx = vx
            this.vy = vy
        } 
    }
//}


//package  
//{
    /**
     * ...
     * @author Thi
     */
    /*public*/ class Conteiner
    {
        public var list:Vector.<Circle> = new Vector.<Circle>()
        public var length:int
        public var next:Conteiner
        
        public function Conteiner() 
        {
             
        }
    }
//}