Why circles are vibrating on collision (Canvas)

Viewed 136

I have been creating a clone of agar.io and I don't understand why the circles start vibrating when they touch each other. Below is my code:

var
  canvas,
  ctx,
  width = innerWidth,
  height = innerHeight,
  mouseX = 0,
  mouseY = 0;

var

  camera = {
    x: 0,
    y: 0,

    update: function(obj) {
      this.x = obj.x - width / 2;
      this.y = obj.y - height / 2;
    }
  },

  player = {
    defaultMass: 54,
    x: 0,
    y: 0,
    blobs: [],

    update: function() {
      for (var i = 0; i < this.blobs.length; i++) {
        var x = mouseX + camera.x - this.blobs[i].x;
        var y = mouseY + camera.y - this.blobs[i].y;
        var length = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        var speed = 54 / this.blobs[i].mass;

        this.blobs[i].velX = x / length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));
        this.blobs[i].velY = y / length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));

        this.blobs[i].x += this.blobs[i].velX;
        this.blobs[i].y += this.blobs[i].velY;

        for (var j = 0; j < this.blobs.length; j++) {
          if (j != i && this.blobs[i] !== undefined) {
            var blob1 = this.blobs[i];
            var blob2 = this.blobs[j];
            var dist = Math.sqrt(Math.pow(blob2.x - blob1.x, 2) + Math.pow(blob2.y - blob1.y, 2));

            if (dist < blob1.mass + blob2.mass) {
              if (this.blobs[i].x < this.blobs[j].x) {
                this.blobs[i].x--;
              } else if (this.blobs[i].x > this.blobs[j].x) {
                this.blobs[i].x++;
              }
              if (this.blobs[i].y < this.blobs[j].y) {
                this.blobs[i].y--;
              } else if ((this.blobs[i].y > this.blobs[j].y)) {
                this.blobs[i].y++;
              }
            }
          }
        }
      }

      this.x += (mouseX - width / 2) / (width / 2) * 1;
      this.y += (mouseY - height / 2) / (height / 2) * 1
    },

    split: function(cell) {
      cell.mass /= 2;

      this.blobs.push({
        x: cell.x,
        y: cell.y,
        mass: cell.mass
      });
    },

    draw: function() {
      for (var i = 0; i < this.blobs.length; i++) {
        ctx.fillStyle = "red";

        ctx.beginPath();
        ctx.arc(-camera.x + this.blobs[i].x, -camera.y + this.blobs[i].y, this.blobs[i].mass, 0, Math.PI * 2);
        ctx.fill();
        ctx.closePath();
      }
    }
  };

function handleMouseMove(e) {
  mouseX = e.clientX;
  mouseY = e.clientY;
}

function setup() {
  canvas = document.getElementById("game");
  ctx = canvas.getContext("2d");
  canvas.width = width;
  canvas.height = height;

  addEventListener("mousemove", handleMouseMove);

  player.blobs.push({
    x: 0,
    y: 0,
    mass: player.defaultMass
  });
  player.blobs.push({
    x: 100,
    y: 100,
    mass: player.defaultMass / 2
  });
  player.blobs.push({
    x: 100,
    y: 100,
    mass: player.defaultMass * 2
  });

  var loop = function() {
    update();
    draw();
    requestAnimationFrame(loop);
  }
  requestAnimationFrame(loop);
}

function update() {
  camera.update(player.blobs[0]);
  player.update();
}

function draw() {
  ctx.fillStyle = "#fff";
  ctx.fillRect(0, 0, width, height);

  player.draw();
}

setup();
body {
  margin: 0;
  padding: 0;
}
<canvas id="game">kindly update your browser.</canvas>

2 Answers
Related