1

I want to detect a collision between two divs and I've tried to do that using the offsetLeft and offsetTop of each one of the divs and by using getBoundingClientRect(). But none of these work.

Is there a way I can get the exact coordinates in which these two elements touch?

const bigDiv = document.querySelector(".big")
const blue = document.querySelector(".blue")
const startBtn = document.querySelector("button")
const red = document.querySelector(".red")
const bigDivDimensions = bigDiv.getBoundingClientRect();
let speed = 5;
//let counter = 0;


let bigDivLeft = bigDivDimensions.left;

startGame();

function random() {
  return Math.floor(Math.random() * (bigDivDimensions.width - 40));
}

function startGame() {
  //let randomSnake = Math.floor(Math.random()*(bigDivDimensions.width-40));
  //let randomApple = Math.ceil(Math.random()*(bigDivDimensions.width -40));
  blue.style.left = random() + "px"
  blue.style.top = random() + "px"
  red.style.left = random() + "px"
  red.style.top = random() + "px"
}

function move(e) {
  let blueX = blue.offsetLeft;
  let blueY = blue.offsetTop;
  let key = e.keyCode;

  if (key !== 37 && key !== 38 && key !== 39 && key !== 40) {
    return
  } else if (key === 37 && blueX > 3) {
    blueX -= speed;
  } else if (key === 38 && blueY > 3) {
    blueY -= speed;
  } else if (key === 39 && blueX < (bigDivDimensions.width - 25)) {
    blueX += speed;
  } else if (key === 40 && blueY < (bigDivDimensions.height - 23)) {
    blueY += speed;
  }

  blue.style.left = blueX + "px";
  blue.style.top = blueY + "px";
  colision(blueX, blueY)
}

function colision(blueX, blueY) {
  /* let redX = red.offsetLeft;
     let redY = red.offsetTop; 
     if(redY === blueY || redX == blueX){console.log("hit")}  */

  let redRect = red.getBoundingClientRect();
  let blueRect = blue.getBoundingClientRect();

  if ((redRect.top < blueRect.bottom) || (redRect.bottom < blueRect.top) || (redRect.right > blueRect.left) || (redRect.left < blueRect.right)) {
    console.log("hit")
  }
}

startBtn.addEventListener("click", startGame)
document.addEventListener("keydown", move)
.big {
  width: 400px;
  height: 400px;
  outline: 1px solid red;
  margin: 0 auto;
  position: relative;
}

.blue {
  width: 20px;
  height: 20px;
  background: blue;
  position: absolute;
}

.red {
  width: 20px;
  height: 20px;
  background: red;
  position: absolute;
}
<button type="button">Start Game</button>
<div class="big">
  <div class="blue"></div>
  <div class="red"></div>
</div>

codepen

1 Answers1

0

Two rectangles do collide when their

horizontal side and vertical side

overlap.

Consider the following answer: Checking for range overlap

// l1 (line 1) --> [x1, x2]
// l2 (line 2) --> [x1, x2]
function checkOverlap(l1, l2) {
  return ((l1[1] - l2[0]) > 0 && (l2[1] - l1[0]) > 0) ? true : false;
}

Check collision with range overlap for the x-side and y-side:

// Rectangle a --> [[x1, x2], [y1, y2]]
// Rectangle b --> [[x1, x2], [y1, y2]]
function collide(a, b) {
  return (checkOverlap(a[0], b[0]) && checkOverlap(a[1], b[1]));
}

Spoiler

SVG-Example

var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
var width = 200;
var height = 200;
svg.setAttribute("width", width);
svg.setAttribute("height", height);
document.body.appendChild(svg);

function createRect(svg, width, height, x, y, style, id) {
  var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
  rect.setAttribute("width", width);
  rect.setAttribute("height", height);
  rect.setAttribute("x", x);
  rect.setAttribute("y", y);
  rect.setAttribute("style", style);
  rect.setAttribute("id", id);
  svg.appendChild(rect);
}

function createSquare(svg, side, x, y, style, id) {
  createRect(svg, side, side, x, y, style, id);
}

function getRandomNumber(a, b) {
  return Math.round(Math.random() * (b - a)) + a;
}

function createRandomSquare(svg, xRange, yRange, side, style, id) {
  var x = getRandomNumber(xRange[0], xRange[1]);
  var y = getRandomNumber(yRange[0], yRange[1]);
  createSquare(svg, side, x, y, style, id);
  return [
    [x, x + side],
    [y, y + side]
  ];
}

function checkOverlap(l1, l2) {
  return ((l1[1] - l2[0]) > 0 && (l2[1] - l1[0]) > 0) ? true : false;
}

// [[x1, x2], [y1, y2]]
function collide(a, b) {
  return (checkOverlap(a[0], b[0]) && checkOverlap(a[1], b[1]));
}

function getCoordinates(arr) {
  return {
    "top-left": [arr[0][0], arr[1][0]],
    "top-right": [arr[0][1], arr[1][0]],
    "bottom-left": [arr[0][1], arr[1][1]],
    "bottom-right": [arr[0][0], arr[1][1]]
  }
}

function run() {
  var bs = document.getElementById("blueSquare");
  var rs = document.getElementById("redSquare");
  var output = document.getElementById("output");
  output.innerHTML = "";
  if (bs !== null && rs !== null) {
    var parent = bs.parentNode;
    parent.removeChild(bs);
    parent.removeChild(rs);
  }

  var side = 30;
  var blueSquare = createRandomSquare(svg, [0, (width - side)], [0, (height - side)], side, "fill:blue", "blueSquare");
  var redSquare = createRandomSquare(svg, [0, (width - side)], [0, (height - side)], side, "fill:red", "redSquare");
  var output1 = "Collision? " + collide(blueSquare, redSquare);
  var output2 = "Blue square: " +
    JSON.stringify(getCoordinates(blueSquare));
  var output3 = "Red square: " + JSON.stringify(getCoordinates(redSquare));
  output.innerHTML = output1 + "<br>" + output2 + "<br>" + output3 + "<br>";
}

var button = document.createElement("button");
button.setAttribute("id", "button");
button.textContent = "Run";
button.addEventListener("click", run);
document.body.appendChild(button);
svg {
  border: 1px solid;
}
<div id="output"></div>