Newtonian Gravitation

by hemingway
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
♥2 | Line 174 | Modified 2014-11-22 09:06:20 | MIT License
play

ActionScript3 source code

/**
 * 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(); }
}