JAVA elastic collision of moving and non moving circles
Asked Answered
R

2

1

I'm trying to write a java mobile application (J2ME) and I got stuck with a problem: in my project there are moving circles called shots, and non moving circles called orbs. When a shot hits an orb, it should bounce off by classical physical laws. However I couldn't find any algorithm of this sort.

The movement of a shot is described by velocity on axis x and y (pixels/update). all the information about the circles is known: their location, radius and the speed (on axis x and y) of the shot.

Note: the orb does not start moving after the collision, it stays at its place. The collision is an elastic collision between the two while the orb remains static

here is the collision solution method in class Shot:

public void collision(Orb o)
{
    //the orb's center point
    Point oc=new Point(o.getTopLeft().x+o.getWidth()/2,o.getTopLeft().y+o.getWidth()/2);
    //the shot's center point
    Point sc=new Point(topLeft.x+width/2,topLeft.y+width/2);

    //variables vx and vy are the shot's velocity on axis x and y
    if(oc.x==sc.x)
    {
        vy=-vy;
        return ;
    }

    if(oc.y==sc.y)
    {
        vx=-vx;
        return ;
    }

    // o.getWidth() returns the orb's width, width is the shot's width

    double angle=0;  //here should be some sort of calculation of the shot's angle
    setAngle(angle);
}

public void setAngle(double angle)
{
    double v=Math.sqrt(vx*vx+vy*vy);
    vx=Math.cos(Math.toRadians(angle))*v;
    vy=-Math.sin(Math.toRadians(angle))*v;
}

thanks in advance for all helpers

Racecourse answered 20/4, 2014 at 9:16 Comment(8)
Its actually pretty easy, because I dont want to type it all out heres what I found online by searching "collision between two circles" gamedevelopment.tutsplus.com/tutorials/…Equilateral
from my understanding this solution is only for a system which both circles are moving. i have tried it in my code and it dindt work as expected, the angles are incorect.Racecourse
the angle calculations should be the same even if one of the circles is not moving. Consider using the same calculation in the tutorial and just ignoring the orbs new velocity. You can also search around online there are tons of resources out there for collision detection.Equilateral
Maybe plasmaphysics.org.uk/programs/coll2d_cpp.htm helps to get the idea, even though it is c++. Still, physics is physics no matter what the coding language is.Ariellearies
@ns47731 i tried exactly what you said, but when you consider the orbs velocity as 0, the equasion becomes illogical: the velocity is always the same no matter what angle the shot is.Racecourse
@Ariellearies i tried using this code but it didnt work out...Racecourse
To get an immobile disk in the collision computations, set its mass to infinity. vobarian.com/collisions seems to be a decent source for the mathematics, even if they too do not mention angular momentum.Appel
see also the related question #22920067Appel
A
1

At the point of collision, momentum, angular momentum and energy are preserved. Set m1, m2 the masses of the disks, p1=(p1x,p1y), p2=(p2x,p2y) the positions of the centers of the disks at collition time, u1, u2 the velocities before and v1,v2 the velocities after collision. Then the conservation laws demand that

0 = m1*(u1-v1)+m2*(u2-v2)
0 = m1*cross(p1,u1-v1)+m2*cross(p2,u2-v2)
0 = m1*dot(u1-v1,u1+v1)+m2*dot(u2-v2,u2+v2)

Eliminate u2-v2 using the first equation

0 = m1*cross(p1-p2,u1-v1)
0 = m1*dot(u1-v1,u1+v1-u2-v2)

The first tells us that (u1-v1) and thus (u2-v2) is a multiple of (p1-p2), the impulse exchange is in the normal or radial direction, no tangential interaction. Conservation of impulse and energy now leads to a interaction constant a so that

u1-v1 = m2*a*(p1-p2)
u2-v2 = m1*a*(p2-p1)
0 = dot(m2*a*(p1-p2), 2*u1-m2*a*(p1-p2)-2*u2+m1*a*(p2-p1))

resulting in a condition for the non-zero interaction term a

2 * dot(p1-p2, u1-u2) = (m1+m2) * dot(p1-p2,p1-p2) * a

which can now be solved using the fraction

b = dot(p1-p2, u1-u2) / dot(p1-p2, p1-p2)

as

a = 2/(m1+m2) * b

v1 = u1 - 2 * m2/(m1+m2) * b * (p1-p2)
v2 = u2 - 2 * m1/(m1+m2) * b * (p2-p1)

To get the second disk stationary, set u2=0 and its mass m2 to be very large or infinite, then the second formula says v2=u2=0 and the first


v1 = u1 - 2 * dot(p1-p2, u1) / dot(p1-p2, p1-p2) * (p1-p2)


that is, v1 is the reflection of u1 on the plane that has (p1-p2) as its normal. Note that the point of collision is characterized by norm(p1-p2)=r1+r2 or

dot(p1-p2, p1-p2) = (r1+r2)^2

so that the denominator is already known from collision detection.


Per your code, oc{x,y} contains the center of the fixed disk or orb, sc{x,y} the center and {vx,vy} the velocity of the moving disk.

  1. Compute dc={sc.x-oc.x, sc.y-oc.y} and dist2=dc.x*dc.x+dc.y*dc.y

    1.a Check that sqrt(dist2) is sufficiently close to sc.radius+oc.radius. Common lore says that comparing the squares is more efficient. Fine-tune the location of the intersection point if dist2 is too small.

  2. Compute dot = dc.x*vx+dcy*vy and dot = dot/dist2

  3. Update vx = vx - 2*dot*dc.x, vy = vy - 2*dot*dc.y

The special cases are contained inside these formulas, e.g., for dc.y==0, that is, oc.y==sc.y one gets dot=vx/dc.x, so that vx=-vx, vy=vy results.

Appel answered 21/4, 2014 at 7:38 Comment(3)
I afraid I'm completely lost here. Though I understand the basic principles you relay on, momentum and energy conservation, I don't know dot() or cross() functions. also what do you mean by p1-p2? arent those points? In addition since v1 is a vector, in addition to its size I need its direction - angle, or v1x and v1y.Racecourse
While one can describe a vector by angle and length, the two coordinates are usually quite sufficient. And in this case, no angle is needed. p,u,v are vectors, a,b,m scalars. dot is the scalar product of vectors. I'll add some detailed steps.Appel
thanks so much! you have no idea how i struggled with this problem!Racecourse
P
0

Considering that one circle is static I would say that including energy and momentum is redundant. The system's momentum will be preserved as long as the moving ball contains the same speed before and after the collision. Thus the only thing you need to change is the angle at which the ball is moving.

I know there's a lot of opinions against using trigonometric functions if you can solve the issue using vector math. However, once you know the contact point between the two circles, the trigonometric way of dealing with the issue is this simple:

dx = -dx; //Reverse direction
dy = -dy;
double speed = Math.sqrt(dx*dx + dy*dy);
double currentAngle = Math.atan2(dy, dx);

//The angle between the ball's center and the orbs center
double reflectionAngle = Math.atan2(oc.y - sc.y, oc.x - sc.x);
//The outcome of this "static" collision is just a angular reflection with preserved speed
double newAngle = 2*reflectionAngle - currentAngle;

dx = speed * Math.cos(newAngle); //Setting new velocity
dy = speed * Math.sin(newAngle);

Using the orb's coordinates in the calculation is an approximation that gains accuracy the closer your shot is to the actual impact point in time when this method is executed. Thus you might want to do one of the following:

  1. Replace the orb's coordinates by the actual point of impact (a tad more accurate)
  2. Replace the shot's coordinates by the position it has exactly when the impact will/did occur. This is the best scenario in respect to the outcome angle, however may lead to slight positional displacements compared to a fully realistic scenario.
Prosperous answered 8/3, 2016 at 8:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.