[SOLVED] Simple ball collision depending on edge of impact

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
User avatar
Bullet Pulse
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 89
Joined: Sun Feb 21, 2010 6:25 pm

[SOLVED] Simple ball collision depending on edge of impact

Post 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
                }
}
Last edited by Bullet Pulse on Thu Apr 01, 2010 2:44 pm, edited 5 times in total.
Image
User avatar
lotios611
Chaos Rift Regular
Chaos Rift Regular
Posts: 160
Joined: Sun Jun 14, 2009 12:05 pm
Current Project: Game engine for the PC, PSP, and maybe more.
Favorite Gaming Platforms: Gameboy Micro
Programming Language of Choice: C++

Re: Simple ball collision depending on edge of impact

Post 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.
"Why geeks like computers: unzip, strip, touch, finger, grep, mount, fsck, more, yes, fsck, fsck, fsck, umount, sleep." - Unknown
XianForce
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 767
Joined: Wed Oct 29, 2008 8:36 pm

Re: Simple ball collision depending on edge of impact

Post 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.
User avatar
Bullet Pulse
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 89
Joined: Sun Feb 21, 2010 6:25 pm

Re: Simple ball collision depending on edge of impact

Post 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?
Image
XianForce
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 767
Joined: Wed Oct 29, 2008 8:36 pm

Re: Simple ball collision depending on edge of impact

Post 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
Post Reply