Tim Daiber
Tim Daiber

Reputation: 358

Collision detection between balls javascript

Hi I am trying to get a response going when 2 ball objects collide on a canvas.

I have a ball object ballm and a ball object called ball.

These two balls are bouncing around on a canvas.

If the balls collide the canvas should say game over.

Here is a code I have for collision so far

function collideWithBall() {

              var dx = (ball.x + ball.radius) - (ballm.x + ballm.r);
              var dy = (ball.y + ball.radius) - (ballm.y + ballm.r);
              var distance = Math.sqrt((dx * dx) + (dy * dy));
              if (distance < ball.radius + ballm.r) {                 

                  ctx.clearRect(0, 0, canvas.width, canvas.height);    
                  ctx.fillStyle = "black";
                  ctx.font = "18px Arial";
                  ctx.fillText("Game Over ", 300, 200);
                  shutdown();

              }         
          }

My only problem is that nothing happens when the 2 balls are colliding. Any ideas would be very helpfull.

Complete code:

<!DOCTYPE html>

<html>

  <head>
    <meta charset="UTF-8">
    <title>Canvas</title>

    <style type="text/css">
      canvas {
        border: 1px solid black;
      }
    </style>

  </head>

  <body>

      <canvas id="tim's-game" width="800px" height="600px"></canvas>

      <script type="text/javascript">
          // up top. creates the canvas with given dimensions
          // declares script type


          // Gets a handle to the element with id canvasOne.      
          var canvas = document.getElementById("tim's-game");      
          // Get a 2D context for the canvas.     
          var ctx = canvas.getContext("2d");      

          // Creates object for the balls 
          var ball = {
              // determines the position where the ball will apear math.random gives a random position on the x ace
              position: {x: Math.floor((Math.random() * 780) + 20), y: 10}
              // Will determine the size of the ball
              , radius: 6
              // Will determine the speed of the ball
              , velocity: {x: 3, y: 0}
              // Will determine if the ball will get faster or slower
              , acceleration: {x: 0, y: 0.1}        
              // Function that draws the ball  
              ,drawBall: function(){                  
                  // Collour of the object         
                  ctx.fillStyle = "rgb(25, 100, 100)";  
                  // begins path
                  ctx.beginPath();
                  // calls the object it will draw with positions and size
                  ctx.arc(ball.position.x, ball.position.y, ball.radius, 0, 2 * Math.PI);
                  // fills the colour 
                  ctx.fill();       



                  // Update the y location.
                  ball.velocity.y += ball.acceleration.y;
                  ball.position.x += ball.velocity.x;
                  ball.position.y += ball.velocity.y;
                  // Keep the animation going while the ball has not touched the canvas bottom.
                  // Note there's a bug here.
                  if ((ball.position.x >= canvas.width - ball.radius) ||  (ball.position.x <=                 ball.radius))
                      ball.velocity.x = -ball.velocity.x;    
                  if ((ball.position.y >= canvas.height - ball.radius) ||  (ball.position.y <=              ball.radius))
                      ball.velocity.y = -ball.velocity.y;   



              }
              ,

          }

          // Created a second ball object
          var ball2 = {
              // determines the position where the ball will apear math.random gives a random position on the x ace
              position: {x: Math.floor((Math.random() * 780) + 20), y: 10}
              // Will determine the size of the ball
              , radius: 6
              // Will determine the speed of the ball
              , velocity: {x: 3, y: 0}
              // Will determine if the ball will get faster or slower
              , acceleration: {x: 0, y: 0.1}        
              // Function that draws the ball  
              ,drawBall2: function(){                  
                  // Collour of the object         
                  ctx.fillStyle = "rgb(25, 100, 100)";  
                  // begins path
                  ctx.beginPath();
                  // calls the object it will draw with positions and size
                  ctx.arc(ball2.position.x, ball2.position.y, ball2.radius, 0, 2 * Math.PI);
                  // fills the colour 
                  ctx.fill();       


                  // Update the y location.
                  ball2.velocity.y += ball2.acceleration.y;
                  ball2.position.x += ball2.velocity.x;
                  ball2.position.y += ball2.velocity.y;
                  // Keep the animation going while the ball has not touched the canvas bottom.
                  // Note there's a bug here.
                  if ((ball2.position.x >= canvas.width - ball2.radius) ||  (ball2.position.x <= ball2.radius))
                      ball2.velocity.x = -ball2.velocity.x;    
                  if ((ball2.position.y >= canvas.height - ball2.radius) ||  (ball2.position.y <= ball2.radius))
                      ball2.velocity.y = -ball2.velocity.y;
              }
          }


          // Creates a new ball object 
          // This ball will be used for moving around the canvas
          var ballm = {
              // spawns the ball in the middle of the canvas
              position:{ x: canvas.width / 2
              , y: canvas.height / 2
              }, r: 50

          };

          // Creates a draw circle function
          function drawCircle() {
              ctx.fillStyle = "rgb(255, 0, 0)";
              ctx.beginPath();
              ctx.arc(ballm.position.x, ballm.position.y, ballm.r, 0, 2 * Math.PI);
              ctx.fill();

              collideWithBall();

          }

          function collideWithBall() {


              var dx = (ball.position.x + ball.radius) - (ballm.position.x + ballm.r);
              var dy = (ball.position.y + ball.radius) - (ballm.position.y + ballm.r);
              var distance = Math.sqrt((dx * dx) + (dy * dy));
              if (distance < ball.radius + ballm.r) {                 

                  ctx.clearRect(0, 0, canvas.width, canvas.height);    
                  ctx.fillStyle = "black";
                  ctx.font = "18px Arial";
                  ctx.fillText("Game Over ", 300, 200);
                  shutdown();

              }         
          }



          // A function to repeat every time the animation loops.
          function repeatme() {

              collideWithBall();
              // clears  the screan/canvas i.e. where the ball was previously does not show up.
              ctx.clearRect(0, 0, canvas.width, canvas.height);
              // calls the function in the ball object
              ball.drawBall();
              ball2.drawBall2();

              //calls the draw circle function
              drawCircle();

              collideWithBall();
              // gets the animation going
              window.requestAnimationFrame(repeatme);  
          }

          // Add an event listener to the keypress event.          
          window.addEventListener("keydown", function(event) {

              ctx.clearRect(0, 0, canvas.width, canvas.height);

              // Right
              if (event.keyCode == 39 && ballm.position.x < canvas.width - ballm.r)
                  ballm.position.x += Math.min(10, canvas.width - ballm.position.x - ballm.r);

              // Left
              else if (event.keyCode == 37 && ballm.position.x > ballm.r)
                  ballm.position.x -= 10;

              // down
              else if (event.keyCode == 40 && ballm.position.y < canvas.height - ballm.r)
                  ballm.position.y += 10;

              // For up movement
              else if (event.keyCode == 38 && ballm.position.y > ballm.r)
                  // updates location by int given
                  ballm.position.y -= 10;

              drawCircle();
                collideWithBall();
          });


          // Get the animation going.

          window.requestAnimationFrame(repeatme);
    </script>

  </body>

</html>

Edit: Have removed extra collideWithBall function.

Have also added position to the code

Edit 2: Added fixes to code works now

Upvotes: 1

Views: 2948

Answers (1)

Armin Braun
Armin Braun

Reputation: 3683

Your math is wrong in my opinion. Your check

if (distance < ball.radius + ballm.r) { 

is correct but implies that the distance is measured center to center for the balls. Hence the correct distance formula would be:

var dx = ball.position.x-ballm.x;
var dy = ball.position.y-ballm.y;
var distance = Math.sqrt((dx * dx) + (dy * dy));

The radius of the balls does not enter the calculation if you are measuring center to center distance as implied by the if statement.

A further issue I can see in your code is that the

collideWithBall

function is defined twice! Please try removing one of the two seemingly equivalent implementations.

Edit : Also you are accessing the positions of the balls wrong. The position of the balls is in the the position property.

Hence you need to use that! See above edited code for how.

works then: http://jsfiddle.net/gQ3hD/2/

Edit2: udpated the fiddle to also handle the second ball correctly by looping over both baals in the collision function.

Upvotes: 3

Related Questions