Search code examples
javascriptcanvascollision-detection

Collision Detection Javascript Not Working(rather Im not working)


I wrote a simple canvas with several bubbles that float around. They are supposed to be green when not colliding and red when any of them are. For some reason they are all green but one. And when the bubbles collide the only ones that turn red are the ones touching that original bubble that wont start off green. I know I am missing something really obvious to you guys, but I went over it a thousand times and just can't see it. If anyone can please let me know, I am ready to feel stupid... thanks.

Here is a link to the GitHub gist:

https://gist.github.com/anonymous/e172bb18c078a2e9a797b8a30fdafcc3

Here is a snippet from the collision detection to drawing the canvas:

// Draw to Canvas
var draw = function() {
ctx.clearRect(0,0,600,400);
for(var i = 0 ; i < spawnArr.length; i++){ 

 // Collision Detect & Correct 
for(var j = 0; j < spawnArr.length; j++) {
  var dx = spawnArr[i].x - spawnArr[j].x;
  var dy = spawnArr[i].y - spawnArr[j].y;
  var distance = Math.sqrt(dx * dx + dy * dy);

  if (distance <  spawnArr[i].rad + spawnArr[j].rad) {

        ctx.strokeStyle = "#FF0000"; 
        ctx.beginPath();
        ctx.arc(spawnArr[i].x, spawnArr[i].y, spawnArr[i].rad, 0, 2*Math.PI);
        ctx.closePath();
        ctx.stroke();

        ctx.beginPath();
        ctx.arc(spawnArr[j].x, spawnArr[j].y, spawnArr[j].rad, 0, 2*Math.PI);
        ctx.closePath();
        ctx.stroke();
       // console.log('hit');
  }
  else {
    ctx.strokeStyle = "#00FF00"; 
    ctx.beginPath();
    ctx.arc(spawnArr[i].x, spawnArr[i].y, spawnArr[i].rad, 0, 2*Math.PI);
    ctx.closePath();
    ctx.stroke();

    ctx.beginPath();  
    ctx.arc(spawnArr[j].x, spawnArr[j].y, spawnArr[j].rad, 0, 2*Math.PI);
    ctx.closePath();
    ctx.stroke();
    //console.log('miss');
  }
}

Solution

  • The problem is you are drawing over the circles many times. When a circle is touching another you draw it red, then if it does not hit the next circle you draw it green. Also you are checking if the circle hit itself, so you draw all the circles red twice It can only be green or red, and it should only be drawn once.

    The following will solve you problems and make it run somewhat quicker. I have added a style to each circle that defines its colour. It test for a hit and if found set the colour to red.

    The second for loop starts from the position of the first for loop plus one. There is no point in checking if B hit A when you already know A hit B

    // Draw to Canvas
    var draw = function () {
        ctx.clearRect(0, 0, 600, 400);
        function drawThing(thing) {
            ctx.strokeStyle = thing.style;
            ctx.beginPath();
            ctx.arc(thing.x, thing.y, thing.rad, 0, 2 * Math.PI);
            ctx.stroke();
        }
    
        for (var i = 0; i < spawnArr.length; i++) {
            var t1 = spawnArr[i];
    
            var t1.style = "#00FF00";
            // Collision Detect & Correct
            for (var j = i + 1; j < spawnArr.length; j++) {
                var t2 = spawnArr[j];
                var dx = t1.x - t2.x;
                var dy = t1.y - t2.y;
                var distance = Math.sqrt(dx * dx + dy * dy);
    
                if (distance < t1.rad + t2.rad) {
                    t1.style = "#FF0000";
                }
            }
            drawThing(t1);
        }
    }