# Sonic 2d collisions

This topic is 5197 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Well basically my 2d world consists of a whole mass of line segments. I have a function whereby if I supply a start point, and a movement vector, the first point that hits a world obstacle is returned. Now, I have a bounding circle. I need to make it bounce about like it does in Sonic...I'm guessing a pinball-style physics engine would be appropriate.. but I wouldn't know where to start. Does anyone have any links to a tutorial on a robust collision detection+response algorithm suited for this type of collision detection..and yes I noticed all the collision threads, I checked them but they didn't seem to have what I wanted.

##### Share on other sites
So what I get from your post is that you need collision detection and response between a moving circle and an environment made of static line segments - is that correct?

##### Share on other sites
yes indeed. I set up a bsp tree with them for extra speed..but I don't need to use it..

##### Share on other sites
Ok. If you need a broad-phase at all for this it can probably be fairly simple, so we'll skip that. For the narrow phase, you ideally want a function that returns all useful information about the intersection between a moving circle and a line segment. Such information would include:

1. A penetration depth and normal if the objects are initially intersecting
2. A time, point, and normal of intersection otherwise

The static test involves finding the distance between a line segment and the circle center. If the distance is less than the circle radius, the normal is the normalized vector from the closest point on the segment, to the circle center.

The swept test requires first sweeping the circle against the infinite line containing the segment, which is fairly simple. You may also have to sweep the circle against the segment endpoints, which involves solving a quadratic. From these tests you can find the point on the circle that first touches the segment; the normal is then the normalized vector from this point to the circle center.

For such a simple test, there's actally quite a bit to it. I have some code that does all of the above; let me know if you'd like to take a look at it.

The collision detection is really the hard part. Once you get that in place, making the circle bounce around in a fairly realistic manner is fairly straightforward.

##### Share on other sites
well basically here's what I've tried doing... For any circle of a given radius, and a collision line segment, there muust logically be another segment parallel to the collision plane where the circle can occur. I usually just check collisions with that and bang I'm done. It screws up when I'm already on this secondary plane, and attempt to move between the actual collision plane and the secondary plane. The collision isn't detected. As a result, I get weird glitchy movement.

##### Share on other sites
hello? jyk, I'd like to see your program...

##### Share on other sites
Here you go:

namespace jyk {namespace Intersection {// --------------------------------------------------------------------------------------template <class T> struct Sweep2{    enum {NONE,          STATIC,          STATIC_INVALID_NORMAL,          SWEPT};              int         type;    T           t;    Vector2<T>  normal;    T           distance;    int         numPoints;    Vector2<T>  points[2];};// --------------------------------------------------------------------------------------template <class T> bool Circle2Seg2(    const Vector2<T> C,             // Circle center    T r,                            // Circle radius    const Vector2<T> V,             // Circle velocity    const Vector2<T> O,             // Line origin    const Vector2<T> D,             // Line direction    const Vector2<T> n,             // Line normal    T tMax,                         // Max time (go elsewhere)    Sweep2<T>& sweep,               // Output info    bool cullBack,                  // Cull if circle starts behind line    T epsilon = Math<T>::EPSILON)   // Epsilon for parallel test{     Vector2<T> d = C - O;    T dn = d.Dot(n);        // Starts behind line    int sweepEndpoint;    if (dn < (T)0.0)    {        if (cullBack)            return false;                // Sweep from back        if (dn < -r)        {            T Vn = V.Dot(n);            if (Vn < epsilon)                return false;                        T num = -dn - r;            if (num > tMax * Vn)                return false;                        sweep.t = num / Vn;            T s = Vector2<T>::Dot(d + sweep.t * V, D);            if (s < (T)0.0)                sweepEndpoint = 0;            else if (s > D.Dot(D))                sweepEndpoint = 1;            else            {                sweep.type = Sweep2<T>::SWEPT;                sweep.normal = -n;                sweep.numPoints = 1;                sweep.points[0] = C + sweep.t * V - r * sweep.normal;                return true;            }        }        // Initially intersects line        else        {            T s = d.Dot(D);            if (s < (T)0.0)                sweepEndpoint = 0;            else if (s > D.Dot(D))                sweepEndpoint = 1;            else            {                sweep.type = Sweep2<T>::STATIC;                sweep.normal = -n;                sweep.distance = r + dn;                return true;            }        }    }    // Starts on or in front of line    else    {        // Sweep from front        if (dn > r)        {            T Vn = V.Dot(n);            if (Vn > -epsilon)                return false;                        T num = -dn + r;            if (num < tMax * Vn)                return false;                        sweep.t = num / Vn;            T s = Vector2<T>::Dot(d + sweep.t * V, D);            if (s < (T)0.0)                sweepEndpoint = 0;            else if (s > D.Dot(D))                sweepEndpoint = 1;            else            {                sweep.type = Sweep2<T>::SWEPT;                sweep.normal = n;                sweep.numPoints = 1;                sweep.points[0] = C + sweep.t * V - r * sweep.normal;                return true;            }        }        // Initially intersects line        else        {            T s = d.Dot(D);            if (s < (T)0.0)                sweepEndpoint = 0;            else if (s > D.Dot(D))                sweepEndpoint = 1;            else            {                sweep.type = Sweep2<T>::STATIC;                sweep.normal = n;                sweep.distance = r - dn;                return true;            }        }    }        if (sweepEndpoint == 0)    {        sweep.normal = -n.Perp();        return (Circle2Point2(C, r, V, O, tMax, sweep));    }    if (sweepEndpoint == 1)    {        sweep.normal = n.Perp();        return (Circle2Point2(C, r, V, O + D, tMax, sweep));    }}// --------------------------------------------------------------------------------------template <class T> bool Circle2Point2(    const Vector2<T> C,             // Circle center    T r,                            // Circle radius    const Vector2<T> V,             // Circle velocity    const Vector2<T> P,             // Point    T tMax,                         // Max time    Sweep2<T>& sweep,               // Output info    T epsilon = Math<T>::EPSILON)   // Epsilon for normal validation{    Vector2<T> d = C - P;    T c = d.Dot(d) - r * r;        // Sweep    if (c > (T)0.0)    {        T b = V.Dot(d);        if (b >= (T)0.0) // Directed away            return false;                    T a = V.Dot(V);        T disc = b * b - a * c;        if (disc < (T)0.0) // Missed            return false;        sweep.t = -b - Math<T>::Sqrt(disc);                if (sweep.t < (T)0.0) // Shouldn't happen            return false;                    if (sweep.t > tMax * a) // Intersection occurs after tMax            return false;        sweep.type = Sweep2<T>::SWEPT;        sweep.t /= a;        sweep.numPoints = 1;        sweep.points[0] = P;        sweep.normal = Vector2<T>::Normalize(d + sweep.t * V);    }    // Static intersection    else    {        sweep.type = Sweep2<T>::STATIC;        T l = d.Length();        if (l < epsilon) // No unique solution, normal not assigned            sweep.distance = r;        else        {            sweep.normal = d / l;            sweep.distance = r - l;        }    }    return true;}// --------------------------------------------------------------------------------------} // namespace Intersection} // namespace jyk

• ### Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 11
• 15
• 21
• 26
• 11