This article is about coding orbital mechanics in javascript and learning the equations needed for creating a demo. This article assumes you already have some experience with coding in javascript.

Listen, I like getting right to writing code as much as the next person, but there are a few things we need to learn before that. We will learn about computing the distance between points, calculating the amount of force acting upon an object using Newtons gravity equation, and computing the direction of a vector.

The distance between points

Computing the distance between two points is easy. This is the equation for doing so.

d = sqrt((x1 - x0)^2 + (y1 - y0)^2)

Newton's law of gravity

This is probably the most complicated part of this article, but once you understand it everything else will be simple in comparison. In this equation, F is equal to the amount of force in newtons (N) acting upon an object.

G is the gravitational constant. M and m is the mass of the two objects we are calculating, and d is the distance between the two objects.

F = (G * m * M) / d^2

The direction of a vector

o = atan2(x1 - x0, y1 - y0)
Fx = cos(o) * F
Fy = sin(o) * F

Astronomical units

Astronomical units are a way of measuring distances in space and is what works best for large distances like between planets and moons. An astronomical unit is the distance between the center of the sun to the center of the earth and is defined as AU = 149.6e9, or about 150 million kilometers.

A demo

This is not to scale.

This is the code

const width = 400;
const height = 400;
const G = 6.67428e-11;
const AU = (149.6e6 * 1000)
var scalevalue = 50;
var speedvalue = 5;
var SCALE = scalevalue / AU
var timestep = 24*3600 / speedvalue

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

function gameCenter() {
    return {x: 0.5 * width, y: 0.5 * height};
}

class Scene {
    constructor() {
      this.objects = [];
  }
  
  addObject(obj) {
      this.objects.push(obj);
  }
  
  attraction(self, other) {
      // compute distance between bodies
      const dx = other.x - self.x;
      const dy = other.y - self.y;
      const distance = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));

      // compute force
      const F = G * self.mass * other.mass / Math.pow(distance, 2);

      // compute direction
      const o = Math.atan2(dy, dx);
      const Fx = Math.cos(o) * F;
      const Fy = Math.sin(o) * F;

      //console.log(sx, sy, ox, oy, dx, dy, d, F, o, Fx, Fy);
      return [Fx, Fy]
  }
  
  render() {
      ctx.fillStyle = "#000";
      ctx.fillRect(0, 0, width, height);
    
    const changes = [];
    
    this.objects.forEach(o => {
      let total = [0,0];
      
      this.objects.forEach(o2 => {
        if (o !== o2) {
          const attr = this.attraction(o, o2);
          total[0] += attr[0];
          total[1] += attr[1];
        }
      });
      
      changes.push(total);
    });
    
    changes.forEach((change, index) => 
        this.objects[index].updateV(change[0], change[1]));
    this.objects.forEach(o => o.draw(this.context));
  }
}

class Particle {
    constructor(opts) {
      this.x = opts.x;
    this.y = opts.y;
    this.vx = opts.vx;
    this.vy = opts.vy;
    this.radius = opts.radius;
    this.mass = opts.mass;
    this.linewidth = opts.linewidth;
    this.strokestyle = opts.strokestyle;
  }

    update() {
      
  }
  
  updateV(vx, vy) {
       this.vx += vx / this.mass * timestep;
      this.vy += vy / this.mass * timestep;
    
    this.updateP();
  }
  
  updateP() {
       this.x += this.vx * timestep;
      this.y += this.vy * timestep;
  }

    translateCoords(x, y) {
      return [0.5 * width + x * SCALE, 0.5 * height + y * SCALE];
  }

    draw() {
    const coords = this.translateCoords(this.x, this.y);
    
    ctx.lineWidth = this.linewidth;
    ctx.fillStyle = this.strokestyle;
    ctx.beginPath();
    ctx.arc(coords[0], coords[1], this.radius, 0, 2 * Math.PI, false);
    ctx.fill();
    }
}

let sun = new Particle({
  name: "Sun",
  mass: 1.989e30,
  vx: 0,
  vy: 0,
  x: 0,
  y: 0,
  radius: 8,
  linewidth: 3,
  strokestyle: 'yellow'
});


let earth = new Particle({
  name: "Earth",
  mass: 5.972e24,
  vx: 0,
  vy: 30290,
  x: AU,
  y: 0,
  radius: 4,
  linewidth: 1,
  strokestyle: '#60a6d4'
});

const scene = new Scene();
scene.addObject(sun);
scene.addObject(earth);

function gameLoop() {
  scene.render();
    requestAnimationFrame(gameLoop);
}

gameLoop();