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

Newtonian Gravitation

Newton's Law of [Universal] Gravitation:
F = (g * (m1*m2 / r^2))

Click and drag either sprite to observe Newtonian Gravitation

Improper (by some margin.. eg: Still using some trace amounts of flow control -> stopping sprite at edge of radius)

This is also still incorrect by some degree but a much more adamant solution in comparison to previous gravitational simulations I have written.

The pseudo-mass variables within this algorithm are using position and sprite radius to determine their magnitude, which makes for interesting results (planet-size sprites have much, much stronger gravitation)

Although Newtonian gravitation is no longer true in physical application/examination, it is quite a close estimation of how gravity works. Einstein's investigations into gravity are much more spot on though - relativity is today's contemporary Occam's Razor since it holds true beyond instances that Newton's formula could not apply to

TODO:

-Write 'Forces' class
-Optimize ALL math
Get Adobe Flash player
by hemingway 22 Nov 2014

    Talk

    signedvoid at 23 Nov 2012 10:09
    Add inertia and orbit motion, please!
    hemingway at 23 Nov 2012 23:09
    here is the order of changes to come: 1. smooth collision correction 2. include inertia (possibly through forces class, propagating gravity to this new class as well) 3. reduce render time consumption via mathematical shortcuts orbital motion is merely a result of inertia & gravity, situationally of course
    hemingway at 27 Nov 2012 00:28
    collision correction has now been implemented, although i am missing a key component to this solution which is to apply an acceleration of gravity (to a body) which is deducted by the difference in distance from the radial limits of two related bodies. doing this will prevent the bodies from 'shaking' or rather bouncing off of each other as they're colliding. if you fork or edit this code, change the gravity constant to a higher value and you will notice the significant amount of bouncing between bodies. the constant was purposely lowered for this revision to hide the 'shaking'
    Embed
/**
 * Copyright hemingway ( http://wonderfl.net/user/hemingway )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/qSz1
 */

package
{
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    
    [SWF(frameRate = 60, width = 465, height = 465)]
    public class Newton extends Sprite
    {
        public static const G:Number = 3;
        
        internal var gravBody :GravBody;
        
        public var bodyArray:Array = [gravBody, gravBody, gravBody, gravBody, gravBody];
        
        public function Newton()
        {
            stage.scaleMode = StageScaleMode.NO_SCALE;    
            
            addEventListener(Event.ADDED_TO_STAGE, addedToStage);
        }
        
        public function _init() :void
        {
            for (var $children:Number = 0; $children < bodyArray.length; $children++)
                {bodyArray[$children] = new GravBody(bodyArray, Math.random() * 465, Math.random() * 465, 4 + Math.random()*60); addChild(bodyArray[$children]);}

            //graphics.clear     ();
            //graphics.lineStyle (1, 0, 0.75);
            //graphics.drawRect  (0, 0, 462, 464);
        }
        
        public function addedToStage($e:Event) :void
        {
            stage.removeEventListener(Event.ADDED_TO_STAGE, addedToStage); 
            
            _init();
        }
    }
}

import flash.display.*;
import flash.events.*;
import flash.geom.*;

class GravBody extends Sprite
{
    protected var _c:Number;
    protected var _a:Number;
    protected var _x:Number;
    protected var _y:Number;
    protected var _r:Number;

    protected var _vX:Number;
    protected var _vY:Number;
    
    private var _drag:Boolean = false;
    
    internal var bodyArray:Array;
    
    public function GravBody($bodyArray:Array, $x:Number = 232.5, $y:Number = 232.5, $r:Number = 20, $c:Number = 0, $a:Number = 0.5)
    {
        addEventListener(Event.ADDED_TO_STAGE, addedToStage);
        
        bodyArray = $bodyArray;
        _c = $c;
        _a = $a;
        _x = $x;
        _y = $y;
        _r = $r;
    }
    
    public function _init() :void
    {
        graphics.clear      ();
        graphics.beginFill  (_c, _a);
        graphics.drawCircle (_x, _y, _r);
    }
    
    public function addedToStage($e:Event) :void
    {
        removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
        
        addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
        addEventListener(Event.ENTER_FRAME, onEnterFrame);
        
        _init();
    }

    internal var oldPoint :Point = new Point();
    internal var newPoint :Point = new Point();
    internal var clcPoint :Point = new Point();
    
    public function onMouseDown($e:MouseEvent) :void
    {
        oldPoint = new Point($e.stageX, $e.stageY);
        
        _drag = true;
    
        stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
    }
    
    public function onMouseMove($e:MouseEvent) :void
    {
        newPoint = new Point($e.stageX, $e.stageY);
        clcPoint = Point(newPoint.subtract(oldPoint));
        
        x += clcPoint.x;
        y += clcPoint.y;
        
        oldPoint = newPoint;
    }
    
    public function onMouseUp($e:MouseEvent) :void
    {
        stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
        stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        
        _drag = false;
    }
    
    public function onEnterFrame($e:Event) :void
    {
        applyForces(bodyArray)
    }

    public function applyForces($array:Array) :void
    {
        if ($array.length > 1)
        {
            for (var $index:Number = 0; $index < $array.length; $index++)
            {
                if (this != $array[$index])
                {
                    var body1:GravBody = this;
                    var body2:GravBody = $array[$index];
                    
                    var $sum     :Number = (body1.radius + body2.radius);
                    var $distX1  :Number = (body2.x - body1.x);
                    var $distY1  :Number = (body2.y - body1.y);
                    var $distX2  :Number = (body1.x - body2.x);
                    var $distY2  :Number = (body1.y - body2.y);
                    var $dist1   :Number = Point.distance(new Point(body1.x, body1.y), new Point(body2.x, body2.y));
                    var $dist2   :Number = Point.distance(new Point(body2.x, body2.y), new Point(body1.x, body1.y));
                    var $forceX1 :Number = ($distX1 / $dist1);
                    var $forceY1 :Number = ($distY1 / $dist1);
                    var $forceX2 :Number = ($distX2 / $dist2);
                    var $forceY2 :Number = ($distY2 / $dist2);
                    var $force1  :Number = ($dist1 - $sum);
                    var $force2  :Number = ($dist2 - $sum);
                    var $mass1   :Point = new Point((body2.x - body1.x) * body2.radius, (body2.y - body1.y) * body2.radius);
                    var $mass2   :Point = new Point((body1.x - body2.x) * body1.radius, (body1.y - body2.y) * body1.radius);

                    body1.vX = Newton.G * ($mass1.x / Math.pow(($dist1 + $sum), 2));
                    body1.vY = Newton.G * ($mass1.y / Math.pow(($dist1 + $sum), 2));
                    body2.vX = Newton.G * ($mass2.x / Math.pow(($dist2 + $sum), 2));
                    body2.vY = Newton.G * ($mass2.y / Math.pow(($dist2 + $sum), 2)); 

                    if (!body1.drag && !body2.drag)
                    {   
                        x += (clcPoint.x / 64);
                        y += (clcPoint.y / 64);
                        
                        if ((($force1 + $force2) / 2) >= 0)
                        {
                            body1.x += body1.vX;
                            body1.y += body1.vY;
                            body2.x += body2.vX;
                            body2.y += body2.vY;
                        }else{
                            body1.x += ($force1 * $forceX1);
                            body1.y += ($force1 * $forceY1);
                            body2.x += ($force2 * $forceX2);
                            body2.y += ($force2 * $forceY2);
                        }
                    }
                }
            }
        }
    }
    
    public function get color() :Number
    { return _c }
    
    public override function get alpha() :Number
    { return _a }
    
    public override function get x() :Number
    { return _x }
    
    public override function get y() :Number
    { return _y }
    
    public function get radius() :Number
    { return _r }
    
    public function get vX() :Number
    { return _vX }
    
    public function get vY() :Number
    { return _vY }
    
    public function get drag() :Boolean
    { return _drag }
    
    public function set color($value:Number) :void
    { _c = $value; _init(); }
    
    public override function set alpha($value:Number) :void
    { _a = $value; _init(); }
    
    public override function set x($value:Number) :void
    { _x = $value; _init(); }
    
    public override function set y($value:Number) :void
    { _y = $value; _init(); }
    
    public function set radius($value:Number) :void
    { _r = $value; _init(); }
    
    public function set vX($value:Number) :void
    { _vX = $value; _init(); }
    
    public function set vY($value:Number) :void
    { _vY = $value; _init(); }
}