Page 1 of 1

[SOLVED] Simple ball collision depending on edge of impact

Posted: Fri Mar 26, 2010 5:25 pm
by Bullet Pulse
So I'm trying to make a ball change directions based on where it hits a brick (pointer iterator).
If it hits the top or bottom of a brick, I want the yVel to reverse, and if it hits the left or right of the brick,
I want the xVel to reverse; if it hits both, then I want it to reverse both velocities.

Right now, the Y bouncing is working fine, but the X bouncing is not.

EDIT:

Here is the rewritten understandable version of the code:

Code: Select all

if (IsCollision(&(*ballIter)->getDstRect(), &(*brickIter)->getDstRect()))
            {
                //If the left edge of the ball is inside the brick
                if ((*ballIter)->getX() > (*brickIter)->getX() &&
                    (*ballIter)->getX() < (*brickIter)->getX() + Brick::WIDTH)
                {
                    (*ballIter)->ReverseX(); //Reverse the ball's x velocity
                }

                //If the right edge of the ball is inside the brick
                if ((*ballIter)->getX() + Ball::BALL_WIDTH  > (*brickIter)->getX() &&
                    (*ballIter)->getX() + Ball::BALL_WIDTH < (*brickIter)->getX() + Brick::WIDTH)
                {
                    (*ballIter)->ReverseX(); //Reverse the ball's x velocity
                }
                
                //If the top edge of the ball is inside the brick
                if (((*ballIter)->getY() > (*brickIter)->getY() &&
                    (*ballIter)->getY() < (*brickIter)->getY() + Brick::HEIGHT))
                {

                    (*ballIter)->ReverseY(); //Reverse the ball's y velocity
                }

                //If the bottom edge of the ball is inside the brick
                if ((*ballIter)->getY() + Ball::BALL_HEIGHT  > (*brickIter)->getY() &&
                    (*ballIter)->getY() + Ball::BALL_HEIGHT < (*brickIter)->getY() + Brick::HEIGHT)
                {

                    (*ballIter)->ReverseY(); //Reverse the ball's y velocity
                }
}

Re: Simple ball collision depending on edge of impact

Posted: Fri Mar 26, 2010 5:46 pm
by lotios611
EDIT: Try replacing your second else with an else if. I'm not 100% sure if that will work though.

Code: Select all

bool Collision(Rect rect1, Rect rect2) {
//Determine overlap for each axis
float xDist = abs(rect1.x - rect2.x);
float yDist = abs(rect1.y - rect2.y);

//minimal amount of distance that the two can be apart and not collide
float xMinDist = rect1.width + rect2.width;
float yMinDist = rect1.height + rect2.height;

if(xDist >= xMinDist || yDist >= yMinDist) return false; //neither axis is colliding

float xOverlap = xDist - xMinDist;
float yOverlap = yDist - yMinDist;

if(xOverlap < yOverlap) xvel = -xvel;
else yvel = -yvel;

return true;
}
I got this code from here. You will probably have to do some major hacking at it to get it to work.

Re: Simple ball collision depending on edge of impact

Posted: Fri Mar 26, 2010 7:12 pm
by XianForce
That code doesn't work ^^... You can get it to work with some slight modification, but if you do some searching around the forums, the actual ES collision code was posted by Falco somewhere, and it's very useful.

Re: Simple ball collision depending on edge of impact

Posted: Fri Mar 26, 2010 7:33 pm
by Bullet Pulse
XianForce wrote:That code doesn't work ^^... You can get it to work with some slight modification, but if you do some searching around the forums, the actual ES collision code was posted by Falco somewhere, and it's very useful.
How can I get it to work?

Re: Simple ball collision depending on edge of impact

Posted: Sat Mar 27, 2010 11:43 am
by XianForce
Bullet Pulse wrote:
XianForce wrote:That code doesn't work ^^... You can get it to work with some slight modification, but if you do some searching around the forums, the actual ES collision code was posted by Falco somewhere, and it's very useful.
How can I get it to work?
Well that code uses full widths. You need to use half widths:

Code: Select all

bool Collision(Rect rect1, Rect rect2) {
//Determine overlap for each axis
float xDist = abs(rect1.x - rect2.x);
float yDist = abs(rect1.y - rect2.y);

//minimal amount of distance that the two can be apart and not collide
float xMinDist = (rect1.width + rect2.width) / 2;
float yMinDist = (rect1.height + rect2.height) / 2;

if(xDist >= xMinDist || yDist >= yMinDist) return false; //neither axis is colliding

float xOverlap = xDist - xMinDist;
float yOverlap = yDist - yMinDist;

if(xOverlap < yOverlap) xvel = -xvel;
else yvel = -yvel;

return true;
}

Technically, it would 'work' before, the collision would just appear to be off. But I'm pretty sure that should do it ^^.... Although I only changed the width/height to half width/height - and it's untested...

Another thing to note: The x, y of the rect should be the CENTER and NOT THE TOP LEFT CORNER. Otherwise it won't work right.

EDIT: But your better off using the ES collision code that Falco posted. It returns a collision normal, which I'm finding very useful! You can push objects back by the normal to resolve the collision, and I usually have stuff that rebounds off walls, so I just normalize the normal, and reflect a velocity vector across it =D