🔒 Locked
Collision Detection
Advertisement
Original Post
I need help with circle collision detection! I don't really know how to get started. I know if use the pythagorean (sp?) theroem, I can figure out the length between two circles and then see if they are touching, but I have no idea where to go with the whole physics of it! Does anyone have any code that would do what I need, or at least get me in the right direction? If not that, any links?
::Daricon::
Edited by - Daricon on 4/25/00 8:16:17 PM
To make the code above a little easier to read, the formula is:
Length=sqrt(X*X + Y*Y);
Silly me, I didn''t read the whole problem. To see if 2 circles are touching, you do this:
//gets distance petween Pos1 and Pos2 and stores it into Vector
VectorSubtract2d(Vector, Pos1, Pos2);
//gets the length of between Pos1 and Pos2 thru Vector
VectorLength=VectorLength2d(Vector);
//add the two hit radius to get accurate hit detection
TotalHitRadius=HitRadius1+HitRadius2;
if(VectorLength<=TotalHitRadius)
{
return true; //collision detected
}
Length=sqrt(X*X + Y*Y);
Silly me, I didn''t read the whole problem. To see if 2 circles are touching, you do this:
//gets distance petween Pos1 and Pos2 and stores it into Vector
VectorSubtract2d(Vector, Pos1, Pos2);
//gets the length of between Pos1 and Pos2 thru Vector
VectorLength=VectorLength2d(Vector);
//add the two hit radius to get accurate hit detection
TotalHitRadius=HitRadius1+HitRadius2;
if(VectorLength<=TotalHitRadius)
{
return true; //collision detected
}
You might not need to do the square root at all. Your final comparison could be something like:
if(VectorLengthSquared <= TotalHitRadiusSquared)
here, VectorLengthSquared = X*X + Y*Y, and TotalHitRadiusSquared would probably be a constant. I just know that sqrt() is pretty computationally expensive.
Daricon, I think you were also wondering what to do after a collision has occurred. I assume your two circles have velocities, which need to change after the collision. Here''s some code:
if(collisionDetected){
// the actual length is needed now
FLOAT VectorLength = sqrt(VectorLengthSquared);
// make separation distances into unit vectors
// you might consider checking that VectorLength != 0 1st
FLOAT unitSepX = X / VectorLength;
FLOAT unitSepY = Y / VectorLength;
// This is how fast the circles are hitting each other.
// basically, I''m calculating 2 dot products and adding
// them.
FLOAT collisionVelocity =
(unitSepX * -circle1.velX +
unitSepY * -circle1.velY) +
(unitSepX * circle2.velX +
unitSepY * circle2.velY) +
// include this if you want a slightly inelastic collision
collisionVelocity *= .75;
// you may have to change the signs here
circle1.velX += unitSepX * collisionVelocity;
circle1.velY += unitSepY * collisionVelocity;
circle2.velX -= unitSepX * collisionVelocity;
circle2.velY -= unitSepY * collisionVelocity;
}
if(VectorLengthSquared <= TotalHitRadiusSquared)
here, VectorLengthSquared = X*X + Y*Y, and TotalHitRadiusSquared would probably be a constant. I just know that sqrt() is pretty computationally expensive.
Daricon, I think you were also wondering what to do after a collision has occurred. I assume your two circles have velocities, which need to change after the collision. Here''s some code:
if(collisionDetected){
// the actual length is needed now
FLOAT VectorLength = sqrt(VectorLengthSquared);
// make separation distances into unit vectors
// you might consider checking that VectorLength != 0 1st
FLOAT unitSepX = X / VectorLength;
FLOAT unitSepY = Y / VectorLength;
// This is how fast the circles are hitting each other.
// basically, I''m calculating 2 dot products and adding
// them.
FLOAT collisionVelocity =
(unitSepX * -circle1.velX +
unitSepY * -circle1.velY) +
(unitSepX * circle2.velX +
unitSepY * circle2.velY) +
// include this if you want a slightly inelastic collision
collisionVelocity *= .75;
// you may have to change the signs here
circle1.velX += unitSepX * collisionVelocity;
circle1.velY += unitSepY * collisionVelocity;
circle2.velX -= unitSepX * collisionVelocity;
circle2.velY -= unitSepY * collisionVelocity;
}
I guess I should have called the post "Collision Response" or something like that.
WhatEver:
Now let me get this straight, is the pvector2d a type that is already defined or something? If it''s not, what is it then? And the same thing for VectorSubtract2d(). Is that something MSVC is going to know about?
Eric:
Where are you defining X and Y? I''m a little confused! Does X = circle2.X - circle1.X, and the same for Y? That''s about all I can guess. That''s a good idea about comparing leaving the length squared until you really need it.
This has been good stuff so far. Thanks you two. Please try to get back to me!
::Daricon::
WhatEver:
Now let me get this straight, is the pvector2d a type that is already defined or something? If it''s not, what is it then? And the same thing for VectorSubtract2d(). Is that something MSVC is going to know about?
Eric:
Where are you defining X and Y? I''m a little confused! Does X = circle2.X - circle1.X, and the same for Y? That''s about all I can guess. That''s a good idea about comparing leaving the length squared until you really need it.
This has been good stuff so far. Thanks you two. Please try to get back to me!
::Daricon::
ummm, why don't you just save the radius length of each particular bounding sphere or circle. Then compare the distance between the two objects with the sum of their radii. If the radii sum is more, no collision has occured. If it is less, then a collision MAY have occured. You could preform further tests to increase accuracy, or just say "screw it, they hit each other" and run with that...
<(o)>
Edited by - aDasTRa on 4/26/00 11:09:57 PM
<(o)>
Edited by - aDasTRa on 4/26/00 11:09:57 PM
me? i thought it was simple enough, but maybe not...say somewhere in the object struct or class you have a variable like
float CollisionRadius;
then assign it a value so that the distance between the center of the object and the farthest edge is contained in the circle, like
Object1.CollisionRadius = 5;
do that for all objects...ie
Object2.CollisionRadius = 5;
then compare their distance
using the distance formula (i think this is it)
Dist = sqrt((Object1.x - Object2.x)^2 + (Object1.y - Object2.y)^2)
and add the radii:
Sum = Object1.CollisionRadius + Object2.CollisionRadius;
Then if Dist < Sum, a collision has occured, else they haven't hit each other
<(o)>
Edited by - aDasTRa on 4/26/00 11:29:52 PM
float CollisionRadius;
then assign it a value so that the distance between the center of the object and the farthest edge is contained in the circle, like
Object1.CollisionRadius = 5;
do that for all objects...ie
Object2.CollisionRadius = 5;
then compare their distance
using the distance formula (i think this is it)
Dist = sqrt((Object1.x - Object2.x)^2 + (Object1.y - Object2.y)^2)
and add the radii:
Sum = Object1.CollisionRadius + Object2.CollisionRadius;
Then if Dist < Sum, a collision has occured, else they haven't hit each other
<(o)>
Edited by - aDasTRa on 4/26/00 11:29:52 PM
aDastra: you''re correct, but what you described is about what Whatever already described in his 2nd post.
Daricon, that''s correct, X and Y are just the separation distances between the centers of the two circles. Also, I thought of a simple alternative to the code I gave earlier: If you detect a collision, you could actually just switch the two circles'' velocities. Here''s the code:
if(collisionDetected){
FLOAT tempX = circle1.velX;
FLOAT tempY = circle1.velY;
circle1.velX = circle2.velX;
circle1.velY = circle2.velY;
circle2.velX = tempX;
circle2.velY = tempY;
}
Note the following limitations: your collision will be 100% elastic, which looks particularly retarded in head-on collisions. Also, my previous code could be modified easily to simulate circles of different masses, whereas this "pseudo-physics" solution can only treat them as equal masses.
Daricon, that''s correct, X and Y are just the separation distances between the centers of the two circles. Also, I thought of a simple alternative to the code I gave earlier: If you detect a collision, you could actually just switch the two circles'' velocities. Here''s the code:
if(collisionDetected){
FLOAT tempX = circle1.velX;
FLOAT tempY = circle1.velY;
circle1.velX = circle2.velX;
circle1.velY = circle2.velY;
circle2.velX = tempX;
circle2.velY = tempY;
}
Note the following limitations: your collision will be 100% elastic, which looks particularly retarded in head-on collisions. Also, my previous code could be modified easily to simulate circles of different masses, whereas this "pseudo-physics" solution can only treat them as equal masses.
Eric:
I tried that new code. It seems to work pretty well in some cases, but it gets funky in others. I think the problem has to do with this part:
Let's say that circle1 is on the left and has a positive X velocity and circle 2 is one the right and has a neagtive one. This is assuming that +Xvelocity moves the circle to the right and -Xvelocity to the left. Forget about Y velocity for a second. It works in this case and they both bounce off each other (a little slower) in opposite directions. The funky stuff starts if circle2 in left with a +Xvel and circle1 is on the right with a -Xvel. They sort of eat into each other and don't bounce off right.
How did you get past this? I haven't done it yet, but I guess I will see where the circles are before the collision and then have some if statements to decide whether I do
or
and the same for the other three lines.
Anyway, thanks Eric. You've been most helpful.
::Daricn::
Edited by - Daricon on 4/27/00 8:35:50 PM
I tried that new code. It seems to work pretty well in some cases, but it gets funky in others. I think the problem has to do with this part:
circle1.velX += unitSepX * collisionVelocity;
circle1.velY += unitSepY * collisionVelocity;
circle2.velX -= unitSepX * collisionVelocity;
circle2.velY -= unitSepY * collisionVelocity;
Let's say that circle1 is on the left and has a positive X velocity and circle 2 is one the right and has a neagtive one. This is assuming that +Xvelocity moves the circle to the right and -Xvelocity to the left. Forget about Y velocity for a second. It works in this case and they both bounce off each other (a little slower) in opposite directions. The funky stuff starts if circle2 in left with a +Xvel and circle1 is on the right with a -Xvel. They sort of eat into each other and don't bounce off right.
How did you get past this? I haven't done it yet, but I guess I will see where the circles are before the collision and then have some if statements to decide whether I do
circle1.velX += unitSepX * collisionVelocity;
or
circle1.velX -= unitSepX * collisionVelocity;
and the same for the other three lines.
Anyway, thanks Eric. You've been most helpful.
::Daricn::
Edited by - Daricon on 4/27/00 8:35:50 PM
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement