views:

481

answers:

5

I have an issue where if the ball hits the paddle just right, it gets locked inside and can't be released. It happens sometimes on the player paddle, but since you have control of it, all you have to to do is move it and it escapes. The computer follows the ball perfectly, so once it gets inside it never can escape, leading to what happens in this video. Now this only happens when I increase the framerate, if it's really low, it kinda, errors out and "goes through" the paddle resulting in a point gained. At least in this case, it's not a noticeable bug and the game continues to play.

Naturally I want the framerate to be as smooth as possible so..., like to sort this out. Here's my code for the very simplistic collision detection. Using UIImageViews.

if (CGRectIntersectsRect (ball.frame, playerPaddle.frame))
    {
     if (ball.center.y < playerPaddle.center.y) //hits the "top" of the computer paddle
     {
      AudioServicesPlaySystemSound (hitSound);
      ballVelocity.y = -ballVelocity.y; // turn ball around if collide
     }
    }

    if (CGRectIntersectsRect (ball.frame, computerPaddle.frame))
    {
     if (ball.center.y > computerPaddle.center.y) //hits the "bottom" of the computer paddle
     {
      AudioServicesPlaySystemSound (hitSound);
      ballVelocity.y = -ballVelocity.y; // turn ball around if collide
     }
    }

Thanks for the help.

+4  A: 

Without seeing the rest of your code, this is just a guess, but what is probably happening is the ball's velocity continually gets flipped back and forth. You need to move the ball outside the paddle after it hits, or have a "minimum time between collisions"

Mark P Neyer
You got there first. I agree. The ball is ping-ponging around INSIDE the paddle. You need to make sure that when you "turn the ball around" that it definitely exits the paddle before being tested for collision again.
Amagrammer
Interesting point, the game loop is so high that it's being tested again before it even escapes. Right?
nullArray
Yup, you've got it. I would have it automatically move the ball outside the paddle.
Mark P Neyer
A: 

Needed an extra condition.

if (ballVelocity.y > 0 && CGRectIntersectsRect (ball.frame, playerPaddle.frame))
    {
     if (ball.center.y < playerPaddle.center.y) //player
     {
      AudioServicesPlaySystemSound (volleyFileID);
      ballVelocity.y = -ballVelocity.y;
     }
    }

    if (ballVelocity.y < 0 && CGRectIntersectsRect (ball.frame, computerPaddle.frame)) //computer
    {
     if (ball.center.y > computerPaddle.center.y)
     {
      AudioServicesPlaySystemSound (volley2FileID);
      ballVelocity.y = -ballVelocity.y;
     }
    }
nullArray
+2  A: 

In addition to the answers above, your ball should really never be allowed to actually enter the paddle. Specifically, if the ball is within the paddle, you should reset its position to just outside of the paddle at the same time you switch its y-velocity.

Specifically:

if (CGRectIntersectsRect (ball.frame, playerPaddle.frame))
{
    AudioServicesPlaySystemSound (hitSound);
    CGRect frame = ball.frame;
    frame.origin.y = playerPaddle.frame.origin.y - frame.size.height;
    ball.frame = frame;
    ballVelocity.y = -ballVelocity.y; // turn ball around if collide
}

if (CGRectIntersectsRect (ball.frame, computerPaddle.frame))
{               
    AudioServicesPlaySystemSound (hitSound);
    CGRect frame = ball.frame;
    frame.origin.y = CGRectGetMaxY(computerPaddle.frame);
    ball.frame = frame;
    ballVelocity.y = -ballVelocity.y; // turn ball around if collide
}
Ed Marty
In addition to seting its position just outside the paddle, also consider only allowing a collision with a paddle if the velocity indicates it's moving in that direction. If the ball is moving away from the paddle, don't even check for a collision.
Ross
A: 

I think the easiest way to handle it is to add in logic so that after a collision with the paddle, the ball's velocity vector is forced to be always pointing away from the center point of the paddle. That way, even if the ball "collides again" with the paddle (because it went too far inside to get out again on the next tick of the event loop), it will just continue heading away from the paddle after the second "bounce".

Jeremy Friesner
A: 

This problem was similar to an issue I was having with the ball being caught inside of the paddle. What I did to solve this was create a boolean. When there is a collision, the boolean is set to true. When the ball hits a wall, the boolean is set to false. Inside of the conditional statement where we check for Rectangle Intersection, I add a check to see if collision is set to false.

So, ultimately what will happen is this:

  • The ball hits paddle and boolean is set to true.
  • The velocity is reversed on the ball
  • When the collision detection tries to execute, it doesn't because the boolean is true
  • The ball bounces off a wall and the boolean is reset to false
  • The ball collides with the other paddle and the boolean is set to true again

Try this and let me know how it works.

-Brandon

byachna