ricefields.me - broadphase

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Canvas Application</title>
  <style>
    /* Ensuring the canvas fills the entire window */
    body, html {
      margin: 0;
      padding: 0;
      overflow: hidden;
    }

    canvas {
      display: block;
      background-color: #f0f0f0;
    }
  </style>
</head>
<body>
  <canvas id="render_canvas"></canvas>

  <script src="index.js"></script>
</body>
</html>

JavaScript

const canvas = document.getElementById('render_canvas');
const ctx = canvas.getContext('2d');
function resizeCanvas() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);

class Broadphase {
  constructor(grid_size, cell_size) {
    this.grid_size = grid_size;
    this.cell_size = cell_size;

    this.max_cell = [
      Math.floor(grid_size[0] / cell_size[0]),
      Math.floor(grid_size[1] / cell_size[1]),
    ];

    // use hash map with string key instead
    this.cells = Array.from({ length: this.max_cell[0] + 1 }, () =>
      Array.from({ length: this.max_cell[1] + 1 }, () => new Set()),
    );

    // keep track of bodies that were moved
    this.move_set = new Set();
  }

  insert(body) {
    const [top_index, bottom_index] = this.toIndices(body.pos, [body.radius, body.radius]);

    body.broadphase = [top_index, bottom_index];

    // insert body into all cells from top_index to bottom_index
    for (let i = top_index[0]; i <= bottom_index[0]; ++i) {
      for (let j = top_index[1]; j <= bottom_index[1]; ++j) {
        if (this.cells[i][j]) {
          this.cells[i][j].add(body);
        } else {
          this.cells[i][j] = new Set([body]);
        }
      }
    }

    this.move_set.add(body);
  }

  remove(body) {
    if (body.broadphase.length) {
      const top_index = body.broadphase[0];
      const bottom_index = body.broadphase[1];

      // remove body from top_index to bottom_index
      for (let i = top_index[0]; i <= bottom_index[0]; ++i) {
        for (let j = top_index[1]; j <= bottom_index[1]; ++j) {
          this.cells[i][j].delete(body);
        }
      }

      body.broadphase = [];
    }
  }

  update(body) {
    this.remove(body);
    this.insert(body);
  }

  // generate a set of possibly colliding bodies
  computePairs() {
    const pairs = new Set();

    const bodies = Array.from(this.move_set);
    for (let a = 0; a < bodies.length; a++) {
   ...