views:

1255

answers:

3

I'm having trouble wrapping my mind around how to calculate the normal for a moving circle in a 2d space. I've gotten as far as that I'm suppose to calculate the Normal of the Velocity(Directional Speed) of the object, but that's where my college algebra mind over-heats, any I'm working with to 2d Circles that I have the centerpoint, radius, velocity, and position.

Ultimately I'm wanting to use the Vector2.Reflect Method to get a bit more realistic physics out of this exercise.

thanks ahead of time.

EDIT: Added some code trying out suggestion(with no avail), probably misunderstanding the suggestion. Here I'm using a basketball and a baseball, hence base and basket. I also have Position, and Velocity which is being added to position to create the movement.

        if ((Vector2.Distance(baseMid, basketMid)) < baseRadius + basketRadius)
        {
            Vector2 baseNorm = basketMid - baseMid;
            baseNorm.Normalize();
            Vector2 basketNorm = baseMid - basketMid;
            basketNorm.Normalize();
            baseVelocity = Vector2.Reflect(baseVelocity, baseNorm);
            basketVelocity = Vector2.Reflect(basketVelocity, basketNorm);
        }


        basePos.Y += baseVelocity.Y;
        basePos.X += baseVelocity.X;
        basketPos.Y += basketVelocity.Y;
        basketPos.X += basketVelocity.X;
        basketMid = new Vector2((basketballTex.Width / 2 + basketPos.X), (basketballTex.Height / 2 + basketPos.Y));
        baseMid = new Vector2((baseballTex.Width / 2 + basePos.X), (baseballTex.Height / 2 + basePos.Y));
+1  A: 

The normal of a circle at a given point on its edge is going to be the direction from its center to that point. Assuming that you're working with collisions of circles here, then one easy "shorthand" way to work this out would be that at the time of collision (when the circles are touching), the following will hold true:

Let A be the center of one circle and B the center of the other. The normal for circle A will be normalize(B-A) and the normal for circle B will be normalize(A-B). This is true because the point where they touch will always be colinear with the centers of the two circles.

spurserh
I'm going to add a bit of code to the original question to illustrate what I'm trying to accomplish. Thanks, I know actual understand what a normal is logically, but am still unclear on how to calculate it, and which vector should go in the first slot of Vector2.Reflect. Sorry I'm a bit dense when it comes to some of this stuff.
jon
+2  A: 

First the reflection. If I'm reading your code right, the second argument to Vector2.Reflect is a normal to a surface. A level floor has a normal of (0,1), and a ball with velocity (4,-3) hits it and flies away with velocity (4,3). Is that right? If that's not right then we'll have to change the body of the if statement. (Note that you can save some cycles by setting basketNorm = -baseNorm.)

Now the physics. As written, when the two balls collide, each bounces off as if it had hit a glass wall tangent to both spheres, and that's not realistic. Imagine playing pool: a fast red ball hits a stationary blue ball dead center. Does the red ball rebound and leave the blue ball where it was? No, the blue ball gets knocked away and the red ball loses most of its speed (all, in the perfect case). How about a cannonball and a golf ball, both moving at the same speed but in opposite directions, colliding head-on. Will they both bounce equally? No, the cannonball will continue, barely noticing the impact, but the golf ball will reverse direction and fly away faster than it came.

To understand these collisions you have to understand momentum (and if you want collisions that aren't perfectly elastic, like when beanbags collide, you also have to understand energy). A basic physics textbook will cover this in an early chapter. If you just want to be able to simulate these things, use the center-of-mass frame:

Vector2 CMVelocity = (basket.Mass*basket.Velocity + base.Mass*base.Velocity)/(basket.Mass + base.Mass);

baseVelocity -= CMVelocity;
baseVelocity = Vector2.Reflect(baseVelocity, baseNorm);
baseVelocity += CMVelocity;

basketVelocity -= CMVelocity;
basketVelocity = Vector2.Reflect(basketVelocity, basketNorm);
basketVelocity += CMVelocity;
Beta
I really appreciate the addition, but the problem is that code in the question does not work. I can't try and add Mass until I get the above to work.
jon
Could you be more specific? Does it fail to compile? Does the if statement fail to trigger when the balls are close, or trigger when the balls are far apart? Do the balls not move in straight lines? Do they bounce in a weird way? (And this is c++, right?)
Beta
It's C#, as it's XNA.
kyoryu
A: 

Caveat: I'm not going to assume that this is completely correct. Physics are not my specialty.

Movement has no effect on a normal. Typically, a normal is just a normalized (length 1) vector indicating a direction, typically the direction that a poly faces on a 3d object.

What I think you want to do is find the collision normal between two circles, yes? If so, one of the cool properties of spheres is that if you find the distance between the centers of them, you can normalize that to get the normal of the sphere.

What seems correct for 2d physics is that you take the velocity * mass (energy) of a sphere, and multiply that by the normalized vector to the other sphere. Add the result to the destination sphere's energy, subtract it from the original sphere's energy, and divide each, individually, by mass to get the resulting velocity. If the other sphere is moving, do the same in reverse. You can probably simplify the math down from there, of course, but it's late and I don't feel like doing it :)

If both spheres are moving, repeat the process for the other sphere (though you could probably simplify that equation to get some more efficient math).

This is just back-of-the-napkin math, but it seems to give the correct results. And, hey, I once derived Euler angles on my own, so sometimes my back-of-the-napkin math actually works out.

This also assumes perfectly elastic collisions.

If I'm incorrect, I'd be happy to find out where :)

kyoryu
Well, physics kind of *is* my specialty, and although I admire your inventiveness, you are making some mistakes. First, you seem to be adding vectors to scalars (directionless quantities), which is traditionally not allowed. The next sentence is unclear (add to this, subtract from that, then divide *each*.. huh?) and seems to reduce to A-(A+B). This will work in some very special cases, but only there. If you want to have some fun, try some 1d collisions, like the examples in my answer, and try to find a method that works. There's nothing quite like solving one of nature's puzzles!
Beta
@Beta: Thanks for the feedback :)
kyoryu