My HTML JS implementation of three body problem simulation.
Use Verlet algorithm and initial condition that give interesting stable trajectory in 8 shape.
Used as base for animations rendered for my channel here:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<canvas id="mycanvas" width="1280" height="1280"></canvas>
<script type="text/javascript">
var N = 3;
// F = 1/r^2
var fx = [];
var fy = [];
var x= [],vx= [],y= [],vy= [];
var xp1= [], yp1= [];
var xm1= [], ym1= [];
var W,H;
var dt = 0.015;
var m = 1;
var G = 1;//0.001;
var step;
var d;
// przygotowanie do rysowania
var canvas = document.getElementById('mycanvas');
W=800; H=800;
canvas.width = W;
canvas.height = H;
var ctx = canvas.getContext('2d');
// inicjalizacja
function init()
{
for(var i=0; i<N; i++)
{
// x[i]=xm1[i]=xp1[i]=0.5+(0.5)*(Math.random()-0.5);
// y[i]=ym1[i]=xm1[i]=0.5+(0.5)*(Math.random()-0.5);
vx[i] = vy[i] = 0;
}
x[0] = 0.5-0.2;
y[0] = 0.5-0.2;
x[1] = 0.5+0.2;
y[1] = 0.5-0.2;
x[2] = 0.5;
y[2] = 0.5+0.2;
x[0] = 0.97000436; y[0] = -0.24308753;
x[1] = -0.97000436; y[1] = 0.24308753;
x[2] = 0; y[2] = 0;
vx[0] = 0.93240737/2.0;
vy[0] = 0.86473146/2.0;
vx[1] = 0.93240737 / 2.0;
vy[1] = 0.86473146 / 2.0;
vx[2] = -0.93240737;
vy[2] = -0.86473146;
step = 0;
}
function dist(x1,y1,x2,y2) { return Math.sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) ); }
// pętla obliczeniowa i rysująca
loop=function()
{
step++;
//rysowanie punktu
ctx.clearRect(0,0,W,H);
ctx.strokeStyle = "rgb(0,0,0)";
for(var i=0; i<N; i++)
{
fx[i] = 0;
fy[i] = 0;
}
// sum forces
for(var i=0; i<N; i++)
for(var j=i+1; j<N; j++)
{
// dij
d = dist(x[i], y[i], x[j], y[j]);
if(d != 0)
{
var rx = x[i] - x[j];
var ry = y[i] - y[j];
var rx = rx / d; // norm
var ry = ry / d; // norm
var Fx = rx * G * m*m / (d*d);
var Fy = ry * G * m*m / (d*d);
fx[i] -= Fx;
fy[i] -= Fy;
fx[j] += Fx;
fy[j] += Fy;
}
}
// integrate
if(step==1)
{
for(var b=0; b<N; b++)
{
vx[b] = vx[b] + fx[b]/m*dt;
vy[b] = vy[b] + fy[b]/m*dt;
xp1[b] = x[b] + vx[b]*dt;
yp1[b] = y[b] + vy[b]*dt;
}
}
else
{
// VERLET
for(var b=0; b<N; b++)
{
xp1[b] = 2*x[b]-xm1[b]+dt*dt*fx[b]/m;
yp1[b] = 2*y[b]-ym1[b]+dt*dt*fy[b]/m;
}
}
for(var b=0; b<N; b++)
{
xm1[b] = x[b];
ym1[b] = y[b];
x[b] = xp1[b];
y[b] = yp1[b];
vx[b] = (x[b] - xm1[b]) / (2*dt);
vy[b] = (y[b] - ym1[b]) / (2*dt);
}
for(var i=0; i<N; i++)
{
ctx.beginPath();
ctx.arc(98*(x[i])+W/2,98*(y[i])+H/2,6,0,2*Math.PI); // kolko
ctx.fill(); // rysuj
}
ctx.font = '48px serif';
ctx.fillText(step.toString(), 10, 50);
//kontynuuj petle
requestAnimationFrame(loop);
};
// start
init();
loop();
</script>
<style type="text/css">
canvas { border: 1px solid rgb(0,0,0); }
</style>
<br>
</body>
</html>