cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - ActiveLovehtmlicon-new-collectionicon-personicon-teamlog-outoctocatpop-outspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              <fieldset class=right><legend>camera</legend><select id=select_camera class="planet-select"></select>
  </fieldset>
<div id="debug">
  <fieldset>
    <legend>fps</legend>
    <output id=fps></output>
  </fieldset>
  <fieldset>
    <legend>
        info
    </legend>
    <label>
      from <select id="select_vel_from" class="planet-select"></select>
    </label>
    <label>
      to <select id="select_vel_to" class="planet-select"></select>
    </label><br>
    vel:  
    <span id=output_vel></span> km/s
    |
    dist:
    <span id=output_dist></span> km
  </fieldset>
  
  <fieldset>
    <legend>time</legend>
    warp: <span id=output_warp></span>&times;
    
    <!-- zoom: <span id=output_zoom></span> -->
  </fieldset>
</div>

<div id="controls">
    <div>
    warp
  <button class=small data-action="warp_slower">&laquo;</button>
    <button class=small data-action="warp_faster">&raquo;</button>
</div>
  <div>
  
  <button data-action="zoom_out">&minus;</button>
  <button data-action="thrust_forward">↑</button>
  <button data-action="zoom_in">&plus;</button>
  
  <button data-action="turn_left">←</button>
  <button data-action="thrust_backward">↓</button>
  <button data-action="turn_right">→</button>
  </div>
    
</div>
            
          
!
            
              body {
    margin:0;
    overflow: hidden;
    background:black;
    color:white;
    font:.9em Verdana,sans-serif
}
input,select,textarea,button {
  font:inherit;
}
#controls {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 6em;
 font-size:2em;
  div {clear: both;}
  button {
    font:inherit;
    font-weight: bold;
    border:0;
    width: 2em;
    height: 2em;
    line-height: 2em;
    padding: 0;
    float: left;
    background:rgba(#000,.5);
    color:white;
    border:1px solid currentColor;
    &.small {
      height: 1em;
      width: 1em;
      line-height: 1em;
    }
    &.active {
      background:rgba(#666,.5);
    }
  }
}

fieldset {
  float: left;
  //position: absolute;
  &.right {
    float: right;
  }
}
[id=debug] {
  position: absolute;
}
[id=help] {
  position: absolute;
  left: 0;
  padding: 1em;
  background:rgba(0,0,0,.5);
  width: 25%;
  line-height: 1;
  transition:opacity .5s ease;
  opacity:1;
}
.hidden {
  opacity:0;
  pointer-events:none;
}
// canvas {cursor:none}
h1{
  margin: 0;
  font-size:1.2em;
  text-transform: uppercase;
  letter-spacing:.025em;
}
canvas{
  position: absolute;
  z-index: -1;
}
            
          
!
            
              var planets = [];
var PLANET_LIMIT=128;

var G = 6.67408e-11;
var GRAVITY_POW = 2; // Math.pow ( distance, GRAVITY_POW )

var enableTrails = false;
var space_layers = []

var TIME_FACTOR = 1;
var SHIP_THRUST = 1e6;
var SHIP_ROTATE = .1;

var draw_pow = .33;
var draw_color; 
var zoom = .000003;
var $planetSelect;
var $cameraSelect;
var $velFromSelect;
var vel_from_value = -1;
var $velToSelect;
var vel_to_value = 3;

var myCameraObject;
// var delta time 
var output_vel = document.getElementById("output_vel");

var output_dist = document.getElementById("output_dist");

var output_warp = document.getElementById("output_warp");

var output_fps = document.getElementById("fps");

var BG_COLOR;
//var output_zoom = document.getElementById("output_zoom");

function mouseWheel(e) {
  var d = e.delta > 0 ? 1/1.1 : 1.1;
  zoom *= d
  resetTrails();
}
function resetTrails() {
  for (var x = 0; x < planets.length; x++) {
    planets[x].locHistory = [];
  }
  myShip.locHistory = [];
  background(0);
}

var maskImage;


function preload() {
  preload_planet_images(start_planets);
  
  maskImage = loadImage('https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/mask.png');
}

function preload_planet_images(obj) {
  for(var x=0;x<obj.length; x++) {
    if (obj.hasOwnProperty(x)) {
      
      var p = obj[x];
      if (p.image) {
        p.img = loadImage(p.image);
      }
      if (p.children) {
        preload_planet_images(p.children);
      }
    }
  }
}

var start_planets = [
  {name:'sun',
   mass:1.9884e32,
   dist:0,
   density:1.408,
   vel:0,
   image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/sun.jpg',
   color:[255,255,0],
   children:[
  {
    name:'mercury',
    mass:3.301e25,
    dist:5.7909e10,
    density:5.427,
    vel:47.36,
    color:[200,100,0],
    image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/mercury.jpg'
  },
  {
    name:'venus',
    mass: 4.869e26, 
    dist:1.0816e11,
    density:5.243,
    vel:35.02,
    color:[100,0,200],
    image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/venus.jpg'
  },
  {
    name:'earth',
    mass: 5.974e26,
    dist:1.496e11,
    density:5.515,
    vel:29.78,
    color:[0,0,255],
    image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/earth.jpg',
    children: [{
      name:'moon',
      mass:7.349e24, 
      density:3.341,
      color:[200,200,100],
      dist:-3.8440000e8,
      vel:1.023,
      image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/moon.jpg'
    }]
  },
  {
    name:'mars',
    mass:6.419e25,
    dist:2.2799e11,
    vel:24.13,
    density:3.933,
    color:[255,0,0],
    image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/mars.jpg',
    children:[{
      name:'phobos',
      mass:1.072e18,
      vel:2.139,
      dist:-9378000,
      density:1.471,
    },
    {
      name:'deimos',
      mass:1.8e17,
      vel:1.351,
      dist:-23459000,
      density:1.471
    }]
  },
  {
    name:'jupiter',
    mass:1.899e29 ,
    dist:7.7836e11,
    vel:13.07,
    density:1.326,
    color:[200,100,50],
    image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/jupiter.jpg',
    children: [{
      name:'io',
      mass:8.9e24,
      density:3.56,
      dist:4.218e8,
      vel:17.3,
      color:[100,200,0],
      image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/io.jpg'
    },{
      name:'europa',
      mass:4.8e24,
      density:3.01,
      dist:6.71100e8,
      vel:13.74,
      color:[200,100,0],
      image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/europa.jpg',
    },
    {
      name:'ganymed',
      mass:1.482e25,
      density:1.940,
      vel:10.88,
      dist:1.0704e9,
      color:[170,160,150],
      image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/ganymed.jpg',
    },
    {
      name:'callisto',
      mass:1.1e25,
      density:1.83,
      dist:1.8827e9,
      vel:8.2,
      color:[150,100,100],
      image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/callisto.jpg'
      
    },
    {
      name:'amalthea',
      mass:2.1e20,
      density:0.85,
      dist:1.81400e8,
      vel:26.49,
      image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/amalthea.jpg'
    },
    {
      name:'himalia',
      mass:6.7e20,
      density:2.6,
      dist:1.1461e10,
      vel:3.3,
    },
    {
      name:'elara',
      mass:8.66e19,
      density:2.6,
      dist:1.1741e10,
      vel:3.25,
    }
    ]
  } ,
     {
       name:'saturn',
       mass:5.685e28,
       density:0.687,
       dist:1.4335e12,
       vel:9.69,
       color:[220,180,150],
       image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/saturn.png',
       imageScale:2.35,
       children:[{
         name:'mimas',
         mass:3.75e21,
         dist:1.856e8,
         vel:14.322,
         density:1.1479,
         color:[100,100,100],
         image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/mimas.jpg'
       },
       {
         name:'enceladus',
         mass:1.08e22,
         dist:2.381e8,
         vel:12.6353,
         color:[150,150,220],
         density:1.608,
         image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/enceladus.jpg'
       },
                 {
                   name:'tethys',
                   mass:6.18e22,
                   dist:2.947e8,
                   density:0.984,
                   vel:11.35,
                   color:[160,160,160],
                   image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/tethys.jpg',
                 },
                 {
                   name:'dione',
                   mass:1.096e23,
                   dist:3.7742e8,
                   vel:10.03,
                   density:1.476,
                   image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/dione.jpg',
                 },
                 {
                   name:'rhea',
                   mass:2.3166e23,
                   dist:5.2704e8,
                   vel:8.48,
                   color:[180,180,200],
                   image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/rhea.jpg',
                 },
                 {
                   name:'titan',
                   mass:1.345e25,
                   density:1.88,
                   dist:1.22183e9,
                   vel:5.57,
                   color:[250,230,120],
                   image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/titan.jpg',
                 },
                 {
                   name:'hyperion',
                   mass:5.6199e20,
                   dist:1.4641e9,
                   vel:5,
                   color:[220,180,140],
                 },
                 {
                   name:'iapetus',
                   mass:1.6e23,
                   color:[160,220,170],
                   dist:3.5613e9,
                   vel:3.26,
                   density:1.27,
                   image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/iapetus.jpg',
                 },
                 {
                   name:'phoebe',
                   mass:8.3e20,
                   vel:1.7,
                   dist:1.2952e10
                 },
                 
       ],
       
     },
     {
       name:'uranus',
       mass:8.683e27,
       dist:2.8724e12,
       vel:6.81,
       color:[50,200,200],
       image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/uranus.jpg',
       children:[{
         name:'ariel',
         mass:1.353e23,
         vel:5.51,
         dist:1.909e8,
         density:1.66,
         image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/ariel.jpg',
         
       },
                 {
                   name:'umbriel',
                   mass:1.72e23,
                   dist:2.663e8,
                   vel:4.67,
                   image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/umbriel.jpg',
                 },
                 
       {
         name:'titania',
         mass:3.527e23,
         dist:4.363e8,
         vel:3.87,
         color:[230,190,140],  
         density:1.711,
         image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/titania.jpg'
       },
                 {
                   name:'oberon',
                   mass:3.014e23,
                   dist:5.83519e8,
                   vel:3.15,
                   color:[220,160,200],
                   image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/oberon.jpg',
                 },
                 {
                   name:'miranda',
                   mass:6.59e21,
                   dist:1.29872e8,
                   vel:6.68,
                   color:[240,240,240],
                   
                 }
       ]
     },
     {
       name:'neptun',
       mass:1.0243e28,
       dist:4.4984e12,
       vel:5.43,
       color:[50,0,255],
       image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/neptun.jpg',
       children:[{
         name:'triton',
         mass:2.1e24,
         dist:3.54759e8,
         vel:4.39,
         color:[240,230,150],
         image:'https://s3-us-west-2.amazonaws.com/s.cdpn.io/36559/triton.jpg'
         
       },
                 {
                   name:'proteus',
                   mass:5e21,
                   vel:7.623,
                   dist:1.17647e8,
                   
                 },
                 {
                   name:'nereid',
                   mass:3.1e21,
                   vel:.934,
                   dist:5.513787e9
                 }
                 ]
     }
   ]
  },
  
]

function createAllChildren(p,pl) {
  for (var x = 0; x < p.children.length; x++) {
    var cp = p.children[x]; 
    if (cp.dist && cp.mass) {
    var cpl = new Planet(cp.name, cp.dist+pl.loc.x,pl.loc.y,cp.mass,cp.density?cp.density:1, cp.color?color(cp.color):undefined, cp.img?cp.img:undefined,pl.vel.x, -cp.vel*1e4 + pl.vel.y, pl, cp.imageScale)
    planets.push(cpl); 
   //console.log("created " + cp.name);
    if (cp.children) {
      createAllChildren(cp,cpl);
    }
    }

  }
}

function setup() {
  
 for ( var x = 0; x < start_planets.length; x++) {
   var p = start_planets[x];
   var pl = new Planet(p.name, p.dist,0,p.mass, p.density?p.density:1, p.color?color(p.color):undefined,p.img?p.img:undefined,0,-p.vel*1e4,undefined,p.imageScale);
   planets.push(pl);
   
   //console.log("created " + p.name);
   if (p.children) {
     
   createAllChildren(p,pl);
   }
   
 } 
  
  var earth = start_planets[0].children[2];
  
  var ship_distance =  6.317e6 + 400000;
  var ship_vel = 7.777*1e5;
  
  myShip = new Ship(earth.dist + ship_distance,0,0,(-earth.vel*1e4-ship_vel));
  createCanvas(window.innerWidth, window.innerHeight);
  
  noStroke();
  $planetSelect = $('.planet-select');
  $planetSelect.append("<option value=-1>ship</option>");
  
  var $actionButtons = $("button[data-action]")
  $actionButtons.on("mousedown touchstart", function(e) {
    var $this = $(this);
    var action = $this.data("action");
    $this.addClass("active");
    if (action == "zoom_in") {
      zoom*=1.1;
    }
    if (action == "zoom_out") {
      zoom/=1.1;
    }
    if (action == "thrust_forward") {
      THRUST_FORWARDS = true;
    }
    if (action == "thrust_backward") {
      THRUST_BACKWARDS = true;
    }
    if (action == "turn_left") {
      ROTATE_LEFT = true;
    }
    if (action == "turn_right") {
      ROTATE_RIGHT = true;
    }
    
    if(action=="warp_faster") {
      TIME_FACTOR *= 1.1;
      if (TIME_FACTOR > 50000) TIME_FACTOR = 50000;
    }
    if(action=="warp_slower") {
      TIME_FACTOR /= 1.1;
      if (TIME_FACTOR < 1) TIME_FACTOR = 1;
    }
    //e.preventDefault();
    //return false;
  });
  $actionButtons.on("touchmove", function() {
    return false;
  });
  
  $actionButtons.on("touchend touchleave mouseup mouseleave", function() {
    var $this = $(this);
    var action = $this.data("action");
    $this.removeClass("active");
    
    if (action == "thrust_forward") {
      THRUST_FORWARDS = false;
    }
    if (action == "thrust_backward") {
      THRUST_BACKWARDS = false;
    }
    if(action == "turn_left") {
      ROTATE_LEFT = false;
    }
    if(action=="turn_right") {
      ROTATE_RIGHT = false;
    }
    return false;
  })
  
  function getParentIndent(p) {
    var returnStr = "";
    
    if (p.parent) {
      returnStr = "┖&nbsp;";
      while(p.parent) {
        returnStr = "&nbsp;&nbsp;" + returnStr;

        p = p.parent
      }
    }
    
    return returnStr;
  }
  
  for (var x = 0; x < planets.length; x++) {
    
    
    $planetSelect.append("<option value='"+x+"'>" + getParentIndent(planets[x]) + planets[x].name + "</option>");
  }
  $cameraSelect = $("#select_camera");
  $cameraSelect.change(function() {
    if (this.value > -1) {
      myCameraObject = planets[this.value];
    } else {
      myCameraObject = myShip;
    }
    
    resetTrails();
  })
  
  
  $velFromSelect = $("#select_vel_from");
  $velFromSelect.val(vel_from_value );
  $velFromSelect.change(function() {
    vel_from_value = this.value;
  })
  $velToSelect = $("#select_vel_to");
  $velToSelect.val(vel_to_value);
  $velToSelect.change(function() {
    vel_to_value = this.value;
  })
   
  //setup_space_layers();
  
  myCameraObject = myShip; 
  BG_COLOR = color(30,0,30);
  background(BG_COLOR);
  frameRate(60);
}
function windowResized() {
  resizeCanvas(window.innerWidth, window.innerHeight);
  setup_space_layers();
}



// add new planets by "throwing"
var start_x=0, start_y=0,start_frame=0, mouse_dragging=false;



var THRUST_FORWARDS = false, THRUST_BACKWARDS = false, ROTATE_LEFT = false, ROTATE_RIGHT = false;
var prev_millis = 0;
var delta_millis = 0;
var myShip;
var prev_fps=60;

var zoom_translate_x = 0, zoom_translate_y = 0; 
function draw() {
  
  var milli = millis();
  delta_millis = 1;
  
  
  //document.getElementById("debug").innerHTML = "ZOOM:" + zoom + " | " + 
    //                    "TIME: " + TIME_FACTOR.toFixed(0) + " x | " + 
    //                    "VEL: " + myShip.vel.mag().toFixed(0) + "m/s"  ;
  var i = getRelativeInfo();   
  
  output_vel.innerHTML = i.vel;
  output_dist.innerHTML = i.dist;
  
  var fps = 1000/(milli - prev_millis);
  prev_fps = Math.floor(lerp(prev_fps,fps,.1));
  output_fps.innerHTML = prev_fps;
  
  //output_zoom.innerHTML = zoom;
  output_warp.innerHTML = TIME_FACTOR.toFixed(1);
  
  var delta_t = delta_millis * TIME_FACTOR / 100;
  
  translate(width/2, height/2);
  zoom_translate_x = -myCameraObject.loc.x * zoom ; 
  zoom_translate_y = -myCameraObject.loc.y * zoom ;
  translate(-myCameraObject.loc.x, -myCameraObject.loc_y);
  //rotate(-myShip.rotation);
   background(BG_COLOR);
  //draw_space_layers(myCameraObject.loc.x,myCameraObject.loc.y);
 
  //translate(width/2,height/2);
  noStroke();
  for(var x=0; x < planets.length-1; x++) {
    var p = planets[x];
    if (p.r)  {
      if (myShip.loc.dist(p.loc) * 2 > p.r*.98 ) {
        myShip.attract(p);
      } else { 
        myShip.bounceOff(p);
      }
    }
    // n body
    for (var ox=0; ox < planets.length; ox++) {
      if (x !== ox) {
        var op = planets[ox];
        p.attract(op);
        
      }
      
    }
    
    // 2 body
    //if (p.parent !== null) {
     //p.attract(p.parent, delta_millis); 
    //}
  }
  for(var x=0; x < planets.length; x++) {
   var p = planets[x];
   
      p.draw();
      p.update(delta_t);
    
  } 
  if (THRUST_FORWARDS) {
    var v = new p5.Vector(0, -SHIP_THRUST);
    v.rotate(myShip.rotation);
    myShip.applyForce(v);
  }
  if (THRUST_BACKWARDS) {
    var v = new p5.Vector(0, SHIP_THRUST);
    v.rotate(myShip.rotation);
    myShip.applyForce(v);
  }
  if (ROTATE_LEFT) {
    myShip.applyRadialForce(-SHIP_ROTATE/TIME_FACTOR);
  }
  if (ROTATE_RIGHT) {
    myShip.applyRadialForce(SHIP_ROTATE/TIME_FACTOR);
  }
      
      
  myShip.draw(); 
  myShip.update(delta_t); 
  //rotate(myShip.rotation);
  
  prev_millis = milli;
}
function getRelativeInfo() {
  if (vel_from_value == vel_to_value) return 0;
  var v_from,v_to;
  var d_from,d_to;
  
  if (vel_from_value == -1) {
    v_from = myShip.vel;
    d_from = myShip.loc;
  } else {
    var p = planets[vel_from_value];  
   v_from = p.vel;  
    d_from = p.loc;
  }
   
  if (vel_to_value == -1) {
    v_to = myShip.vel;
    d_to = myShip.loc;
  } else {
    var p = planets[vel_to_value];
    v_to = p.vel;
    d_to = p.loc;
  }
  var v_delta = p5.Vector.sub(v_from,v_to);
  var d = p5.Vector.sub(d_from,d_to);
  return {
    vel:(v_delta.mag() / 10000).toFixed(1),
    dist:(d.mag()/1000).toFixed(1)
  }
}

function keyPressed(e) {
  //console.log (e)
  if (e.key=="c") {
    draw_color = getRandomColor();
    return false;
  } else if (e.key == "e") {
    planets = [];
  } else if (e.key == '+') {
    TIME_FACTOR *= 1.1;
    if (TIME_FACTOR > 50000) TIME_FACTOR = 50000;
  } else if (e.key == '-') {
    TIME_FACTOR *= .9;
    if (TIME_FACTOR < 1) TIME_FACTOR = 1;
  } else if (e.key == "h") {
    document.getElementById("help").classList.toggle("hidden");
  } else if (e.keyCode == LEFT_ARROW ) {
    ROTATE_LEFT = true;
    
  } else if (e.keyCode == RIGHT_ARROW) {
    
    ROTATE_RIGHT = true;
  } else if (e.keyCode == UP_ARROW) {
    THRUST_FORWARDS = true;
    
  } else if (e.keyCode == DOWN_ARROW) {
    THRUST_BACKWARDS = true;
  }
    
}
function keyReleased(e) {
  if (e.keyCode == UP_ARROW) {
    THRUST_FORWARDS = false;
  } else if (e.keyCode == DOWN_ARROW) {
    THRUST_BACKWARDS = false;
  } else if (e.keyCode == LEFT_ARROW) {
    ROTATE_LEFT = false;
  } else if (e.keyCode == RIGHT_ARROW) {
    ROTATE_RIGHT = false;
  }
  
  
} 


function Planet(name, x,y,mass,density,c,img,vx, vy, parent_planet, imgScale) {
  this.loc = new p5.Vector(x,y);
  this.name = name;
  this.locHistory = [];
  
  vx = vx || 0;
  vy = vy || 0;
  this.vel = new p5.Vector(vx,vy);
  this.acc = new p5.Vector();
  
  if (typeof parent_planet == "undefined") parent_planet = null;
  this.parent = parent_planet;
  if (typeof img !== "undefined")  {
    this.image = img;
    this.image.mask(maskImage);
  }
  if (typeof imgScale !== "undefined") {
    this.imageScale = imgScale;
  }
  if (typeof c == "undefined") c = color(128);
  this.color = c;
  this.density = density;
  if (typeof mass == "undefined") mass = 100;
  this.mass = mass;
  this.r = getPlanetSize(this.mass, this.density);
  
  this.is_alive = true;
}
Planet.prototype.applyForce = function(v) {
  if (this.is_alive) {
    v.div(this.mass);
    this.acc.add(v);
  }
}
Planet.prototype.attract = function(other_planet) {
  var force = p5.Vector.sub(this.loc,other_planet.loc); // find the vector of the force
  var d = force.mag();              // and the distance
  force.normalize();   
  var strength =  -(G * this.mass * other_planet.mass) / Math.pow(d, GRAVITY_POW);  
  force.mult(strength);   
  this.applyForce(force);
}
Planet.prototype.update = function(delta_t) {
  if (typeof delta_t === "undefined") delta_t = 1;
  
  if (this.is_alive) {
    this.vel.add(p5.Vector.mult(this.acc, delta_t)); 
    this.loc.add(p5.Vector.mult(this.vel, delta_t ));
    this.acc.mult(0);
  }
}
Planet.prototype.draw = function() {
  if (this.is_alive) {
    
    
    var x_pos = zoom_translate_x + this.loc.x*zoom;
    var y_pos = zoom_translate_y + this.loc.y*zoom;
    var d = this.r * zoom; // /2*zoom+Math.pow(2 * (1-zoom) * this.mass,.1)/100;
    
    // draw trail:
    if (enableTrails && this !== myCameraObject) {   
      noFill();
      stroke(this.color);
      strokeWeight(2);
      beginShape();
      for (var x = 0; x < this.locHistory.length; x++) {curveVertex(this.locHistory[x].x,this.locHistory[x].y);
                                                       }
      endShape();
      if (this.locHistory.length > 1000) {
        this.locHistory.splice(0,1);
      }
      this.locHistory.push({
        x:x_pos,y:y_pos
      });
        noStroke();
    }
    
    if (this.name == "earth") {
      //console.log(this.name + ": " + x_pos + " : " + y_pos);
    }
    if ((x_pos + this.r*zoom) > (-width/2) && 
        (x_pos - this.r*zoom) < (width/2) && 
        (y_pos + this.r*zoom) > (-height/2) && 
        (y_pos - this.r*zoom) < (height/2) )  {
      if(this.image) {
        if (d>1) {
          var dd = d;
          if (this.imageScale) {
            dd = dd * this.imageScale;
          }
          
          
        image(this.image,x_pos-dd/2,y_pos-dd/2,dd,dd);
        }
        noFill();
        stroke(this.color)
        ellipse(x_pos,y_pos,d*.98);
        
        noFill();
      } else {
        noStroke();
        fill(this.color);
        ellipse(x_pos,y_pos,d);
      }
    }
  }
}
Planet.prototype.eats = function(other_planet) {
  if (this.is_alive && other_planet.is_alive) {
    var totalMass = (this.mass+other_planet.mass);
    // weight location accordion to mass
    
    this.color = lerpColor(other_planet.color, this.color, this.mass/totalMass);
    
    var loc = p5.Vector.lerp(other_planet.loc,this.loc,this.mass / totalMass )
    
    var vel = p5.Vector.add(p5.Vector.mult(this.vel, this.mass / totalMass)   ,
                            p5.Vector.mult(other_planet.vel, other_planet.mass / totalMass));

    this.mass = totalMass;
    
    this.r = 
      (this.mass);
    this.loc = loc;
    this.vel = vel;

    other_planet.is_alive = false;
  }
}

function Ship(loc_x,loc_y,vel_x, vel_y) {
  this.loc = new p5.Vector(loc_x,loc_y);
  this.vel = new p5.Vector(vel_x,vel_y);
  this.acc = new p5.Vector();
  
  this.rotation = 0; 
  this.rotation_vel = 0;
  
  this.height = 20;
  this.width = 10;
  this.tipHeight = 6; 
  
  this.mass = 100;
  this.locHistory=[];
 
}
function getPlanetSize(mass, density) {  
  if (typeof density === "undefined") density = 1;
  
  var r = Math.pow(mass/(16500*density*Math.PI), 1/3);
  
  return r;
}
Ship.prototype.update = function(delta_t) {
  if (typeof delta_t == "undefined") delta_t = 1;
  
  this.vel.add(p5.Vector.mult(this.acc,delta_t));
  this.loc.add(p5.Vector.mult(this.vel,delta_t));
  
  this.acc.mult(0);
  this.rotation += this.rotation_vel * delta_t;
  this.rotation_vel*=.98;
}
Ship.prototype.attract = function(p) {
  var force = p5.Vector.sub(this.loc,p.loc); // find the vector of the force
  var d = force.mag();              // and the distance
  force.normalize();   
  var strength =  -(G * this.mass * p.mass) / Math.pow(d, GRAVITY_POW);  
  force.mult(strength);   
  this.applyForce(force);
}
Ship.prototype.applyRadialForce = function(r) {
  this.rotation_vel += r; 
}
Ship.prototype.applyForce = function(v) {
  this.acc.add(v);
}
Ship.prototype.bounceOff = function(p) {
  var direction = p5.Vector.sub(this.loc, p.loc);
  var relative_vel= p5.Vector.sub(p.vel, this.vel);
  
  this.vel.add(relative_vel);
  
}
Ship.prototype.draw = function() {
  //translate(x_pos,y_pos);
  var x_pos = this.loc.x*zoom + zoom_translate_x;
  var y_pos = this.loc.y*zoom + zoom_translate_y;
  
  if (enableTrails && this !== myCameraObject) {
    
    noFill();
    stroke(200);
    strokeWeight(2);
    
    beginShape();
    for (var x = 0; x < this.locHistory.length; x++) {
      curveVertex(this.locHistory[x].x, this.locHistory[x].y);
    }
    endShape();
    
    
    if (this.locHistory.length > 1000) this.locHistory.splice(0,1);
    this.locHistory.push({
      x:x_pos,y:y_pos
    });
    noStroke();
  }
  translate(x_pos,y_pos);
  rotate(this.rotation);
  
     stroke(255,255,0);
  if (THRUST_FORWARDS) {
    fill(255-random(50),128+random(50),0);
    
    triangle( + -this.width/2+2,+this.height/2, 
              + random(-4,4),  + this.height/2 + random(8,11),
              + this.width/2-2,  + this.height/2);
  }
  if (THRUST_BACKWARDS) {
    fill(255-random(50),128+random(50),0);
    
    triangle( + -this.width/2+1,  + -this.height/2+this.tipHeight,
              + random(-2,2), -this.height/2 - random(8,11),
              + this.width/2-1, -this.height/2+ this.tipHeight);
  }
  
    noStroke();
    fill(200);
    triangle(-this.width/2, -this.height/2+this.tipHeight, 0, -this.height/2,  + this.width/2, -this.height/2 + this.tipHeight); 
    rect(-this.width/2,-this.height/2+this.tipHeight, this.width, this.height-this.tipHeight);
}
function getRandomColor(saturation, brightness) {
  if (typeof saturation == "undefined") saturation = 100;
  if (typeof brightness == "undefined") brightness = 100;
  
  return color(random(360),saturation,brightness);  
}
  



  function setup_space_layers() {
  
  space_layers[0] = createGraphics(width,height);
  fillWithRandomStars(space_layers[0],100,128,2);
  
  space_layers[1] = createGraphics(width,height);
  fillWithRandomStars(space_layers[1],500,112,2);
  
  space_layers[2] = createGraphics(width,height);
  fillWithRandomStars(space_layers[2],1000,96,2);
  
  space_layers[3] = createGraphics(width,height);
  fillWithRandomStars(space_layers[3],2000,80,1);
  
  space_layers[4] = createGraphics(width,height);
  fillWithRandomStars(space_layers[4],5000,64,1);
  
}

function draw_space_layers(offset_x, offset_y) {
  push();
  
  for (var x = 0; x < space_layers.length; x++) {
    if (space_layers[x]) {
      
      var ox = (offset_x)/(x+1);
      var oy = (offset_y)/((x+1));
      
      var z = Math.pow(zoom,1/10);
      var w = width*z; // *z+zoom_translate_x; 
      var h = height*z; // *z+zoom_translate_y;
      
      var ox = ((1e24 - ox) % w) * z;
      var oy = ((1e24 - ox) % h) * z; 
      
     // console.log("ox: ", ox, "oy: ", oy);
//       while(ox > width) ox -= width;
//       while (oy > height) oy -= height;
//       while (ox < -width) ox += width;
//       while (oy < -height) oy += height;
      image(space_layers[x],ox-w/2,oy-h/2,w,h);
      if (ox>w/2) {
        image(space_layers[x],ox-w/2*3,oy-h/2,w,h);
      }
      if (ox < -w/2) { 
        image(space_layers[x],ox+w/2,oy-h/2,w,h);
      }
      
      if(oy > 0) {
        image(space_layers[x],ox-w/2,oy-h/2*3,w,h);
      }
      if(oy < zoom_translate_y) {
        image(space_layers[x],ox-w/2,oy+h/2,w,h);
      }
      
      if (ox > zoom_translate_x && oy > zoom_translate_y) {
        image(space_layers[x],ox-w/2*3,oy-h/2*3,w,h);
      }
     
      if (ox > zoom_translate_x && oy < zoom_translate_y) {
        image(space_layers[x],ox-w/2*3,oy+h/2,w,h);
      }
            
      if (ox < zoom_translate_x && oy > zoom_translate_y) {
        image(space_layers[x],ox+w/2,oy-h/2*3,w,h);
      }
            
      if (ox < zoom_translate_x && oy < zoom_translate_y) {
        image(space_layers[x],ox+w/2,oy+h/2,w,h);
      }
    }
  }
  pop();
}
function fillWithRandomStars(g,n, alpha,size) {
  if (typeof alpha == "undefined") alpha = 255;
  if (typeof size == "undefined") size = 2;
  g.stroke(255,alpha);
  g.strokeWeight(size);
  for (var x = 0; x < n; x++)  {
    g.point(random(width), random(height));
  }
}
            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.
Loading ..................

Console