JSFiddle - React, Tailwind, and code Playground

by raxxla

HTML

<canvas id="canvas" width="400" height="400" style='border:1px solid;'></canvas>

JavaScript

var context = document.getElementById('canvas').getContext('2d');
var ball = [], n=10;

for (var i=0; i<n; i++){
  var r = 10+10*Math.random();
  ball[i] = {};
  ball[i].x = Math.random()*(canvas.width-2*r)+r;
  ball[i].y = Math.random()*(canvas.height-2*r)+r;
  ball[i].r = r;
  ball[i].vx = 3*Math.random()*Math.pow(-1, Math.round(Math.random()+1));
  ball[i].vy = 3*Math.random()*Math.pow(-1, Math.round(Math.random()+1));
  ball[i].m = r*r;
}

setInterval(draw,40);

function draw() {
  context.clearRect(0, 0, canvas.width, canvas.height);
  var dt=1;
  for (var i=0; i<ball.length; i++) {
    findCollision(dt);
    motion(i, dt);
    context.beginPath();
    context.arc(ball[i].x, ball[i].y, ball[i].r, 0, 2*Math.PI);
    context.stroke();
  }
}

function findCollision(dt) {
  var t, tc, q, w;
  for (var i=0; i<ball.length; i++) {
    for (var j=0; j<ball.length; j++) {
      var a=Math.pow(ball[i].vx-ball[j].vx, 2)+Math.pow(ball[i].vy-ball[j].vy, 2);
      var b=2*((ball[i].x-ball[j].x)*(ball[i].vx-ball[j].vx)+(ball[i].y-ball[j].y)*(ball[i].vy-ball[j].vy));
      var c=Math.pow(ball[i].x-ball[j].x, 2)+Math.pow(ball[i].y-ball[j].y, 2)-Math.pow(ball[i].r+ball[j].r, 2);
      var d=b*b-4*a*c;
      if (d>0) {
        var t1=(-b+Math.sqrt(d))/2/a;
        var t2=(-b-Math.sqrt(d))/2/a;
        if (t1<t2) {
          if (t1>0) tc=t1;
        }
        else if (t2>0) tc=t2;
      }
      if (t) {
        if (tc<t) t=tc, q=i, w=j;
      }
      else t=tc, q=i, w=j;
    }
  }
  if (t<dt) {
    for (var i=0; i<ball.length; i++) {
      motion(i, t);
    }
    dt-=t;
    collision(q, w);
  }
  else return;
  findCollision(dt);
}

function collision(q, w) {
  var dx=ball[q].x-ball[w].x;
  var dy=ball[q].y-ball[w].y;
  var r=Math.sqrt(dx*dx+dy*dy);
  var v1=ball[q].vx*dx/r+ball[q].vy*dy/r;
  var v1p=-ball[q].vx*dy/r+ball[q].vy*dx/r;
  var v2=ball[w].vx*dx/r+ball[w].vy*dy/r;
  var v2p=-ball[w].vx*dy/r+ball[w].vy*dx/r;
  var...