Source description for demo by antimatter15.
<body> <canvas id="c"></canvas> <script> var canvas = document.getElementById('c'); document.body.setAttribute('style','margin:0;left:0;top:0;padding:0') canvas.width = innerWidth; canvas.height = innerHeight; var context = canvas.getContext('2d') var planets = [ [300,100,10,-0.2,0], [300,300,10,0.2,0], //x,y,r,xv,yv ]; var selected = -1; setInterval(function(){ if(selected > 0) planets[selected][2]+=0.1; context.clearRect(0,0,innerWidth,innerHeight) for(var plen = planets.length, a = plen, b; a--;){ for(b = plen; b--;){ if(b!=a && a != selected && b != selected){ //there is no friction in space. Plus it'll yield a divide by zero error //inverse square law: force = mass/distance-squared; var dx = planets[b][0] - planets[a][0]; var dy = planets[b][1] - planets[a][1]; var d2 = dx*dx + dy*dy; var d = Math.sqrt(d2); var force = planets[b][2]/d2; planets[a][3] += dx / d * force; //possible optimization: force = force/d planets[a][4] += dy / d * force; //and sumY += dy / force } } planets[a][0] += planets[a][3]; planets[a][1] += planets[a][4]; context.fillStyle = "hsl(" + Math.min(300, Math.floor(50 * Math.sqrt(planets[a][3] * planets[a][3] + planets[a][4] * planets[a][4]))) + ",100%,40%)"; context.beginPath(); context.arc(planets[a][0], planets[a][1], planets[a][2], 0, Math.PI * 2, true); context.fill() } },0) document.body.onmousedown = function(e){ selected = planets.length; planets.push([e.clientX,e.clientY,2,0,0]) return false } document.body.onmouseup = function(e){ planets[selected][3] = (e.clientX - planets[selected][0])/100; planets[selected][4] = (e.clientY - planets[selected][1])/100; selected = -1; return false } </script> </body>