46
\$\begingroup\$

I need to brush up my trigonometry and hope you can help here with a simple mathematical model. Here is my model so far in the image attached. I am aware that the frame animation has other problems when the ball is moving very fast, but for now I just need to calculate ballDx and ballDy. It is also possible that ballDx = 0 (vertical movement only), but when the ball deflects ballDx may get a different value.

2D collision between ball and the corner edge of a solid unmovable object

\$\endgroup\$
  • 22
    \$\begingroup\$ Is this what they call a "corner case"? \$\endgroup\$ – Andrew Grimm Apr 11 '11 at 2:30
  • 2
    \$\begingroup\$ Definitely, as things go, soon we may employ the theory of relativity to solve it – the problem is getting mass(ive). \$\endgroup\$ – Lumis Apr 13 '11 at 23:18
45
\$\begingroup\$

Note: All of the following assumes the ball's surface is frictionless (so it won't start spinning or rebound differently because it is).

At the moment of collision, the ball will be touching the corner. When solid objects collide, a force will act along the so called surface normal, i.e. perpendicular to the surface at the point of collision.

Since it's a ball, perpendicular to the surface is towards to ball's center. Ok, so we know the direction of the force, what about its magnitude? Assuming an elastic collision (and that the rectangle can't move), the ball must rebound at the same velocity it impacted with.

Let (nDx, nDy) be the velocity after collision, (oDx, oDy) the velocity before collision, and (x,y) the position of the ball at the point of collision. Let's further assume the corner the ball collides with is at (0,0).

Expressing our insights as formulae, we have:

(nDx, nDy) = (oDx, oDy) + c * (x, y)
length (nDx, nDy) = length (oDx, oDy)

Which is equivalent to:

nDx = oDx + c * x
nDy = oDy + c * y
nDx^2 + nDy^2 = oDx^2 + oDy^2

Substituting the first two equations in the last one, we get:

(oDx + c * x)^2 + (oDy + c * y)^2 = oDx^2 + oDy^2

Expanding using the binomial thorem

(a+b)^2 = a^2 + 2ab + b^2 

yields:

oDx^2 + 2 * oDx * c * x + (c * x) ^ 2 + oDy^2 + 2 * oDy * c * y + (c * y) ^ 2 = oDx^2 + oDy^2
2 * oDx * c * x + 2 * oDy * c * y + (c * x) ^ 2 + (c * y) ^ 2 = 0
(2 * oDx * x + 2 * oDy * y) * c + (x^2 + y^2) * c^2 = 0

This quadratic equation for c has two solutions, one of which is 0. Obviously, that's not the solution we are interested in, as generally the direction of the ball will change as a result of the collision. To get the other solution, we divide both sides by c and get:

(2 * oDx * x + 2 * oDy * y) + (x^2 + y^2) * c = 0

That is:

 c = -(2 * oDx * x + 2 * oDy * y) / (x^2 + y^2)

To summarize, we have:

c = -(2 * oDx * x + 2 * oDy * y) / (x^2 + y^2)
nDx = oDx + c * x
nDy = oDy + c * y

Edit: In code:

if (collision) {
    float x = ballX - cornerX;
    float y = ballY - cornerY;
    float c = -2 * (ballDx * x + ballDy * y) / (x * x + y * y);
    ballDx = ballDx + c * x;
    ballDy = ballDy + c * y;
}

A few implementation considerations: While you can approximate (x,y) with the ball's position after the simulation step, this approximation will change the angle of deflection and hence be very noticeable, so your simulation steps need to be very fine (perhaps such that the ball doesn't move more than 1/20 of its diamater per step). For a more accurate solution, you could compute the time the collision occurs, and split that simulation step at that time, i.e. do a partial step until the point of collision, and another partial step for the remainder of the step.

Edit 2: Computing the point of impact

Let r be the radius, (x0, y0) the position and (dx, dy) the velocity of the ball at the beginning of the simulation step. For simplicity, let's further assume that the corner in question is located at (0,0).

We know:

(x,y) = (x0, y0) + (dx, dy) * t

We want

length(x,y) = r

That is

(x0 + dx * t) ^ 2 + (y0 + dy * t) ^ 2 = r^2
x0^2 + 2 * x0 * dx * t + dx^2 * t^2 + y0^2 + 2 * y0 * dy * t + dy^2 * t^2 = r ^ 2
(dx^2 + dy^2) * t^2 + (2 * x0 * dx + 2 * y0 * dy) * t + (x0^2 + y0^2 - r^2) = 0
\____  _____/         \____________  ___________/       \_______  ________/
     \/                            \/                           \/
     a                             b                            c

That is a quadratic equation in t. If its discriminant

D = b^2 - 4 * a * c

is negative, it has no solutions, i.e. the ball will never hit the corner on its present course. Otherwise, its two solutions are given by

t1 = (-b - sqrt(D)) / (2 * a)
t2 = (-b + sqrt(D)) / (2 * a)

We are interested in the time the collision started, which is the earlier time t1.

Your method would become:

    // compute a,b,c and D as given above

    if (D >= 0) {
        t = (-b - sqrt(D)) / (2 * a);
        if (0 < t && t <= ts) {
            // collision during this timestep!

            x = x + t * dx;
            y = y + t * dy;
            ts = ts - t;

            // change dx and dy using the deflection formula 
        }
    }

    x = x + ts * dx;
    y = y + ts * dy;
\$\endgroup\$
  • 1
    \$\begingroup\$ this deserve +1 \$\endgroup\$ – dynamic Apr 10 '11 at 17:09
  • 1
    \$\begingroup\$ Feel free to upvote, then :-) \$\endgroup\$ – meriton - on strike Apr 10 '11 at 17:52
  • 3
    \$\begingroup\$ You say very early that At the moment of collision, the ball will be touching the corner but I don't see a justification of this approximation (and it must be an approximation because it's not true - the ball is touching in two places, neither of which is the corner). \$\endgroup\$ – Peter Taylor Apr 11 '11 at 12:28
  • 1
    \$\begingroup\$ @Peter Taylor: You did notice that the OP has drawn the ball outside the rectangle, and the collision detection formula given in the question assumes this, too? You gotta think outside the box here :-) \$\endgroup\$ – meriton - on strike Apr 11 '11 at 21:35
  • 1
    \$\begingroup\$ Love this answer, but it could use some $\LaTeX$ markup of the math. \$\endgroup\$ – Martin Wickman Apr 13 '11 at 20:44
13
\$\begingroup\$

Here's a visual way of looking at a problem.

The original problem set is circle vs. rectangle (gray in the image below). This is equivalent to point vs. rounded rect (shown in black).

So this is a multi-part problem. You're testing your point collision vs. 4 lines (extruded out from the edge of the box by the radius of the original circle) and 4 circles (at the corners of the rectangle with the same radius of the original circle).

With the rough velocity in your original image, the point will hit the bottom right corner circle. All you have to do is figure out the point on the corner circle that you would hit, calculate the angle of that, and reflect off of it.

enter image description here

I'll leave the derivation of that as an exercise to the reader.

\$\endgroup\$
2
\$\begingroup\$

I'm working on a game and also stuck here. But I guess it goes this way:

enter image description here

There's another view My problem is that I don't know how to quickly calculate the new dx, dy (to me using traditional math requires too many calculations).

\$\endgroup\$
  • \$\begingroup\$ My point of view is different to the one in the 2nd link, because I don't think the new velocity vector depends on the center of the block like that. My brother told me the ball will bounce back to the old direction (dx = -dx && dy = - dy) but I don't think so. \$\endgroup\$ – Risa Apr 10 '11 at 12:06
  • \$\begingroup\$ If the ball hits the corner and ballX distance from cornerX is smaller than 1/4 of ballW then it will bounce back, otherwise it will deflect forward to the right. This is a simple model I am using at the moment, which is not fine tuned to find exact angle. \$\endgroup\$ – Lumis Apr 10 '11 at 12:22
0
\$\begingroup\$

Kinematics is all about choosing the correct, as in most convenient for calculations, frame of reference.

Here we will first define the transformation T that resolves our axes into components parallel (x') and perpendicular (y') to a line between the centre of the ball and the corner. The inverse transformation T* will restore our original coordinate system.

In this new frame of reference, by reflection (and the time and space symmetry of physics), we have the velocity transformation of contact M (a point impulse) as that which reverses the x' component and leaves unchanged the y' component. In matrix terms this is the diagonal matrix with -1 and 1 on the diagonal.

Then the velocity after the collision is simply: V' = T* . M . T . Vo.

The time of impact t is then just the solution for (T . Do) + (X . T . Vo) (t) = r where X is the X-axis projection operator and r is the radius of the ball. Rearranged, we obtain
t = ( r - (T . Do) ) / ( (X . T . Vo) (t) )

This has the distinct advantage of burying all the complex mathematics in rigorously written, tested, and debugged standard graphics libraries. This solution is also identical for 2D and 3D situations - just switch graphics library. Finally, it highlights that one should first think about appropriate frames of reference before tackling any physics problem. There is always the NIH temptation, but in truth that is just a recipe for bugs when more succinct solutions are available.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.