user2602079
user2602079

Reputation: 1393

top of paddle collision detection pong

This is for pong.

I can get collision of the ball and front paddle to fire but not the ball and top of paddle, but this code seems correct for it. This code is inside the ball object. The ball is a square image with correct width and height attributes.

    // Paddle collision detection
    // Hits front of paddle
    if ((this.x) == (playerPaddle.x + playerPaddle.width) && (this.y > playerPaddle.y) && this.y < (playerPaddle.y + playerPaddle.height)) {
        console.log("front connect");
        this.vx = -this.vx;
    }
    // Hits top of paddle
    if ((this.x + this.width) >= playerPaddle.x && this.x <= (playerPaddle.x + playerPaddle.width) && (this.y + this.height) == playerPaddle.y) {
        console.log("top connect");
        this.vy = -this.vy;
    }

It fires if i change && (this.y + this.height) == playerPaddle.y) to && (this.y + this.height) > playerPaddle.y) but obviously this is wrong, causing it to fire whenever the ball is way below the paddle. It seems like a bug in the browser as it looks correct to me. I'm using chrome which seems to always work well.

Upvotes: 1

Views: 2067

Answers (1)

Steven Moseley
Steven Moseley

Reputation: 16325

Since a 2d ball is circular, you'll need to use trig functions to properly determine a connect with the edge. I suggest you check the general area first with a "quick check" to prevent slowing down your app.

// Paddle Collision Detection
// Start by a global check to see if the ball is behind the paddle's face
if (this.x <= playerPaddle.x + playerPaddle.width) {
    // Get the ball's radius
    var rad = this.width/2;

    // Give yourself a 3px 'padding' area into the front of the paddle
    // For the detection fo collisions to prevent collision issues caused
    // By a ball moving > 1px in a given frame.  You may want to adjust this number
    var padding = 3;

    // Detect if ball hits front of paddle
    // y collision should be from 1/2 the ball width above the paddle's edge
    // to 1/2 the ball width below the paddle's edge
    if (this.x + padding >= playerPaddle.x + playerPaddle.width 
            && this.y - rad >= playerPaddle.y
            && this.y + rad <= playerPaddle.y + playerPaddle.height) {
        console.log("front connect");
        this.vx = -this.vx;

    // Next, do a "quick check" to see if the ball is in the correct
    // general area for an edge collision prior to doing expensive trig math
    } else if (this.y - this.height >= playerPaddle.y
            && this.y <= playerPaddle.y
            && this.x - rad >= playerPaddle.x) {

        // Get the position of the center of the ball
        var x = this.x + rad;
        var y = this.y + rad;

        // Get the position of the corner of the paddle
        var px = playerPaddle.x + playerPaddle.width;
        var py = playerPaddle.y;
        if (this.y + this.height > playerPaddle.y) {
            // if the ball is below the top edge, use the bottom corner
            // of the paddle - else use the top corner of the paddle
            py += playerPaddle.height;
        }

        // Do some trig to determine if the ball surface touched the paddle edge
        // Calc the distance (C = sqrt(A^2 + B^2))
        var dist = Math.pow(Math.pow(x - px, 2) + Math.pow(y - py, 2), 0.5);

        // Check if the distance is within the padding zone
        if (dist <= rad && dist >= rad - padding) {
            // Get the angle of contact as Arc-sin of dx/dy
            var angle = Math.asin(x - px / y - py);

            // Adjust the velocity accordingly
            this.vy = (-this.vy * Math.cos(angle)) + (-this.vx * Math.sin(angle));
            this.vx = (-this.vx * Math.cos(angle)) + (-this.vy * Math.sin(angle));
        }

    }
}

Upvotes: 2

Related Questions