Search code examples
javascripthtmlcanvascollision-detectioncollision

How to get a collision function to work properly in Javascript?


I'm pretty close to finish this program using Canvas. This program is simply a ball that falls down from top to bottom and there's a basket that catches it, that is it. However, I have the following issues.

1) When I press the left or right arrows from keyboard for more than couple of times somehow the basket will go all the way to either left or right and disappear.

2) When the ball hits the basket nothing happens (my Collision detection function doesn't work properly). However, I should say that my collision detection works just fine when the balls hits the ground (alert message shows up saying "Ball hit the ground").

Is there a way to show a message on the top of the canvas like "1 point" every time the basket catches a ball ( if there are 5 balls then I should get a message to say "5 points")

Can someone tell me what I am doing wrong please? Thank you so much in advance!!

LIVE CODE HERE
http://codepen.io/HenryGranados/pen/QNOZRa

Here's my code :

 //create the constructor for the class pad
 function Pad() {
//initialisation code will go here

//create private variables for the x and y coordinates
var x = 200,
    y = 200,
    vx = 0,
    vy = 0,
   padX = (canvas.width - 20) / 2;
   rightPressed = false,
   leftPressed = false;

//create the draw function to give us the draw method
//it accepts one parameter which is the context from the canvas it is drawn on
Pad.prototype.draw = function (context) {
    //save the state of the drawing context before we change it
    context.save();
    //set the coordinates of the drawing area of the new shape to x and y
    context.translate(x, y);
    //start the line (path)
    context.beginPath();
    context.fillStyle = "#800000"; // This is the basket
    context.moveTo(15, 20);
    context.bezierCurveTo(20, 100, 150, 100, 150, 20);
    //close the path
    context.closePath();
    context.fill();
    //go ahead and draw the line
    context.stroke();
    //restore the state of the context to what it was before our drawing
    context.restore();
}

//create a public property called X (note caps!)
Object.defineProperty(this, 'X',
{
    //getter
    get: function () {
        //return the value of x (lower case)
        return x;
    },
    //setter
    set: function (value) {
        //ste the value of x (lower case)
        x = value;
    }
}
)

//create a public property called Y (note caps!)
Object.defineProperty(this, 'Y',
{
    //getter
    get: function () {
        //return the value of y (lower case)
        return y;
    },
    //setter
    set: function (value) {
        //ste the value of y (lower case)
        y = value;
    }
}
)


padX = function () {

    if (rightPressed && padX < canvas.width - 20) {
        padX += 5;
    }
    else if (leftPressed && padX > 0) {
        padX -= 5;
    }

 }

 Pad.prototype.move = function () {
    //change the x axis by the x velocity
    x += vx;
    //change the y axis by the y velocity
    y += vy;
 }

 Pad.prototype.setVector = function (vector) {
    //set the vx value based on this vector
    vx = vector.VX;
    //set the vy value based on this vector
    vy = vector.VY;
}

//public method to set the vector of the saucer
Pad.prototype.accelerate = function (Acceleration) {
    //set vx
    vx += Acceleration.AX;
    ////set vy
    //vy += Acceleration.AY;
 }


 //create a public property called Top
 Object.defineProperty(this, 'Top',
 {
    //getter
    get: function () {
        //return the y posn less the height
        return y - 10;
    }
 }
 )

  //create a public property called Bottom
  Object.defineProperty(this, 'Bottom',
  {
    //getter
    get: function () {
        //return the y posn plus the height
        return y + 10;
    }
  }
 )

  //create a public property called Left
  Object.defineProperty(this, 'Left',
  {
    //getter
    get: function () {
        //return the x posn less the width
        return x - 80;
    }
   }
  )

  //create a public property called Right
  Object.defineProperty(this, 'Right',
{
    //getter
    get: function () {
        //return the x posn plus the width
        return x + 80;
    }
 }
 )

 }

Solution

  • (1) There are at least two options to solve this problem in your Pad.move function you could limit the change of x. You change it only when its within canvas width:

      Pad.prototype.move = function() {
        //change the x axis by the x velocity
        var canvasWidth = 400,
          padWidth = 150;
        if (x + vx < canvasWidth - padWidth && x + vx >= 0)
          x += vx;
        //change the y axis by the y velocity
        y += vy;
      }
    

    or similarly as you create ground you could create walls on both sides and collide pad with them.

    (2) There is no collision handling between ball and pad: place it in function drawFrame():

     if (collision.Overlapping(ball, pad)) {
         context.strokeText('ball hit pad!',20,100)
         //..do some other stuff here
          }
    

    (3)Which brings us to showing message on canvas, you can just draw text on canvas

    var ctx = canvas.getContext("2d");
    ctx.font = "30px Arial";
    ctx.fillText("Hello World",10,50);
    

    Demo: http://codepen.io/anon/pen/RaxwLp?editors=1011 Pad was blocked because when key is pressed acceleration is always increased, so in order to move in opposite direction first it must go to 0 which takes quite some time. I have added keyup event and when key is released acceleration is zeroed:

    if(leftPressed){
     acceleraton.HThrust(.01);
    }else if(rightPressed){
      acceleraton.HThrust(-.01);
    }else{
     acceleraton.Halt();
    }