coder
coder

Reputation: 1

Colliding two circles without using canvas

I have created three circles and made it bounce off the wall without using HTML canvas. Now I want two circles to collide with each other and move those circles in the opposite direction. I tried to detect the collision by checking it's position but it doesn't work. I don't know where I went wrong. Here's my code:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Bounce Ball</title>
<meta name="viewport" content="width=device-width, initial-scale=1">  
<style>
    .circle{
        height: 50px;
        width: 50px;
        position: absolute; 
        border-radius: 50%;    
    }        
    .container {
        height: 300px;
        width: 300px;
        background-color: skyblue;
        position: relative;
    }
</style>
</head>
<body>
<div class ="container" id ="container">        
    <div class="circle" id = "circle1" style="background-color:black; 
    height: 50px; width: 50px;top:0; left:0"></div>  
    <div class="circle" id ="circle2" style="background-color:rgb(197, 100, 
    100);height: 50px; width: 50px;top:200px;left: 150px"></div>    
    <div class="circle" id ="circle3" style="background-color:brown;height: 
    50px;width: 50px;top:50px;left: 640px"></div>   
</div>
<script>
      var container = document.getElementById("container");
      container.style.width="700px";
      container.style.height = "300px";  
      var balls = document.getElementsByClassName("circle");   
      for(var i=0; i <balls.length; i++){
        var speed={x:3,y:-3}
        setInterval(draw, 50 , balls[i], speed);            
      }          
      function draw(ball, speed) { 
           if(parseInt(ball.style.left) > (parseInt(container.style.width)- 
      parseInt(ball.style.width)) || (parseInt(ball.style.left) <0) ){
                speed.x = -speed.x;                               
           } 
            ball.style.left = parseInt(ball.style.left) +  speed.x + 'px';                                       
           if(parseInt(ball.style.top) > (parseInt(container.style.height)- 
      parseInt(ball.style.height)) || (parseInt(ball.style.top) <0)){
               speed.y = -speed.y;
           }
             ball.style.top = parseInt(ball.style.top) + speed.y + 'px'; 
         //for colliding two circles
                    for(var i =0 ; i <= balls.length-1; i++){                  
                for(var j = i + 1; j < balls.length; j++){
                        if(parseInt(balls[i].style.left) + 
                 parseInt(balls[i].style.width) == 
                 parseInt(balls[j].style.left) || 
                 parseInt(balls[j].style.left) + 
                    parseInt(balls[j].style.width) == 
                   parseInt(balls[i].style.left) && 
                    parseInt(balls[i].style.top) + 
                    parseInt(balls[i].style.height) == 
               parseInt(balls[j].style.top) || parseInt(balls[j].style.top) 
               + parseInt(balls[j].style.height) == 
                  parseInt(balls[i].style.top)) {
                         speed.x = - speed.x; 
                         speed.y = -speed.y;                             
                    }
                    ball[i].style.left = parseInt(ball[i].style.left) + 
                         speed.x + 'px'; 
                    ball[j].style.left = parseInt(ball[j].style.left) + 
                         speed.x + 'px';                       
                    ball[i].style.top = parseInt(ball[i].style.top) + 
                    speed.y + 'px'; 
                    ball[j].style.top = parseInt(ball[j].style.top) + 
                        speed.y + 'px';                             
                }             

            }   

        }   

    </script>
    </body>
   </html>

Upvotes: 0

Views: 147

Answers (1)

Emil S. J&#248;rgensen
Emil S. J&#248;rgensen

Reputation: 6366

I would recommend moving as much as possible into javascript variables so you don't need to consult the HTML for every parameter.

You had quite the number of typos, among them speed.x = - speed.x; where you meant speed.x = -speed.x; and your code was difficult to read without any comments or helper functions to explain what's going on.

I have fixed your typos and restructured your code in the snippet below. Try checking the developer console, typically by pressing F12, as this will show you code errors with line number and severity rating.

In my snippet below i have tried to move the parameters into JavaScript to show how that would work, while still leaving some on the HTML nodes:

//Basic properties
var width = 700;
var height = 300;
//Get container
var container = document.getElementById("container");
// Set dimensions
container.style.width = width + "px";
container.style.height = height + "px";
//Load balls
var balls = Array.prototype.slice.call(document.getElementsByClassName("circle"))
  .map(function(ball) {
    return {
      HTMLNode: ball,
      xPos: parseInt(ball.style.left),
      yPos: parseInt(ball.style.top),
      xAcc: 3,
      yAcc: -3,
      size: 50
    };
  });
//Utility functions
function angleBetween(x1, y1, x2, y2) {
  return Math.atan2(y2 - y1, x2 - x1);
}

function distanceBetween(x1, y1, x2, y2) {
  return Math.abs(y2 - y1) + Math.abs(x2 - x1);
}
//Draw function
function draw() {
  //Loop through balls
  for (var ballIndex1 = 0; ballIndex1 < balls.length; ballIndex1++) {
    var ball1 = balls[ballIndex1];
    //Collide with horisontal wall
    if (ball1.xPos > width - ball1.size || ball1.xPos < 0) {
      ball1.xAcc = -ball1.xAcc;
    }
    //Collide with vertical wall
    if (ball1.yPos > height - ball1.size || ball1.yPos < 0) {
      ball1.yAcc = -ball1.yAcc;
    }
    //Collide with other balls
    for (var ballIndex2 = ballIndex1 + 1; ballIndex2 < balls.length; ballIndex2++) {
      var ball2 = balls[ballIndex2];
      //Test within collision distance
      if (distanceBetween(ball1.xPos, ball1.yPos, ball2.xPos, ball2.yPos) > ball1.size) {
        continue;
      }
      //Get angle of collision
      var angle = angleBetween(ball1.xPos, ball1.yPos, ball2.xPos, ball2.yPos);
      //Apply force to acceleration
      ball1.xAcc = -Math.cos(angle) * 3;
      ball2.xAcc = -ball1.xAcc;
      ball1.yAcc = -Math.sin(angle) * 3;
      ball2.yAcc = -ball1.yAcc;
    }
    //Apply acceleration to position
    ball1.yPos += ball1.yAcc;
    ball1.xPos += ball1.xAcc;
    //Apply to node
    ball1.HTMLNode.style.left = ball1.xPos + "px";
    ball1.HTMLNode.style.top = ball1.yPos + "px";
  }
}
//Start simulation
setInterval(draw, 1000 / 60);
.circle {
  position: absolute;
  border-radius: 50%;
  height: 50px;
  width: 50px;
}

.container {
  height: 300px;
  width: 300px;
  background-color: skyblue;
  position: relative;
}
<div class="container" id="container">
  <div class="circle" id="circle1" style="background-color:black; 
    top:0; left:0"></div>
  <div class="circle" id="circle2" style="background-color:rgb(197, 100, 
    100);top:200px;left: 150px"></div>
  <div class="circle" id="circle3" style="background-color:brown;top:50px;left: 640px"></div>
</div>

Upvotes: 1

Related Questions