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

Multiple spheres #1

The "display" package has the "Sprite" and the "Graphics" classes.
for timer events
for keystroke events no matter where the user happens to be
Here is the SWF meta tag:
sets stage's background color, etc.
Get Adobe Flash player
by bill.billson103 11 Mar 2016
    Embed
/**
 * Copyright bill.billson103 ( http://wonderfl.net/user/bill.billson103 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/QHND
 */

package {
    import flash.display.*;     // The "display" package has the "Sprite" and the "Graphics" classes.
    import flash.geom.*;
    import flash.events.*;
    import flash.text.*;
    import flash.filters.*;
    import flash.utils.*;   // for timer events
    import mx.core.FlexGlobals;    // for keystroke events no matter where the user happens to be
    
    // Here is the SWF meta tag:
    [SWF(percentWidth = "100%", percentHeight = "100%", backgroundColor = "#efef00", frameRate = "120")]  // sets stage's background color, etc.
    public class sphereBox extends Sprite {         //instead of "extends Sprite", where a sprite is a layer that can be moved and manipulated (like a single graphical sprite might use).  Can still use "extends MovieClip" or "extends Sprite", though.
        // Declarations for class variables follow.
        //protected var username:TextField;
        //protected var password:TextField;    // protected means that only things from same class or its subclasses can access it
        protected var myFormat:TextFormat = new TextFormat();
        internal var coordText:TextField = new TextField();
        public var moreText:TextField = new TextField();    // publlic means ANY other class can use it (even things in classes from other packages)
        internal var extraText:TextField = new TextField();  // internal means ONLY things from classes in the SAME PACKAGE as this class
        internal var numClicks:int = 0;
        //private var  shapes:Array = [];   // an array of all the shapes to be used
        //private var phases:Array = [];  // the phases of the shapes (see this used later)
        //private var shapesContainer:Sprite = new Sprite();   // the Sprite holds everything seen later
        //private var atom1:myAtomClass = new myAtomClass();    // an atom for displaying
        private var theTimer:Timer;            // timer for keeping track of time
        private var numAtoms:int=6;
        private var atoms:Array = new Array();
        private var xc:Array = new Array();   // position (units: pixels)
        private var yc:Array = new Array();
        private var dx:Array = new Array();  // velocity (units: pixels/clock tick)
        private var dy:Array = new Array();
        private var x1:int=40;       // old
        private var y1:int=40;       // old
        private var dx1:int=3;       // old
        private var dy1:int=2;       // old
        private var xmin:int=0;
        private var ymin:int=0;
        private var xmin1:int=0;     // old
        private var ymin1:int=0;     // old
        private var xmax:int=stage.width;
        private var ymax:int=stage.height;
        private var xmax1:int=stage.width;      // old
        private var ymax1:int=stage.height;      // old
        private var xBuffer:int=30;
        private var yBuffer:int=30;
        private var delay:int=20;
        private var dxsave:Array = new Array();
        private var dysave:Array = new Array();
        private var dxsave1:int;            // old
        private var dysave1:int;            // old
        private var dxlim:int=20;
        private var dylim:int=20;
        private var dxlim1:int=20;       // old
        private var dylim1:int=20;       // old
        private var sizes:Array = new Array();
        private var size1:int=30;          // old
        private var sizeMax:int=100;
        private var sizeMin:int=10;
        private var sizeMax1:int=100;     // old
        private var sizeMin1:int=10;        // old
        private var gravity:Boolean=false;
        private var rotationAngle:Number=0;    //old
        private var rotationSpeed:Number=5;     // old
        private var rotAngles:Array= new Array();            // angle of sphere (degrees)
        private var rotSpeeds:Array = new Array();         // angular velocity of sphere (degrees/clock tick)
        private var noRotation:Boolean = true;
        private var doChase:Boolean = false;
        private var cursorX:int;
        private var cursorY:int;
        private var attraction:Boolean=true;
        private var wildChase:Boolean=false;
        private var helpbox:TextField;
        private var infobox:TextField;
        private var showingHelpBox:Boolean=false;
        private var focus:int=0;    // sphere of interest
        
        public function sphereBox() {        // the (always) first function is the "constructor" that is triggered when this actionscript is referenced (by the webpage)
            
            super();     // inherit all the imports from the superclass MovieClip for the new class helloWorld.


            doInit();    // To set everything up.

            // Construct boxes.
/*            username = new TextField();
            username.text="Enter username";
            username.type="input";      //  "input" means editable; "dynamic" to disable this
            username.border=true;
            username.height=20;
            username.width=140;
            addChild(username);
            password = new TextField();
            password.text="Password";
            password.type="input";
            password.y=25;
            password.border=true;
            password.height=60;
            password.width=140;
            password.background=true;
            password.backgroundColor=0x32788f
            password.textColor=0xf3fc44;      // Get RGB colors quickly from http://www.colorpicker.com/
            password.multiline=true;
            password.wordWrap=true;     // all these optinos are at http://help.adobe.com/en_US/as3/dev/WS8d7bb3e8da6fb92f-20050207122bd5f80cb-8000.html
            addChild(password); */
            
            // Listen for change events from the text fields.
//            username.addEventListener(Event.CHANGE, loginChangeHandler);
//            password.addEventListener(Event.CHANGE, loginChangeHandler);
            stage.addEventListener(MouseEvent.CLICK, _onStageMouseDown);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, _onStageMouseMove);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, _onKeyDown);            // for only when user has stage active and is in it (i.e. the cursor is)
//            infobox.text="Post adding events...";
            // FlexGlobals.topLevelApplication.addEventListener(KeyboardEvent.KEY_DOWN, _onKeyDown);     // for no matter where cursor/user happens to be
            
            // Create a Timer-class object in order to give fluid movement.
            theTimer = new Timer(delay, 0);                               // time of one cycle (a.ka. interval) in milliseconds; go for # of cycles given by second argument (0=forever)
            theTimer.addEventListener(TimerEvent.TIMER, _onTick);        // execute given function at each interval
            //stage.addEventListener(TimerEvent.TIMER_COMPLETE, _onTimerComplete);   // to do if the timer is finished the given # of cycles
            theTimer.start();                                       // start the timer
//            infobox.text="Timer has been started.";
//
            
            
            // Make a circle.
 /*           var  myCircle:Shape = new Shape();    // The instance with name myCircle is created.
            myCircle.graphics.beginFill(0x990000);  // Fill the circle with the color #990000.
            myCircle.graphics.lineStyle(2, 0x000000);  // Give the ellipse a black, two-pixel-thick line.
            myCircle.graphics.drawCircle((stage.stageWidth - 100) / 2, (stage.stageHeight - 100) / 2, 100);   // Draw the circle, assigning it an x position, y positiion, and a radius.
            myCircle.graphics.endFill();   // End the filling of the circle.  Must always have this when finished with drawing in the shape.
            addChild(myCircle);  // Add a child.
            
            var t:TextField = new TextField();  // declares variable as a text field
            t.text = "Hello World";  // assigns my words to my variable
            t.x = 100;                   // moves my text to the right 100 pixels
            t.y = 150;
            t.textColor = 0x0db5ad;    // sets the RGB color of the text
            t.backgroundColor = 0x111111;   // sets the background color for the text that is displayed (hopefully)
            t.height = 20;
            
            addChild(t);         // displays my variable as text on the screen
*/

 /*
            moreText.text = "Hello Class!";
            moreText.x=100;
            moreText.y=200;
            moreText.textColor = 0x737306;
            addChild(moreText);
            
            extraText.text = "Hello Class!";
            extraText.x=200;
            extraText.y=175;
            extraText.opaqueBackground=true;
            extraText.background = true;
            extraText.backgroundColor= 0x808000;
            extraText.textColor = 0x300000;
            addChild(extraText);
*/

        }  // End of the main function my3Dviewer.





        public function doInit():void {
            // Do all initializations.
            makeBackground();
            cursorTracker();
            // Using multiple atoms this time.
            var ii:int;
            xmax=stage.width;
            ymax=stage.height;
            for (ii=0; ii<numAtoms; ii++) {
                atoms.push(new myAtomClass());
                rotAngles.push(0);
                rotSpeeds.push(0);
                sizes.push(30);
                addChild(atoms[ii]);
                xc.push(((ii+1)*70)%xmax);
                yc.push(((ii+1)*51)%ymax);
                dx.push(3-ii);
                dy.push(2);
                if (xc[ii]<xBuffer) {xc[ii]=(xmax-xBuffer)-xc[ii];}
                if (xc[ii]>(xmax-xBuffer)) {xc[ii]=xBuffer+(x-(xmax-xBuffer));}
                dxsave.push(dx[ii]);
                dysave.push(dy[ii]);
                atoms[ii].SetCoordinates(xc[ii], yc[ii], 0, rotAngles[ii], xc[ii], yc[ii]);
            }
            //atom1  = new myAtomClass();   // old
            //xmax1 = stage.width;          // old
            //ymax1 = stage.height;         // old
            //addChild(atom1);              // old
            //atom1.SetCoordinates(xc[ii], yc[ii], 0, rotAngles[ii], xc[ii], yc[ii]);    // old
            coordText.width=120;
            // information text field
/*            infobox = new TextField();
            infobox.x=50;
            infobox.y=350;
            infobox.width=300;
            infobox.height=300;
            infobox.textColor=0x884410;
            infobox.text="INFO";
            stage.addChild(infobox); */
        }  // End of function doInit().

        public function helpScreen():void {
            if (!showingHelpBox) {
                helpbox = new TextField();
                helpbox.x=50;
                helpbox.y=120;
                helpbox.width=300;
                helpbox.height=300;
                helpbox.textColor=0x884410;
            
                helpbox.text="OPTIONS \n\n";
                helpbox.appendText("    h  :   Help screen.\n");
                helpbox.appendText("    n  :   Spin on/off.\n");
                helpbox.appendText("    g  :   Toggles gravity.\n");
                helpbox.appendText("    c  :   Chase mode on/off.\n");
                helpbox.appendText("    w  :  Toggles wild chase.\n");
                helpbox.appendText("    a  :   Toggles chase attraction/repulsion.\n");
                helpbox.appendText("    f/d :  Increases/decreases clock speed.\n");
                helpbox.appendText("    z  :    Toggles size of sphere.\n");
                helpbox.appendText("    t   :    Toggle translucency of sphere.\n");
                helpbox.appendText("    s  :    Stop sphere.\n");
                helpbox.appendText("    Arrow Keys :   Alter velocity.\n");
                helpbox.appendText("    Space key :   Show/hide sphere.\n");
                helpbox.appendText("    +/- :  Change diameter of sphere.\n");
                addChild(helpbox);        // could also explicitly use stage.addChild(helpbox) to same end
                showingHelpBox=true;
            } else {
                removeChild(helpbox);
                showingHelpBox=false;
            }
        }

        
        public function makeBackground():void {
            // Make the background for the stage.
            var mtx:Matrix = new Matrix();
            mtx.createGradientBox(stage.stageWidth * 1.5, stage.stageHeight * 1.5, 0, -stage.stageWidth * 0.25, -stage.stageHeight * 0.25);
            var theBackground:Shape = new Shape();
            theBackground.graphics.beginGradientFill(GradientType.RADIAL, [0xbef4f7, 0xb4d3eb], [1.0, 1.0], [0, 255], mtx);
            theBackground.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
            addChild(theBackground);
        } // end of function makeBackground

        public function cursorTracker():void {
             //The section below is going to display more text.
            coordText.text = "Starting";
            coordText.x = 160;
            coordText.y = 90;
            coordText.textColor = 0xff5000;
            addChild(coordText);
        }  // end function cursorTracker


        
/*        protected function loginChangeHandler(event:Event):void {
            if ((username.text == "tyler") &&
                (password.text == "shadowcopy")) {
                     // authentication verified -- continue
                     myFormat.font="Verdana";
                     myFormat.bold=true;
                     myFormat.size=16;
                     myFormat.italic=true;
                     myFormat.underline=true;
                     moreText.defaultTextFormat=myFormat;
                     
                     moreText.text = "AUTHENTICATION PASSED";
                     moreText.x=80;
                     moreText.y=60;
                     moreText.textColor=0xff1010;
                     moreText.width=250;
                     
                     addChild(moreText);
                }
        } // end of function loginChangeHandler     */

        protected function _onStageMouseDown(e:Event):void {
            trace(e);
            numClicks++;
            //extraText.text="CLICK " + numClicks;
            //infobox.text="CLICK #" + numClicks;
            trace("Does this show up?");   // should print to the screen... mostly for debug mode and need to turn off "Omit trace statements" setting in Publish settings
            //atom1.toggleVisible();
            var ii:int
            for (ii=0; ii<numAtoms; ii++) {
                atoms[ii].toggleTranslucency();
            }
            if (showingHelpBox) {
                stage.removeChild(helpbox);
                showingHelpBox=false;
            }

        } // end of function _onStageMouseDown

        protected function _onStageMouseMove(e:MouseEvent):void {
            var currentX:Number = parent.mouseX;
            var currentY:Number = parent.mouseY;
            cursorX = int(currentX);
            cursorY = int(currentY);
            coordText.text=currentX +", "+ currentY;
        }  // end of function _onStageMouseMove

        protected function _onKeyDown(e:KeyboardEvent):void {
            var bShiftPressed:Boolean = e.shiftKey;
            var bAltPressed:Boolean = e.altKey;
            var bCtrlPressed:Boolean = e.ctrlKey;
            var ii:int;
            
            //infobox.text="Key pressed.";            
            //if (e.keyCode == 32 && bAltPressed) {
            if (e.keyCode == 32) {           // space bar
                for (ii=0; ii<numAtoms; ii++) {
                    atoms[ii].toggleVisible();
                }
            }
            //if (e.keyCode == ("S").charCodeAt(0) && bCtrlPressed) {
            if (e.keyCode == ("S").charCodeAt(0)) {
            //if (e.keyCode == 83 && bCtrlPressed) {
            //if ( bCtrlPressed) {
                if (dx[0] != 0 || dy[0] != 0) {
                    dxsave[0]=dx[0]; dysave[0]=dy[0];
                    dx[0]=0; dy[0]=0;
                    gravity=false;
                } else {
                    dx[0]=dxsave[0]; dy[0]=dysave[0];
                }
            }
            //if (e.keyCode == ("Z").charCodeAt(0) && bAltPressed) {
            if (e.keyCode == ("Z").charCodeAt(0)) {
                atoms[0].toggleScale();
            }
            
           const letters:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
           //const letter_A:int = letters[0].charCodeAt(0);
           const letter_A:int = ("A").charCodeAt(0);
           const letter_C:int = ("C").charCodeAt(0);
           const letter_D:int = ("D").charCodeAt(0);
           const letter_F:int = ("F").charCodeAt(0);
           const letter_G:int = ("G").charCodeAt(0);
           const letter_H:int = ("H").charCodeAt(0);
           const letter_N:int = ("N").charCodeAt(0);
           const letter_T:int = ("T").charCodeAt(0);
           const letter_W:int = ("W").charCodeAt(0);
           switch (e.keyCode) {
               case letter_G:        // turn on gravity
                   gravity = !gravity;
                   break;
               case letter_F:         // speed up timer clock (shorten delay with minimum of 1 millisecond for ticks)
                   if (delay>1) { delay--;  }
                   //delay=5;
                   theTimer.removeEventListener(TimerEvent.TIMER, _onTick);
                   theTimer = new Timer(delay, 0);                                  // time of one cycle (a.ka. interval) in milliseconds; go for # of cycles given by second argument (0=forever)
                   theTimer.addEventListener(TimerEvent.TIMER, _onTick);        // execute given function at each interval
                   theTimer.start();                                       // start the timer
                   break;
               case letter_C:        // cursor chasing toggle
               //case 67:    // letter 'c'
                   doChase = !doChase;
                   break;
               case letter_A:        // whether cursor is attractive or repulsive
                   attraction = !attraction;
                   break;
               case letter_W:       // toggles wild (i.e. more random) cursor chase
                   wildChase = !wildChase;
                   break;
               case letter_D:       // slow down timer clock (no upper limit for how far apart ticks can be)
                   delay++;
                   theTimer.removeEventListener(TimerEvent.TIMER, _onTick);
                   theTimer = new Timer(delay, 0);                                  // time of one cycle (a.ka. interval) in milliseconds; go for # of cycles given by second argument (0=forever)
                   theTimer.addEventListener(TimerEvent.TIMER, _onTick);        // execute given function at each interval
                   theTimer.start();                                       // start the timer
                   break;
               case letter_N:      // whether or not sphere has rotation enabled (includes caroming with english)
                   noRotation = !noRotation;
                   if (!noRotation) {
                       for (ii=0; ii<numAtoms; ii++) { rotSpeeds[ii]=5.0; }
                    }
                   break;
               case letter_T:       // toggles translucency of sphere
                   //if ( !bAltPressed) break;
                   atoms[0].toggleTranslucency();
                   break;
               case 37:      // LeftArrow
                   if (dx[0] > -dxlim) {  dx[0]--; }
                   break;
               case 38:      // UpArrow
                   if (dy[0] > -dylim) {  dy[0]--; }
                   break;
               case 39:      // RightArrow
                   if (dx[0] < dxlim) {  dx[0]++; }
                   break;
               case 40:      // DownArrow
                   if (dy[0] < dylim) {  dy[0]++; }
                   break;
               case 187:    // =+ key      (increase sphere diameter)
                   //if ( !bCtrlPressed ) break;
                   if (sizes[0] < sizeMax) {  sizes[0]++; }
                   atoms[0].changeSize(sizes[0]);
                   xBuffer=sizes[0];
                   yBuffer=sizes[0];
                   break;
               case 189:    // -_ key      (decrease sphere diameter)
                   //if ( !bCtrlPressed ) break;
                   if (sizes[0] > sizeMin) {  sizes[0]--; }
                   atoms[0].changeSize(sizes[0]);
                   xBuffer=sizes[0];
                   yBuffer=sizes[0];
                   break;
               case letter_H:     // help menu
                   helpScreen();
                   break;
               default:
           }

        } // end function _onKeyDown


        protected function _onTick(e:TimerEvent):void {
            var i:uint=0;
            var distX:int;
            var distY:int;
            var drawX:int;      // actual position to draw sphere's center (x-component)
            var drawY:int;      // ...  (y-component)
            var rad:int;           // radius of sphere
            var impact:Number;  // not used yet
            var ddx:Number;   // change in velocity x-component
            var ddy:Number;   // change in velocity y-component
            var dW:Number;    // change in rotational K.E.
            var dT:Number;    // change in translational K.E.
            var T0:Number;   // initial translational K.E.
            var T1:Number;   // final translational K.E.
            var W0:Number;   // initial rotational K.E.
            var W1:Number;   // final rotational K.E.
            var HMOI:Number=1.0;    // will need to calibrate this value for one-half the moment of inertia (units chosen so sphere mass is two and angles are in degrees)
            var origdx:Number;
            var origdy:Number;
            var wasLeft:Boolean=false;
            var wasRight:Boolean=false;
            var wasTop:Boolean=false;
            var wasBottom:Boolean=false;
            var wasMovingNeg:Boolean=false;
            var wasMovingPos:Boolean=false;
            var wasSpinningNeg:Boolean=false;
            var wasSpinningPos:Boolean=false;
            var absFinalRotSpeed:Number;
            var angle:Number;
            var goDirection:Number;
            var scaleC:Number=1.00;    // for help box special effects
            var scaleV:Number=0.0;
            var scaleA:Number=0.001;
            var ii:int;
            
            //infobox.text="Timer ticked." + xc[0] + ", " + yc[0];
            
            if (showingHelpBox) {
                if (scaleC>1.10) {   scaleA = -0.0001;  }
                if (scaleC<0.90) {   scaleA =  0.0001;  }
                scaleV += scaleA;
                scaleC += scaleV;
                helpbox.scaleX=scaleC;
                helpbox.scaleY=scaleC;
                helpbox.scaleX=2.0;
            }

            // Calculate movement/behavior for each atom.
            for (ii=0; ii<numAtoms; ii++) {
                
                origdx=dx[ii];
                origdy=dy[ii];
                
                drawX=xc[ii];
                drawY=yc[ii];
                rotAngles[ii] += rotSpeeds[ii];
                
                wasSpinningNeg = (rotSpeeds[ii] < 0);
                wasSpinningPos = (rotSpeeds[ii] > 0);
                
                // Calculate the initial translational energy.  Assume units so that mass has value of two.
                T0 = Math.sqrt(Number(dx[ii]*dx[ii])+Number(dy[ii]*dy[ii]));
                // Calculate the initial rotational (angular) energy.  Assume units so that one-half the moment of inertia is HMOI.
                W0 = HMOI*Number(rotSpeeds[ii]*rotSpeeds[ii]);


                if (doChase) {
                    //coordText.text=cursorX +", "+ cursorY + " --- CHASE";
                    cursorX=parent.mouseX;     // or use stage.mouseX ?
                    cursorY=parent.mouseY;     // or use stage.mouseY ?
/*                    if (Math.abs(cursorX-xc[ii]) > Math.abs(cursorY-yc[ii])) {
                        ddx = ( xc[ii]>cursorX ? -1 : 1 );
                        if (Math.abs(ddx) > 5.0) { ddx= (ddx < 0.0 ? -5.0 : 5.0 ); }
                        dx[ii] += ddx;
                    } else {
                        ddy = ( yc[ii]>cursorY ? -1 : 1 );
                        if (Math.abs(ddy) > 5.0) { ddy= (ddy < 0.0 ? -5.0 : 5.0 ); }
                        dy[ii] += ddy;
                    }  */
                    angle= Math.atan2(Number(yc[ii]-cursorY), Number(xc[ii]-cursorX))*180.0/Math.PI;
                    if (wildChase) {
                        angle += Math.random()*90.0-45.0;
                    } else {
                        angle += Math.random()*45.0-22.5;
                    }
                    goDirection = Math.round(angle/90.0);
                    if (attraction) { goDirection += 2; }
                    goDirection = int((goDirection < 0 ? goDirection+4 : goDirection));
                    goDirection = int((goDirection > 4 ? goDirection-4 : goDirection));
                    switch (goDirection) {
                        case 0: {    if (dx[ii]<10) { dx[ii]++; }  break;   }
                        case 1: {    if (dy[ii]<10) { dy[ii]++; }  break;   }
                        case 2: {    if (dx[ii]>-10) { dx[ii]--; }  break;   }
                        case 3: {    if (dy[ii]>-10) { dy[ii]--; }  break;   }
                        default: ;
                    }
                } // end of if (doChase) section
               //infobox.text="Got to alpha point.  xc[2]="+xc[2]+" drawX="+drawX+"\n";                
//            } else {
                    if (xc[ii]<=(xmin+xBuffer)) {      // hit left limit
                        wasLeft=true;
                        wasMovingNeg = (dy[ii]<0);
                        wasMovingPos = (dy[ii]>0);
                        dx[ii]= Math.abs(dx[ii]);    // Reflection bounce w.r.t. x-component since hit left wall
                        //xc[ii]= ((xmin+xBuffer)-xc[ii])+(xmin+xBuffer);     // Not using correct-time positioning of sphere (leads to necessary speed corrections to conserve energy and avoid runaway mechanics)
                        drawX=xmin+xBuffer;  // Position to draw sphere's center if compression is being used (i.e. sphere can approach boundary closer than its radius leading to temporary distortion to ellipse).
                        ddy = rotSpeeds[ii]/2;  // Calculate the change in velocity's y-component due to spin of sphere when in contact with boundary.
/*                        if (rotSpeeds[ii]==0) {
                            ddy = 0;
                        } else if (Math.abs(rotSpeeds[ii])<2) {
                            ddy = (ddy < 0 ? -1 : 1);
                        } else {
                            ddy = rotSpeeds[ii]/2;
                        } */
                        if (Math.abs(ddy) > 5.0) { ddy= (ddy < 0.0 ? -5.0 : 5.0 ); }
                        dy[ii] += ddy;
                    } else if (xc[ii]>=(xmax-xBuffer)) {     // hit right limit
                        
                        wasRight=true;
                        wasMovingNeg = (dy[ii]<0);
                        wasMovingPos = (dy[ii]>0);
                        dx[ii]= -Math.abs(dx[ii]);
                        //xc[ii]= -(xc[ii]-(xmaxc[ii]-xBuffer))+(xmaxc[ii]-xBuffer);
                        drawX=xmax-xBuffer;
                        ddy = -rotSpeeds[ii]/2;
                        if (Math.abs(ddy) > 5.0) { ddy= (ddy < 0.0 ? -5.0 : 5.0); }
                        rotSpeeds[ii] -= dy[ii]*3;
                        dy[ii] += ddy;
                    }
                    //infobox.appendText("Got to gamma point.\n---");
                    if (yc[ii]<=(ymin+yBuffer)) {     // hit top limit
                        //infobox.appendText("Gamma point 1.  ");
                        wasTop=true;
                        wasMovingNeg = (dx[ii]<0);
                        wasMovingPos = (dx[ii]>0);
                        dy[ii]= Math.abs(dy[ii]);
                        //yc[ii]= ((ymin+yBuffer)-yc[ii])+(ymin+yBuffer);
                        drawY=ymin+yBuffer;
                        ddx = -rotSpeeds[ii]/2;
                        if (Math.abs(ddx) > 5.0) { ddx= (ddx < 0.0 ? -5.0 : 5.0); }
                        rotSpeeds[ii] -= dx[ii]*3;
                        dx[ii] += ddx;
                    } else if (yc[ii]>=(ymax-yBuffer)) {      // hit bottom limit
                        //infobox.appendText("Gamma point 2.\n");
                        wasBottom=true;
                        wasMovingNeg = (dx[ii]<0);
                        wasMovingPos = (dx[ii]>0);
                        dy[ii]= -Math.abs(dy[ii]);
                        //yc[ii]= -(yc[ii]-(ymaxc[ii]-yBuffer))+(ymaxc[ii]-yBuffer);
                        drawY=ymax-yBuffer;
                        ddx = rotSpeeds[ii]/3;
                        if (Math.abs(ddx) > 5.0) { ddx= (ddx < 0.0 ? -5.0 : 5.0); }
                        rotSpeeds[ii] += dx[ii]*3;
                        dx[ii] += ddx;
                    } //else { infobox.appendText("Gamma point 3.\n"); }
 //               }
               
                //infobox.appendText("Got to beta point."); 
                //infobox.text="Got to beta point.  xc[2]="+xc[2]; 
                // Calculate the new translational kinetic energy.
                T1 = Math.sqrt(Number(dx[ii]*dx[ii])+Number(dy[ii]*dy[ii]));
                
                // Calculate the new rotational speed using conservation of energy.
                // ... So first calculate the change in translational kinetic energy.  Assume units giving mass of two.
                dT=T1-T0;
                // Calculate the final rotational kinetic energy.
                W1 = T0+W0-T1;
                // Calculate the final rotational speed.
                if (W1>=0.0) {
                    absFinalRotSpeed = Math.sqrt(Number(W1) / HMOI);
                    // Lastly, find the sign for the final rotational speed based on the original movements.
                    if (wasLeft) {
                        if (wasMovingNeg) { rotSpeeds[ii] = -absFinalRotSpeed; } else { rotSpeeds[ii] = absFinalRotSpeed; }
                    }
                    if (wasRight) {
                        if (wasMovingPos) { rotSpeeds[ii] = -absFinalRotSpeed; } else { rotSpeeds[ii] = absFinalRotSpeed; }
                    }
                    if (wasTop) {
                        if (wasMovingPos) { rotSpeeds[ii] = -absFinalRotSpeed; } else { rotSpeeds[ii] = absFinalRotSpeed; }
                    }
                    if (wasBottom) {
                        if (wasMovingNeg) { rotSpeeds[ii] = -absFinalRotSpeed; } else { rotSpeeds[ii] = absFinalRotSpeed; }
                    }
                }
            
                //rotSpeeds[ii] += dy[ii]*3;   // !!!! ... to be replaced with conservation-of-energy formula.
                // Done with calculating new rotational speed.
                
                
                // Some sensibility checks on final angular speed.
                if (Math.abs(rotSpeeds[ii]) > 10.0) { rotSpeeds[ii]= (rotSpeeds[ii] < 0.0 ? -10.0 : 10.0); }
                if (noRotation) { rotSpeeds[ii]=0; }
                
                //infobox.text="Changing coordinates now.";
                xc[ii] += dx[ii];
                yc[ii] += dy[ii];
//                infobox.text="xc[0], yc[0] = "+xc[0]+", "+yc[0]+"\n";
//                infobox.appendText("xc[1], yc[1] = "+xc[1]+", "+yc[1]+"\n");
//                infobox.appendText("xc[2], yc[2] = "+xc[2]+", "+yc[2]+"\n");
                
                //if (gravity && (dy[ii] < dylim)) { dy[ii]++; }
                if (gravity && (yc[ii] < ( ymax-yBuffer)))  { dy[ii]++; }
                
                rad=atoms[ii].getRadius();
                distX=Math.min(Math.abs(xc[ii]), Math.abs(xc[ii]-stage.width));
                distY=Math.min(Math.abs(yc[ii]), Math.abs(yc[ii]-stage.height));
                
                atoms[ii].SetCoordinates(drawX, drawY, 0, rotAngles[ii], distX, distY);
            } // end loop over all atoms (count variable is i)
            //infobox.appendText("delta\n");
          }  // end function _onTick
    
    
    } // end main class my3Dviewer
    
    
} // end of package




import flash.geom.Matrix; // end of package
import flash.display.*;

class myAtomClass extends Sprite {         // every atom is a Sprite-derived object

    // Declarations grouped:
    private var xc:Number = 0.0;     // actual atomic coordinates (not screen coordinates)
    private var yc:Number = 0.0;
    private var zc:Number = 0.0;
    private var an:int = 0;                // atomic number of atom
    private var elName:String = "NA";      // atomic symbol or identifier for atom
    private var vis:Boolean = true;   // whether the atom is visible
    private var xsc:int=50;
    private var ysc:int=50;
    private var theRadius:int=30;
    private var targetRadius:int=30;
    private var big:Boolean=false;
    private var isTranslucent:Boolean=false;
    private var myCircle:Shape = new Shape();


    // Functions grouped:
    public function myAtomClass():void {   // the constructor function that is automatically called upon instantiation

        // myCircle.graphics.beginFill(0x2020ff);
        var gradMatrix:Matrix = new Matrix();
        gradMatrix.createGradientBox(100, 100, Math.PI*0.40, -53, -50);  // 100% width and height, rotate (one radian), translate by zero along x and y axis.
        myCircle.graphics.beginGradientFill("radial",      // fill type (either "radial" or "linear")
                                                [0xddddff, 0x2020ff],        // colors
                                                [100, 100],                           // alphas for two colors (range: 0 to 100; for transparency(100)/opacity(0))
                                                [0, 230],                     // ratios for two colors (range: 0 to 255; spatial limits of solid colors before gradiation begins)
                                                gradMatrix,                  // the transformation matrix for scaling, rotating, and translating the gradient
                                                "pad",                          // spread method (pad just extends final colors, mirror reverses and iterates, repeat just starts over and iterates)
                                                "RGB",                        // SpreadMethod can be either RGB (default) or linearRGB
                                                -0.40);                         // focalPointRatio position from one edge of gradient circle to the other (-1 to 1)
                                                
        myCircle.graphics.lineStyle(1,                           // line thickness (pixels)
                                                0x000000,                  // color (RGB)
                                                100,                            // alpha for line (opacity; range 0-100)
                                                false,                          // pixel hinting (default: false), whether to hint strokes to full pixels
                                                "normal",                    // always scale the strokes when scaling is done
                                                "none",                       // end caps of lines
                                                "miter",                       // joint style for angles/bends
                                                1);                               // miter limit (only used if joint style is miter)
        
        //myCircle.graphics.drawCircle(xsc, ysc, theRadius);
        myCircle.graphics.drawCircle(0, 0, theRadius);
        myCircle.graphics.endFill();
        addChild(myCircle);

    } // end of constructor function myAtomClass


   public function updateAtom():void {
       // This function may not be necessary.
   }

        

    public function SetCoordinates (x:Number, y:Number, z:Number, theRotAngle:Number, distX:Number, distY:Number):void {
        this.xsc=x; this.ysc=y;
        this.rotation = theRotAngle;
        //this.myCircle.x=this.xsc; this.myCircle.y=this.ysc;
        this.x=this.xsc; this.y=this.ysc;
        this.scaleX = targetRadius/30.0;
        this.scaleY = targetRadius/30.0;
        if (targetRadius > distX) {
            //this.scaleX=targetRadius/30.0*(distX/targetRadius);
            //this.scaleX *= distX/targetRadius;
            //this.scaleY /= distX/targetRadius*1.0;
            //this.scaleX=distX/targetRadius;
        }
        if (targetRadius > distY) {
            //this.scaleY=targetRadius/30.0*(distY/targetRadius);
            //this.scaleY *= distY/targetRadius;
            //this.scaleX /= distY/targetRadius*1.0;
            //this.scaleY=distY/targetRadius;
        }
        

       this.updateAtom();   // this updateAtom function is not really used
    } // end of function SetCoordinates

    public function makeVisible():void {
        this.vis=true;
        this.myCircle.visible=this.vis;
    }
    
    public function makeInvisible():void {
        this.vis=false;
        this.myCircle.visible=this.vis;
    }
    
    public function toggleVisible():void {
        if (this.vis) {
            this.makeInvisible();
        } else {
            this.makeVisible();
        }
     }
     
     public function toggleScale():void {
         if (this.big) {
             big=false;
             //this.myCircle.scaleX=1.5;
             //this.myCircle.scaleY=1.5;
             this.changeSize(30);
             //this.scaleX=(this.scaleY=1.5);
         } else {
             big=true;
             //this.myCircle.scaleX=1.0;
             //this.myCircle.scaleY=1.0;
             this.changeSize(45);
             //this.scaleX=(this.scaleY=1.0);
         }
         
     } // end of function toggleScale


     public function toggleTranslucency():void {
         this.isTranslucent = !this.isTranslucent;
         if (this.isTranslucent) {
             myCircle.alpha=0.5;
         } else {
             myCircle.alpha=1.0;
         }
     }  // end of function toggleTranslucency


     public function changeSize(newRadius:Number):void {
         this.targetRadius = newRadius;
         this.scaleX = targetRadius/30.0;
         this.scaleY = targetRadius/30.0;
     } // end of function changeSize

    public function getRadius():int {
        return (this.targetRadius);
    }  // end of function getRadius


    public function update(ox:int, oy:int):void {
        var x:int=0;
        
    } // end of function update

    
    
    
    
} // end of class myAtomClass