JamieJon
JamieJon

Reputation: 1

cannot get collision detection on ball to floor array?

I can't seem to get collision detection to work with the floor array? I seem to be having the issue in the ballMovement function.
The ball falls straight through the rectangles made by the array.

  1. Floor Array (issue)
  2. Collision Detection

<html lang=en>
<head>
<meta charset=utf-8>
    <title>Javascript gravity</title>
    <link rel="stylesheet" href="game.css">
    </head>
    <body onload="init()">


<script>
    var canvas, ctx, container;
    canvas = document.createElement( 'canvas' );
    ctx = canvas.getContext("2d");
    var ball;
    var message = "Helloworld";

    // Velocity x
    var vx = 2.0;
    // Velocity y - randomly set
    var vy;

    var gravity = 0.5;  
    var bounce = 0.7; 
    var xFriction = 0.1;

    // Floor Array
    var floor = new Array();    

    //Rectagles
    Rectangle = function(x, y, w, h, color){

    if (x == null || y == null || w == null || h == null){

        alert("You must pass in all the veriables for a rectange: (x, y, width, height)");

        var errorMsg = "The following are not provided:";
        if (x == null)
            errorMsg += " 'x' ";
        if (y == null)
            errorMsg += " 'y' ";
        if (w == null)
            errorMsg += " 'width' ";
        if (h == null)
            errorMsg += " 'height'";

        alert(errorMsg);
        throw new Error(errorMsg);
    }

    this.x      = x;
    this.y      = y;
    this.width  = w;
    this.height = h;

    this.color = new Color();

    this.Contains = function(x, y){

        if (x >= this.x && x <= this.x + this.width &&
            y >= this.y && y <= this.y + this.height)
            return true;
        else 
            return false;
    };

    this.Draw = function(ctx){
        ctx.fillStyle = this.color.ToStandard();
        ctx.fillRect(this.x, this.y, this.width, this.height);
    }
};
    //Rectangle Colors
    Color = function(r, g, b, a){

    this.r = 255;
    this.g = 255;
    this.b = 255;
    this.a = 1;

    if (r != null)
        this.r = r;
    if (g != null)
        this.g = g;
    if (b != null)
        this.b = b;
    if (a != null)
        this.a = a;

    this.ToStandard = function(noAlpha){

        if (noAlpha == null || !noAlpha)
            return "rgba(" + this.r + "," + this.g + "," + this.b + "," + this.a + ")";
        else
            return "rgb(" + this.r + "," + this.g + "," + this.b + ")";
    };
};


    function init(){
       setupCanvas();
        vy = (Math.random() * -5) + -5;
        ball = {x:canvas.width / 2, y:100, radius:10, status: 0,   color:"red"};

        floor.push(new Rectangle(0, 480, 500, 20));
        floor.push(new Rectangle(250, 350, 200, 20));
        //floor.push(new Rectangle(150, 300, 20, 20));
        //floor.push(new Rectangle(200, 250, 20, 20));
        //floor.push(new Rectangle(250, 200, 20, 20));
        //floor.push(new Rectangle(300, 150, 20, 20));
        //floor.push(new Rectangle(350, 100, 20, 20));
        //floor.push(new Rectangle(400, 50, 20, 20));
        for (var i = 0; i < floor.length; i++)floor[i].color = new Color(0, 0, 0, 1);

    }//end init method

    function draw() {
        ctx.clearRect(0,0,canvas.width, canvas.height); 

        for (var i = 0; i < floor.length; i++)
             floor[i].Draw(ctx);

        //display some text
           ctx.fillStyle = "red";
           ctx.font = "20px Arial";
           ctx.fillText(message, 20,20);    

             //draw cirlce
            ctx.beginPath();
            ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI*2, false);
            ctx.fillStyle = ball.color;
            ctx.fill();
            ctx.closePath();

        ballMovement();

    }

    setInterval(draw, 1000/35);     

    function ballMovement(){
        ball.x += vx;
        ball.y += vy;
        vy += gravity;

        //If either wall is hit, change direction on x axis
        if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0){
            vx *= -1;
        }

          // Ball hits the canvas floor
        if (ball.y + ball.radius > canvas.height){// ||

            // Re-positioning on the base
           ball.y = canvas.height - ball.radius;
            //bounce the ball
              vy *= -bounce;
            //do this otherwise, ball never stops bouncing
              if(vy<0 && vy>-2.1)
                         vy=0;
            //do this otherwise ball never stops on xaxis
             if(Math.abs(vx)<1.1)
                 vx=0;

             xF();

    }
    // Ball hits the rectangles
        if (ball.y + ball.radius > floor.width){// ||

            // Re-positioning on the base
           ball.y = floor.height - ball.radius;
            //bounce the ball
              vy *= -bounce;
            //do this otherwise, ball never stops bouncing
              if(vy<0 && vy>-2.1)
                         vy=0;
            //do this otherwise ball never stops on xaxis
             if(Math.abs(vx)<1.1)
                 vx=0;

             xF();

    }


}

    function xF(){
             if(vx>0)
                 vx = vx - xFriction;
             if(vx<0)
                 vx = vx + xFriction;
    }    


    function setupCanvas() {//setup canvas


    container = document.createElement( 'div' );
    container.className = "container";

    canvas.width = 500; 
    canvas.height = 500; 
    document.body.appendChild( container );
    container.appendChild(canvas);  

    ctx.strokeStyle = "red";
    ctx.lineWidth =1;   
}

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

Upvotes: 0

Views: 38

Answers (1)

Barudar
Barudar

Reputation: 570

There are a couple of mistakes:

  1. You compare the ball position on Y axis ball.y to the bar width floor.width, it may be a typing/editing mistake.

  2. You should replace floor.width by floor.y to check whether the ball hits the bar when it falls.

  3. But floor is an Array of Rectangle, it includes the bar and potential bricks to break, if I guess it right. So you need to loop through floor before checking, otherwise floor.height equals undefined.

    for (let i = 0; i < floor.length; i += 1) {
        const rect = floor[i];
        // Ball hits the rectangle
        if (ball.y + ball.radius > rect.y) {
            // ...
        }
    }
  1. Then, floor isn't an appropriate name for an Array which doesn't contain any 'floor'.

  2. Finally, add a condition to handle the ball X position (collisions with the bar, the bricks, etc.).

Working example: https://jsfiddle.net/nmerinian/3sokr512/22/

Have a good day

Upvotes: 0

Related Questions