2D Collisions

Started by
13 comments, last by EdwardDingle 14 years ago
Thanks again, the code worked great, better than I expected actually, I had to write out the results because I did not actually understand why it worked along long walls, but I see why I was wrong now.

Now I need to figure out how to get the resulting angle and position after hitting the wall, which seems to be where I was having the most difficulty understanding before, and why I decided to come here for help.

The steps I need to do (and I have no clue if im right) is:
-Calculate how much penetration there has been into the rectangle.
-Move the circle against the wall
-Calculate New Vector(???)
Advertisement
the code for sphere - rectangle collision is relatively straight forward. The principle is easy (if you consider when a circle intersects a circle).

1) find point on rectangle perimeter the closest to the circle centre.
2) is that point outside the circle, no collision.
3) else push the sphere away so that that point is at exactly at the distance equal to the radius of the sphere, from the sphere centre.

Quote:
Vector closestPointFromRectangle(Vector point, Vector min, Vector max){     Vector closest = point;     if(point.x < min.x) closest.x = min.x;     if(point.x > max.x) closest.x = max.x;     if(point.y < min.y) closest.y = min.y;     if(point.y > max.y) closest.y = max.y;     return point;}bool CollideCircleOnRectangle(Vector& centre, float radius, Vector min, Vector max){    // closest point on rectangle to sphere centre    Vector closest = closestPointFromRectangle(centre, min, max);    // vector between sphere centre and closest point on rectangle    Vector delta = (centre - closest);    // distance, squared, between sphere centre and closest point on rectangle    float distance_squared = delta.lengthSquared();    // if distance squared greater than radius squared, no intersection.    if (distance_squared > radius * radius) return false;    // distance between the sphere centre and closest point on rectangle    float distance = sqrt(distance_squared);    // vector needed to push sphere away from rectangle, so that distance    // between sphere and closest point on rectangle is exactly equal to radius.    Vector push_vector = delta * (radius - distance) / distance;        // push sphere away from rectangle.    centre += push_vector;    return true;     }


EDIT : if the sphere centre is inside the rectangle, you'll need some more code!

Everything is better with Metal.

How do I update the current vector that my ship is moving in? Do I add the push vector to that? When I do that it works, but I feel like there is a loss of momentum when I "bounce"

[Edited by - EdwardDingle on March 30, 2010 11:02:57 PM]
Quote:
Do I add the push vector to that? When I do that it works, but I feel like there is a loss of momentum when I "bounce"


Nope, that's not accurate enough.

You reflect the velocity / displacement / move vector (whatever it is called) by 'reflecting' it against the collision normal, Which happens to be the delta vector (normalised). This reflection is basically calculating a collision impulse that will 'inverse' the velocity along the collision normal, thus making a bounce effect.

Quote:
bool CollideCircleOnRectangle(Vector& centre, Vector& velocity, float radius, Vector min, Vector max){    // closest point on rectangle to sphere centre    Vector closest = closestPointFromRectangle(centre, min, max);    // vector between sphere centre and closest point on rectangle    Vector delta = (centre - closest);    // distance, squared, between sphere centre and closest point on rectangle    float distance_squared = delta.lengthSquared();    // if distance squared greater than radius squared, no intersection.    if (distance_squared > radius * radius) return false;    // distance between the sphere centre and closest point on rectangle    float distance = sqrt(distance_squared);    // vector needed to push sphere away from rectangle, so that distance    // between sphere and closest point on rectangle is exactly equal to radius.    Vector push_vector = delta * (radius - distance) / distance;        // push sphere away from rectangle.    centre += push_vector;    // collision normal    Vector collision_normal = delta / distance;    // coefficient of restitution (how much bounce you want).    const float coef_restitution = 0.7f;    // how much impact we get    float impact_speed = velocity.dotProduct(collision_normal);    // objects move away from each other. no collison impulse    // or else the objects will 'stick' into each other.    if(impact_speed > 0.0f)        return true;    // collision impulse    Vector collision_impulse = collision_normal * (impact_speed * -(1.0f + coef_restitution));    // apply collision impulse    velocity += collision_impulse;        return true;}

Everything is better with Metal.

Thanks again, you're quite brilliant! :) Clearly I need to brush up on Euclidean vectors.

This topic is closed to new replies.

Advertisement