Jump to content
  • Advertisement
Sign in to follow this  
Shashi

Sonic 2d collisions

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!