BIT-101 Particle class in AS3

/*Public Properties:


vx:Number – the velocity on the x axis. default is 0
vy:Number – the velocity on the y axis. default is 0
damp:Number – a pseudo-friction value. 1.0 is no friction. Usual values are between 0.9 and 1.0. default is 0.9
bounce:Number – how much the particle will bounce from a wall. -1.0 will bounce with same force it hit with.

default is -0.5

grav:Number – how much velocity is added to vy each frame. Usual values are 0.0 to 2.0. default is 0
maxSpeed:Number – maximum allowed speed in any direction for a particle.

default is Number.MAX_VALUE (essentially infinity or no limit)

wander:Number – gives particle a random motion. numbers between 0 and 5 works well. default is 0
draggable:Boolean – if true, drag and throw is possible on the particle
edgeBehavior:String – determines behavior when particle hits an edge of the world.

Can be set to "wrap", "bounce", or "remove"
        wrap causes the particle to disappear and appear on the opposite edge of the space
        bounce causes the particle to bounce off the edge at a speed determined by the bounce property
        remove causes the particle to be permanently deleted if it leaves the space.

turnToPath:Boolean – if true, particle will turn towards the direction it is moving in.

Public Methods:


setBounds(bounds:Object)

- sets the "walls" of the universe in which the particle will be able to travel
- arguments:
    bounds. an object containing properties: xMin, xMax, yMin, yMax.
            you can directly use the object returned from the method getBounds().
            default values are the Stage dimensions.

gravToMouse(bGrav:Boolean [, force:Number])

- causes the particle to gravitate towards the mouse. it is advised that us use maxSpeed along with this,
  as this method can create near infinite particle speeds.
- arguments:
    bGrav. if true, particle will gravitate towards mouse. if false, it won't. default is false.
    force. the gravitational force applied to the particle.
           generally high numbers of 1000 or more are used. default is 1000

springToMouse(bSpring:Boolean [, force:Number])

- causes the particle to spring to the mouse
- arguments:
    bSpring. if true, particle will spring to the mouse. if false, it won't. default is false.
    force. the strength of the spring. generally numbers less than 1 are used. default is 0.1

repelMouse(bRepel:Boolean [, force:Number, minDist:Number])

- causes the particle to spring away from the mouse
- arguments:
    bRepels. if true, particle will spring away from the mouse. if false it won't.
    force. the strength of the spring action. generally numbers less than 1 are used. default is 0.1
    minDist. the distance in pixels from the mouse that the particle will attempt maintain.
             default is 100
- returns:
    the index number of the point added (can be used to remove the point)

addSpringPoint(x:Number, y:Number [, force:Number])

- adds a stationary point to which the particle will spring. any number of points can be added,
  but the result will be that the particle will spring to an point which is the average of all points.
- arguments:
    x, y. the point to which the particle will spring.
    force. the strength of the spring. default is 0.1
- returns:
    the index number of the point added (can be used to remove the point)

addGravPoint(x:Number, y:Number [, force:Number])

- adds a stationary point to which the particle will try to gravitate. any number of points can be added.
- arguments:
    x, y. the point to which the particle will gravitate.
    force. the gravitational force of the point. default is 1000
- returns:
    the index number of the point added (can be used to remove the point)

addRepelPoint(x:Number, y:Number [, force:Number, minDist:Number])

- adds a stationary point which the particle will try to spring away from.
  any number of points can be added.
- arguments:
    x, y. the point the particle will try to avoid.
    force. the force of the spring. default is 0.1
    minDist. the distance in pixels from the point that the particle will try to maintain. default is 100
- returns:
    the index number of the point added (can be used to remove the point)

addSpringClip(clip:MovieClip [, force:Number])

- designates a movie clip to which the particle will spring towards. any number of clips can be added.
- arguments:
    clip. a movie clip towards which the particle will spring.
    force. the strength of the spring. default is 0.1
- returns:
    the index number of the clip added (can be used to remove the clip from the list)

addGravClip(clip:MovieClip [, force:Number])

- designates a movie clip to which the particle will gravitate. any number of clips can be added.
- arguments:
    clip. a movie clip towards which the particle will spring.
    force. the strength of the gravitation. default is 1000
- returns:
    the index number of the clip added (can be used to remove the clip from the list)

addRepelClip(clip:MovieClip [, force:Number, minDist:Number])

- designates a movie clip which the particle will spring away from. any number of clips can be added.
- arguments:
    clip. a movie clip which the particle will spring away from.
    force. the strength of the spring. default is 0.1
    minDist. the distance in pixels from the point that the particle will try to maintain. default is 100
- returns:
    the index number of the clip added (can be used to remove the clip from the list)

removeSpringPoints(index:Number)

- removes a previously specified spring point
- arguments:
    index. the number of the point to remove

removeGravPoints(index:Number)

- removes a previously specified gravity point
- arguments:
    index. the number of the point to remove

removeRepelPoints(index:Number)

- removes a previously specified repel point
- arguments:
    index. the number of the point to remove

clearSpringPoints()

- removes all spring points

clearGravPoints()

- removes all grav points

clearRepelPoints()

- removes all repel points

clearSpringClips()

- removes all spring points

clearGravClips()

- removes all grav points

clearRepelClips()

- removes all repel points*/

package
{

import flash.display.MovieClip;
import flash.events.*;

/**
 *      Original AS2 Class by Keith Peters (BIT-101)
 *      Conversion to AS3 by Chris Teso
 */
public class Particle extends MovieClip {

    private var __vx:Number                 = 0;
    private var __vy:Number                 = 0;
    private var __k:Number                  = .2;
    private var __damp:Number               = .9;
    private var __bounce:Number             = -.5;
    private var __grav:Number               = 0;
    private var __bounds:Object;
    private var __draggable:Boolean         = false;
    private var __edgeBehavior:String       = "bounce";
    private var __drag:Boolean;
    private var __oldx:Number;
    private var __oldy:Number;
    private var __maxSpeed:Number;
    private var __wander:Number             = 0;
    private var __turn:Boolean              = false;
    private var __springToMouse:Boolean     = false;
    private var __mouseK:Number             = .2;
    private var __gravToMouse:Boolean       = false;
    private var __gravMouseForce:Number     = 5000;
    private var __repelMouse:Boolean        = false;
    private var __repelMouseMinDist:Number  = 100;
    private var __repelMouseK:Number        = .2;
    private var __springPoints:Array;
    private var __gravPoints:Array;
    private var __repelPoints:Array;
    private var __springClips:Array;
    private var __gravClips:Array;
    private var __repelClips:Array;
    private var __efClip:MovieClip;

    //
    public function Particle()
    {
        trace( "particle initialized" )
        addEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
        init();
    }

    private function onAddedToStage( event:Event ):void
    {
        removeEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
        //can access the stage now.
        //trace( "added to stage" );
    } 

    private function init():void
    {
        __bounds = new Object();
        setBounds( 0, Main.stage.stageWidth, 0, Main.stage.stageHeight );
        __maxSpeed = Number.MAX_VALUE;
        __springPoints = new Array();
        __gravPoints = new Array();
        __repelPoints = new Array();
        __springClips = new Array();
        __gravClips = new Array();
        __repelClips = new Array();

        __efClip = new MovieClip();
        __efClip.addEventListener( Event.ENTER_FRAME, __efHandler );

    }
    public function set vx(nVx:Number):void
    {
        __vx = nVx;
    }

    public function get vx():Number
    {
        return __vx;
    }

    public function set vy(nVy:Number):void
    {
        __vy = nVy;
    }

    public function get vy():Number
    {
        return __vy;
    }

    public function set damp(nDamp:Number):void
    {
        __damp = nDamp;
    }

    public function get damp():Number
    {
        return __damp;
    }

    public function set bounce(nBounce:Number):void
    {
        __bounce = nBounce;
    }

    public function get bounce():Number
    {
        return __bounce;
    }

    public function set grav(nGrav:Number):void
    {
        __grav = nGrav;
    }

    public function get grav():Number
    {
        return __grav;
    }

    public function set maxSpeed( nMaxSpeed:Number )
    {
        __maxSpeed = nMaxSpeed;
    }

    public function get maxSpeed():Number
    {
        return __maxSpeed;
    }

    public function set wander( nWander:Number ):void
    {
        __wander = nWander;
    }

    public function get wander():Number
    {
        return __wander;
    }

    public function set edgeBehavior(sEdgeBehavior:String):void
    {
        __edgeBehavior = sEdgeBehavior;
    }

    public function get edgeBehavior():String
    {
        return __edgeBehavior;
    }

    public function setBounds( left, right, top, bot)
    {
        __bounds.top = top;
        __bounds.bottom = bot;
        __bounds.left = left;
        __bounds.right = right;
    }

    public function set draggable( bDrag:Boolean ):void
    {
        __draggable = true;
        if ( bDrag )
        {
            this.addEventListener( MouseEvent.CLICK, pressHandler );
            this.addEventListener( MouseEvent.MOUSE_UP, releaseHandler );
            stage.addEventListener( MouseEvent.MOUSE_UP, outsideHandler) ; // releaseOutside handler hack

        } else
        {
            this.removeEventListener( MouseEvent.CLICK, pressHandler );
            this.removeEventListener( MouseEvent.MOUSE_UP, releaseHandler );
            stage.removeEventListener( MouseEvent.MOUSE_UP, outsideHandler );
            __drag = false;
        }
    }

    private function pressHandler( e:MouseEvent ):void
    {
        this.startDrag();
        __drag = true;
    }

    private function releaseHandler( e:MouseEvent ):void
    {
        this.stopDrag();
        __drag = false;
    }

    private function outsideHandler( e:MouseEvent ):void
    {
        this.stopDrag();
        __drag = false;
    }

    public function get draggable():Boolean
    {
        return __draggable;
    }

    public function set turnToPath(bTurn:Boolean):void
    {
        __turn = bTurn;
    }

    public function get turnToPath():Boolean
    {
        return __turn;
    }

    private function __efHandler( e:Event ):void
    {
        __move();
    }

    private function __move():void
    {
        var dx;
        var dy;
        var distSQ;
        var dist;
        var force;
        var tx;
        var ty;
        var point;
        var clip;
        var k;
        var minDist;

        if ( __drag )
        {
            __vx = this.x - __oldx;
            __vy = this.y - __oldy;
            __oldx = this.x;
            __oldy = this.y;

        } else
        {
            if ( __springToMouse )
            {
                __vx += ( this.parent.mouseX - this.x ) * __mouseK;
                __vy += ( this.parent.mouseY - this.y ) * __mouseK;
            }

            if ( __gravToMouse )
            {
                trace( "this.x = "+this.x )
                trace( "this.parent.mouseX ="+this.parent.mouseX )
                dx = this.parent.mouseX - this.x;
                dy = this.parent.mouseY - this.y;

                distSQ = dx * dx + dy * dy;
                dist = Math.sqrt( distSQ );
                force = __gravMouseForce / distSQ;
                __vx += force * dx / dist;
                __vy += force * dy / dist;
            }

            if ( __repelMouse )
            {
                dx = this.parent.mouseX - this.x;
                dy = this.parent.mouseY - this.y;

                dist = Math.sqrt(dx * dx + dy * dy);
                if (dist < __repelMouseMinDist)
                {
                    tx = this.parent.mouseX - __repelMouseMinDist * dx / dist;
                    ty = this.parent.mouseY - __repelMouseMinDist * dy / dist;
                    __vx += (tx - this.x) * __repelMouseK;
                    __vy += (ty - this.y) * __repelMouseK;
                }
            }

            for ( var sp:uint=0; sp < __springPoints.length; sp++ )
            {
                point = __springPoints[sp];
                __vx += (point.x - this.x) * point.k;
                __vy += (point.y - this.y) * point.k;
            }

            for ( var gp:uint = 0; gp < __gravPoints.length; gp++ )
            {
                point = __gravPoints[gp];

                dx = point.x - this.x;
                dy = point.y - this.y;

                distSQ = dx * dx + dy * dy;
                dist = Math.sqrt( distSQ );
                force = point.force / distSQ;
                __vx += force * dx / dist;
                __vy += force * dy / dist;
            }

            for ( var rp:uint = 0; rp < __repelPoints.length; rp++ )
            {
                point = __repelPoints[rp];
                dx = point.x - this.x;
                dy = point.y - this.y;

                dist = Math.sqrt( dx * dx + dy * dy );
                if (dist < point.minDist)
                {
                    tx = point.x - point.minDist * dx / dist;
                    ty = point.y - point.minDist * dy / dist;

                    __vx += (tx - this.x) * point.k;
                    __vy += (ty - this.y) * point.k;

                }
            }

            for ( var sc:uint = 0; sc < __springClips.length; sc++ )
            {
                clip = __springClips[sc].clip;
                k = __springClips[sc].k;
                __vx += (clip.x - this.x) * k;
                __vy += (clip.y - this.y) * k;

            }

            for ( var gc:uint = 0; gc < __gravClips.length; gc++ )
            {
                clip = __gravClips[gc].clip;
                dx = clip.x - this.x;
                dy = clip.y - this.y;

                distSQ = dx * dx + dy * dy;
                dist = Math.sqrt( distSQ );
                force = __gravClips[gc].force / distSQ;
                __vx += force * dx / dist;
                __vy += force * dy / dist;
            }

            for ( var rc:uint= 0; rc < __repelClips.length; rc++ )
            {
                clip = __repelClips[rc].clip;
                minDist = __repelClips[rc].minDist;
                k = __repelClips[rc].k;
                dx = clip.x - this.x;
                dy = clip.y - this.y;

                dist = Math.sqrt(dx * dx + dy * dy);
                if (dist < minDist)
                {
                    tx = clip.x - minDist * dx / dist;
                    ty = clip.y - minDist * dy / dist;
                    __vx += (tx - this.x) * k;
                    __vy += (ty - this.y) * k;

                }
            }
            __vx += Math.random() * __wander - __wander / 2;
            __vy += Math.random() * __wander - __wander / 2;
            __vy += __grav;
            __vx *= damp;
            __vy *= damp;

            var speed = Math.sqrt(__vx * __vx + __vy * __vy);
            if (speed > __maxSpeed) {
                __vx = __maxSpeed * __vx / speed;
                __vy = __maxSpeed * __vy / speed;
            }
            if (__turn)
            {
                this.rotation = Math.atan2(__vy, __vx) * 180 / Math.PI;
            }

            this.x += __vx;
            this.y += __vy;

            if(__edgeBehavior == "wrap")
            {
                if ( this.x > __bounds.right + this.width/2 )
                {
                    this.x = __bounds.left - this.width/2;
                } else if ( this.x < __bounds.left - this.width/2)
                {
                    this.x = __bounds.right + this.width/2;
                }
                if( this.y > __bounds.bottom + this.height/2)
                {
                    this.y = __bounds.top - this.height/2;
                } else if (this.y < __bounds.top - this.height/2)
                {
                    this.y = __bounds.bottom + this.height/2;
                }

            } else if(__edgeBehavior == "bounce")
            {
                if ( this.x > __bounds.right - this.width/2)
                {
                    this.x = __bounds.right - this.width/2;
                    __vx *= __bounce;
                } else if (this.x < __bounds.left + this.width/2){
                    this.x = __bounds.left + this.width/2;
                    __vx *= __bounce
                }
                if( this.y > __bounds.bottom - this.height/2){
                    this.y = __bounds.bottom - this.height/2;
                    __vy *= __bounce
                } else if ( this.y < __bounds.top + this.height/2){
                    this.y = __bounds.top + this.height/2;
                    __vy *= __bounce;
                }

            } else if(__edgeBehavior == "remove")
            {
                if( this.x > __bounds.right + this.width/2 || this.x < __bounds.left - this.width/2 ||
                   this.y > __bounds.bottom + this.height/2 || this.y < __bounds.top - this.height/2){
                    removeChild( this );
                }
            }
            if( stage != null )
                stage.invalidate();
        }
    };

    public function gravToMouse( bGrav:Boolean, force:Number ):void
    {
        if (bGrav) {
            if (!force) {
                var force = 1000;
            }
            __gravMouseForce = force;
            __gravToMouse = true;
        }
        else {
            __gravToMouse = false;
        }
    }

    public function springToMouse( bSpring:Boolean, force:Number ):void
    {
        if (bSpring)
        {
            if (!force) {
                var force = .1;
            }
            __mouseK = force;
            __springToMouse = true;

        } else
        {
            __springToMouse = false;
        }
    }

    public function repelMouse( bRepel:Boolean, force:Number, minDist:Number ):void
    {
        if (bRepel)
        {
            if (!force)
            {
                var force = .1;
            }
            if (!minDist)
            {
                var minDist = 100;
            }
            __repelMouseK = force;
            __repelMouseMinDist = minDist;
            __repelMouse = true;

        } else
        {
            __repelMouse = false;
        }
    }

    public function addSpringPoint(x:Number, y:Number, force:Number):Number
    {
        if (!force)
        {
            var force = .1;
        }
        __springPoints.push( {x:x, y:y, k:force} );
        return __springPoints.length - 1;
    }

    public function addGravPoint(x:Number, y:Number, force:Number):Number
    {
        if (!force)
        {
            var force = 1000;
        }
        __gravPoints.push( {x:x, y:y, force:force} );
        return __gravPoints.length - 1;
    }

    public function addRepelPoint( x:Number, y:Number, force:Number, minDist:Number ):Number
    {
        if (!force) {
            var force = .1;
        }
        if (!minDist) {
            var minDist = 100;
        }
        __repelPoints.push({x:x, y:y, k:force, minDist:minDist});
        return __repelPoints.length - 1;
    }

    public function addSpringClip(clip:MovieClip, force:Number):Number
    {
        if (!force)
        {
            var force = .1;
        }
        __springClips.push( {clip:clip, k:force} );
        return __springClips.length - 1;
    }

    public function addGravClip(clip:MovieClip, force:Number):Number
    {
        if (!force)
        {
            var force = 1000;
        }
        __gravClips.push({clip:clip, force:force});
        return __gravClips.length - 1;
    }

    public function addRepelClip( clip:MovieClip, force:Number, minDist:Number ):Number
    {
        if ( !force )
        {
            var force = .1;
        }
        if ( !minDist )
        {
            var minDist = 100;
        }
        __repelClips.push( {clip:clip, k:force, minDist:minDist} );
        return __repelClips.length - 1;
    }

    public function removeSpringPoint( index:Number ):void
    {
        __springPoints.splice(index, 1);
    }

    public function removeGravPoint( index:Number ):void
    {
        __gravPoints.splice(index, 1);
    }

    public function removeRepelPoint( index:Number ):void {
        __repelPoints.splice(index, 1);
    }

    public function removeSpringClip(index:Number):void
    {
        __springClips.splice(index, 1);
    }

    public function removeGravClip(index:Number):void
    {
        __gravClips.splice(index, 1);
    }

    public function removeRepelClip(index:Number):void
    {
        __repelClips.splice(index, 1);
    }

    public function clearSpringPoints():void
    {
        __springPoints = new Array();
    }

    public function clearGravPoints():void
    {
        __gravPoints = new Array();
    }

    public function clearRepelPoints():void
    {
        __repelPoints = new Array();
    }

    public function clearSpringClips():void
    {
        __springClips = new Array();
    }

    public function clearGravClips():void
    {
        __gravClips = new Array();
    }

    public function clearRepelClips():void
    {
        __repelClips = new Array();
    }
}

}

AS3 Polar Coordinates and Radians

/flash/radians.swf

Many times I’ve set up interfaces where I need to place different objects equidistant around a central object. The solution to this problem is to first calculate the angle of each object by converting Radians to Degrees. This can be expressed by the following formula

Media_httpuploadwikim_idwbg

So, you simply need to loop through your collection of objects and assign each a different angle. After that you plug that angle into a new Polar Point.

for(var i=0;i

Here’s the complete source: radians.zip

package
{
        import flash.ui.*;
        import flash.display.*;
        import flash.events.*;
        import flash.geom.*;

        public class Main extends Sprite
        {

                /*
                ========================================================
                | Private Variables                         | Data Type
                ========================================================
                */

                private var array:Array = new Array()
                private var circumference:int;

                /*
                ========================================================
                | Constructor
                ========================================================
                */

                public function Main ()
                {
                        stage.align = StageAlign.TOP_LEFT;

                        // make some balls
                        addParticle( 100 )

                        menu.txtParticles.text = 'Particles: 100';

                        stage.addEventListener( Event.ENTER_FRAME, runParticle )

                        menu.slideCircumference.addEventListener( Event.CHANGE, changeCircumference );
                        menu.particles.addEventListener( Event.CHANGE, changeParticles );

                }

                private function addParticle( num )
                {
                        stage.removeEventListener( Event.ENTER_FRAME, runParticle )

                        var tot:Number = array.length

                        // kill mc's
                        for( var t=0;t

Permalink: http://www.christeso.com/index.php/lab/as3-polar-coordinates-and-radians

AS3 Drop Down Menu Class

I briefly Googled for a drop down class to no avail. I say briefly as I only went one page deep. I’m sure there are others out there, but I instead got impatient as usual and just wrote my own. I thought I’d share it for other impatient people’s benefit. Without further ado here’s the AS3 Drop Down Class code. It’s a work in progress and most likely will be updated when I give it any more thought.

You can see the drop down in use on my homepage.

Edit [ 12.16.08 ] : added directional code.

//usage
// array for drop
var dropOtherArray:Array = new Array()
dropOtherArray.push( {title:"iWork", name:"folio"} )
dropOtherArray.push( {title:"iExperiment", name:"lab"} )
dropOtherArray.push( {title:"iWrite", name:"blog"} )
dropOtherArray.push( {title:"iPhotograph", name:"photo"} )
dropOtherArray.push( {title:"iFlickr", name:"flickr"} )
dropOtherArray.push( {title:"iRecord", name:"vimeo"} )
dropOtherArray.push( {title:"contactMe", name:"contact"} )

fmat.color = 0xffffff
fmat.font = font.fontName
fmat.size = 11

addChild( _dropOther = new DropDown( 180, 25, "iLiveElsewhere:", fmat, 0x000033, dropOtherArray, "down", other ) )

package com.teso.ui
{
        import com.gskinner.motion.*
        import flash.display.*;
        import flash.events.*;
        import flash.net.*;
        import flash.utils.*;
        import flash.text.*;
        import fl.transitions.*;
        import fl.transitions.easing.*;

        public class DropDown extends Sprite
        {
                private var _items:Array = new Array()
                private var _overC:uint;
                private var _backC:uint;
                private var _w:Number;
                private var _h:Number;
                private var _timer:Timer;
                private var _open:Boolean = false;
                private var _defaultText:TextField;
                private var _title:String;
                private var _direction:String;
                private var _fmt:TextFormat;

                public function DropDown( w:Number, h:Number, title:String, fmt:TextFormat, colorBack:uint, itemArray:Array, direction:String, callback )
                {
                        // timer
                        _timer = new Timer( 300 );
                        _timer.addEventListener( TimerEvent.TIMER, closeDrop )

                        // vars
                        _w = w
                        _h = h
                        _backC = colorBack
                        _items = itemArray
                        _title = title
                        _direction = direction
                        _fmt = fmt

                        // create a back for the holder
                        var holder:MovieClip = new MovieClip();
                        holder.name = "holder"
                        holder.graphics.beginFill( _backC, 1 );
                        holder.graphics.drawRoundRect( 0, 0, _w, _h, 2, 2 )
                        holder.graphics.endFill()

                        // add the drop
                        addChild( holder )

                        // set listeners
                        holder.buttonMode = true;
                        holder.addEventListener( MouseEvent.MOUSE_OVER, openDrop )
                        holder.addEventListener( MouseEvent.MOUSE_OVER, cancelClose )
                        holder.addEventListener( MouseEvent.MOUSE_OUT, startClose )

                        // create a text field
                        var t:TextField = new TextField()
                        t.name = "holderText"
                        t.selectable = false;
                        t.autoSize = TextFieldAutoSize.LEFT;
                        t.htmlText = title
                        t.setTextFormat( fmt )
                        t.y = ( holder.height/2 ) - ( t.height/2 )

                        _defaultText = t

                        // add the text
                        holder.addChild( t )

                        // create children
                        for( var i=0; iPermalink:

http://www.christeso.com/index.php/lab/as3-drop-down-menu-classas3-drop-down-menu-class/