1
\$\begingroup\$

I've been working on making Pong in OpenGL and SDL and currently have both paddles and the game ball set up properly. I have an Object (or Entity) class which is used to instantiate each of the entities in the game. The Object class constructor takes a width and a height for the object, the direction in which it moves (x and y), its position, its speed, and rotation.

In order to detect whether the ball has collided with either a paddle or the top or bottom of the screen, I do the following checks:

// Collision with the top
            if ((ballTop >= topWallBottom) || (ballBottom <= bottomWallTop)) {
                ball.yDir = -ball.yDir;
            }

            // Collisions Left Paddle - Ball
            if ((
                (leftPaddleBottom > ballTop) ||
                (leftPaddleTop < ballBottom) ||
                (leftPaddleLeft > ballRight) ||
                (leftPaddleRight < ballLeft))) {

            }
            else{
                ball.xDir = -ball.xDir;
                ball.yDir = -ball.yDir;
            }
            if ((
                (rightPaddleBottom < ballTop) ||
                (rightPaddleTop > ballBottom) ||
                (rightPaddleLeft > ballRight) ||
                (rightPaddleRight < ballLeft))) {

            }
            else{
                ball.xDir = -ball.xDir;
                ball.yDir = -ball.yDir;
            }

The dimensions of each object are defined by essentially using the width and height of each object, dividing either value by two (for either the x or the y direction) and checking if the ball's (collision box) position has intersected with that of a paddle or a border:

// Ball dimensions
            float ballTop, ballBottom, ballLeft, ballRight;
            ballTop = ball.posY + (ball.height / 2.0f);
            ballBottom = ball.posY - (ball.height / 2.0f);
            ballLeft = ball.posX - (ball.width / 2.0f);
            ballRight = ball.posX + (ball.width / 2.0f);

            // Wall Dimension
            float topWallBottom = topWall.posY - (topWall.height / 2.0);
            float topWallTop = topWall.posY + (topWall.height / 2.0);
            float bottomWallBottom = bottomWall.posY - (bottomWall.height / 2.0);
            float bottomWallTop = bottomWall.posY + (bottomWall.height / 2.0);

            // Left Paddle Dimensions
            float leftPaddleTop = leftPaddle.posY + (leftPaddle.height / 2.0f);
            float leftPaddleBottom = leftPaddle.posY - (leftPaddle.height / 2.0f);
            float leftPaddleRight = leftPaddle.posX + (leftPaddle.width / 2.0f);
            float leftPaddleLeft = leftPaddle.posX - (leftPaddle.width / 2.0f);
            // Right Paddle Dimensions
            float rightPaddleTop = rightPaddle.posY + (rightPaddle.height / 2.0f);
            float rightPaddleBottom = rightPaddle.posY - (rightPaddle.height / 2.0f);
            float rightPaddleRight = rightPaddle.posX + (rightPaddle.width / 2.0f);
            float rightPaddleLeft = rightPaddle.posX - (rightPaddle.width / 2.0f);

For some reason, the ball seems to be passing right through the paddle and not redirecting at all. I'm pretty sure that I have everything set up correctly but I can't really determine what is preventing the ball's collisions from being detected.

Is there something that I'm doing wrong conceptually, or is there just a small mechanical issue? I feel like its the latter, but I can't be sure.

Here is the full code for reference.

Of course, any other specific suggestions about how to implement collision detection here would be welcomed, thanks!

\$\endgroup\$
  • 1
    \$\begingroup\$ Object A "Passing through" Object B often means that Object A goes 'too fast' and never 'overlaps' Object B, so if you check "intersection" to see if there is a "collision", you'll skip it. A couple of ways to get around this: 1) increase the size (thickness) of the paddle 2) increase the rate at which you perform your 'physics' update 3) instead of doing a "object-object collision detection", do a "object-at-frame-1-to-object-at-frame-2-path-object collision detection"; you detect the collision between the object B and a line segment of object A between this frame and the last one. \$\endgroup\$ – Vaillancourt Feb 24 '16 at 4:31
  • 1
    \$\begingroup\$ Search around here, this problem has been asked a couple of times. \$\endgroup\$ – Vaillancourt Feb 24 '16 at 4:32
1
\$\begingroup\$

Objects passing through each other, in simulation, is called tunnelling and is a very common problem. There are numerous ways round it, some of which have been highlighted already.

A common way to solve fast moving, small objects from tunelling is to fire a ray between their previous position, and current position, and checking for intersection. If you detect one then you move your object to the intersection point then run your intersection test.

So your code would now do something like

if(IntersectRay(PreviousPos, CurrentPos, &IntersectionPos))
{
 BallPos = IntersectionPos;
}

Your InterectRay would looke something like

if(PreviousPos.x >  LeftBat.x && CurrentPos.x < LeftBat.x)
{
    // We have crossed the bat's plane check to see where y was
    float percentAlong = (LeftBat.x - PreviousPos.x) / (CurrentPos.x - PreviousPos.x);
    float yIntersection = percentAlong * (CurrentPos.y - PreviousPos.y) + PreviousPos.y;

    // Is Y within bat's bounds?
}

I've not run this code but you can see what I'm doing. Checking to see if the ray crosses a bat's vertical plane then, if it does, checking to see where the y interesction was and seeing if that is within the bat's height. If it is, then you return that intersection as found and true.

That way you should mostly pick up intersections.

More advanced versions of this can be a case of extrapolating sphere collisions, instead of rays which can pass through narrow gaps, or even scaling the collision geometry along velocity.

Basically real time physics simulation is difficult for exactly the problems that you are coming across.

\$\endgroup\$
  • \$\begingroup\$ The technical term for this is continuous collision detection \$\endgroup\$ – Coburn Oct 11 '16 at 17:42
0
\$\begingroup\$

I am just replying from the top of my head. But I think that your if should be something like this:

if (((leftPaddleBottom <= ballBottom) &&
            (leftPaddleTop <= ballTop) &&
            (leftPaddleLeft < ballLeft) &&
            (leftPaddleRight > ballLeft)))

For the left paddle: The ball should be within the limits of the paddle (top and bottom),

GOOD
___
| |
| |O
|_|

BAD
___
| |
| |
|_|
   O

The left side of the ball should be smaller than the right side of the paddle but greater than the left side of the paddle

GOOD
___
| |
| O
|_|

BAD
  ___
  | |
O | | 
  |_|

Hope it helps.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.