PDA

View Full Version : Collision Between Objects


Justin Brimm
2002.12.11, 04:35 AM
Taking a hint from the O'Reilly tutorial, I've created a simple little program that has a ball that bounces around. I wasn't content with that, so I decided to add gravity, wind and friction and such. I got that to work (yet not quite perfect), but I decided to press on and make multiple balls that also collide with each other.

My question is, how do I do this? I know how to detect the collision (simply comparing points and locations), but I can't get the locations of the other balls. All the balls are kept in an array, and to test the collision of each ball I need to run a for loop. My problem here is, how do I go out and grab all the locations of all the other balls that are in the same array inside the if argument for the collision?

I don't know if that's clear at all, but hopefully someone can help.

Note: A for loop is already running, which grabs the current ball in the loop to be tested to all the other balls.

Justin Brimm
2002.12.11, 04:45 AM
P.S. How do you do 'and' in an if statement? I believe 'or' is ||, correct me if I'm wrong though.

skyhawk
2002.12.11, 04:57 AM
logical and is &&
very simple collision between 2 balls or spheres can be done using our good friend the distance formula(related to pythagorous)

x=ball1.x-ball2.x
y=ball1.y-ball2.y
r=ball1.radius+ball2.radius
if(x*x+y*y>r*r)
sucessful collision


there is some problems with this code, it does not take into account fast moving objects. So, if you have balls that move faster than the diameter of the ball, this simple solution doesn't work. It also doesn't take moving balls at all, as in a few cases it might show they do not collide, when in fact they did collide between giving time period. BUT! despite these fallacies, if you have all the balls in their position, it will tell you if any are touching any others.

Justin Brimm
2002.12.11, 05:21 AM
As stated above, the problem isn't how to detect the collision, but how to grab all the other ball positions out of the same array as the ball that's going to test collisions, so a collision can even be tested.

OneSadCookie
2002.12.11, 05:32 AM
I'm not sure I understand what you're asking, but I think maybe what you want is a double for loop:

int i;
for (i = 0; i < NUMBER_OF_BALLS; ++i)
{
int j;
for (j = 0; j < NUMBER_OF_BALLS; ++j)
{
float xDistance = balls[i].x - balls[j].x;
float yDistance = balls[i].y - balls[j].y;
float collisionDistance = balls[i].radius + balls[j].radius;

if (((xDistance * xDistance) + (yDistance * yDistance)) < (collisionDistance * collisionDistance))
{
/* a collision occurred */
}
}
}

Notice that this checks more pairs than are necessary (each pair is checked twice, bar each ball with itself which is only checked once).

You can fix this by changing the condition on the inner for loop from j < NUMBER_OF_BALLS to j < i.

kelvin
2002.12.11, 06:32 AM
what kind of array?

codemattic
2002.12.11, 08:02 AM
Originally posted by jbrimm
My question is, how do I do this? I know how to detect the collision (simply comparing points and locations), but I can't get the locations of the other balls.

managing collisions (not the actual math involved in detecting collisions) is quite an interesting problem. How do you create classes that are general enough to reuse - but specific enough to understand what to do in each of the many permutations that are possible with collisions.

Here is what I do. Im assuming you are using a object-oriented language.

I create a class called 'Group'. Group has an array of objects of type 'Sprite'. The *Group* class has the code to handle collisions. So I might have:

Group * badGuysGroup, * bulletsGroup, * goodGuyGroup;
...

so I have methods which allow me to:

//collide all sprites in this group w/ each other
badGuysGroup->collideGroup();

//collide all the sprites from one group with all the sprites of another
badGuysGroup->collideWithGroup(bulletsGroup);

//I can avoid doing collisions that wouldnt matter - like I would *not* do this:
bulletsGroup->collideGroup();
//because I dont need to test bullet-bullet collisions

//also if I have a specific sprite I want to collide with all bullets I can:
Sprite * goodGuySprite;
...
bulletsGroup->collideWithSprite(goodGuySprite);

hth,
Codemattic

Josh
2002.12.11, 09:08 AM
Originally posted by jbrimm
P.S. How do you do 'and' in an if statement? I believe 'or' is ||, correct me if I'm wrong though. "And" is && and you are correct, || is "or."

FCCovett
2002.12.11, 10:39 AM
There is a fairly recent and comprehensive article on sphere collision test for a billiard game that can be found on http://www.gamasutra.com (registration required, but it's free).

NYGhost
2002.12.11, 02:31 PM
Anyone have any info abount bounding boxes collision detection?

FCCovett
2002.12.11, 02:58 PM
I feel bad redirecting people from this forum to another, but http://www.flipcode.com is filled with posting and references about axis-aligned bounding boxes and collision detection. It's worth a peek.

skyhawk
2002.12.11, 03:46 PM
we should add how to do circle/sphere and bounding box collision detection to our FAQ.

ededed
2002.12.11, 04:10 PM
int i;
for (i = 0; i < NUMBER_OF_BALLS; ++i)
{
int j;
for (j = 0; j < NUMBER_OF_BALLS; ++j)
{

// Make sure that balls dont collide with themselves
if(i != j) {

float xDistance = balls[i].x - balls[j].x;
float yDistance = balls[i].y - balls[j].y;
float collisionDistance = balls[i].radius + balls[j].radius;

if (((xDistance * xDistance) + (yDistance * yDistance)) < (collisionDistance * collisionDistance))
{
/* a collision occurred */
}
}
}
}

NYGhost
2002.12.11, 04:50 PM
Sphere collisions are the easiest, once you try to get collision with other primitives it gets very tricky.
For most games spheres will work fine, except if you use physics with non spherical objects.

codemattic
2002.12.11, 04:54 PM
(this is off the top of my head - I havent tested it)

If you do your loops like this you avoid testing collisions twice.


int i;
for (i = 0; i < NUMBER_OF_BALLS - 1; ++i)
{
int j;
for (j = i+1; j < NUMBER_OF_BALLS; ++j)
{
... do testing here
}
}



-Codemattic